Mac安裝FFmpeg
1.安裝homebrew
- 打開終端執(zhí)行下面命令
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
2.通過Homebrew 安裝 FFmpeg
- 打開終端,在終端執(zhí)行
brew install ffmpeg
粘招,等待完成即可晶姊。這個過程有點久(# ̄~ ̄#)... - 完成后可驗證下是否安裝成功,在終端執(zhí)行
ffmpeg -version
,顯示如下就安裝成功了。
image.png
iOS下編譯FFmpeg
1.安裝gas-preprocessor
- 后面運行腳本時需要用到gas-preprocessor
- 安裝命令依次執(zhí)行
sudo git clone https://github.com/bigsen/gas-preprocessor.git /usr/local/bin/gas
sudo cp /usr/local/bin/gas/gas-preprocessor.pl /usr/local/bin/gas-preprocessor.pl
sudo chmod 777 /usr/local/bin/gas-preprocessor.pl
sudo rm -rf /usr/local/bin/gas/
2.安裝 yams
- 安裝命令依次執(zhí)行
curl http://www.tortall.net/projects/yasm/releases/yasm-1.2.0.tar.gz -o yasm-1.2.0.gz
tar -zxvf yasm-1.2.0.gz
cd /Users/你的用戶名/yasm-1.2.0
./configure && make -j 4 && sudo make install
3.下載腳本FFmpeg-iOS-build-script.sh
- 執(zhí)行如下命令
git clone https://github.com/kewlbear/FFmpeg-iOS-build-script.git
- 下載完成后,我們在
/Users/你的用戶名
這個路徑下可以看到有個yasm-1.2.0
文件夾??點進(jìn)去找到FFmpeg-iOS-build-script
這個文件夾??再打開build-ffmpeg.sh
使兔,本次使用的是4.2.1版本
image.png - 配置后運行腳本命令如下,等待生成FFmpeg庫藤韵。這個過程也是很久的虐沥,耐心點??♀?整個下來大概843M
/Users/你的用戶名/yasm-1.2.0/FFmpeg-iOS-build-script/build-ffmpeg.sh
-
執(zhí)行完成后會生成如下四個文件夾??
image.png -
如果在運行過程中可能出會出現(xiàn)以下編譯錯誤,如沒問題泽艘,請忽略
image.png - 這時執(zhí)行下面命令后再執(zhí)行上面的腳本即可欲险。
sudo xcode-select --switch /Applications/Xcode.app
iOS下集成FFmpeg
1.新建一個空項目,在Link Binary With Libraries 里添加靜態(tài)庫如下
libz.tbd
libbz2.tbd
libiconv.tbd
CoreMedia.framework
VideoToolbox.framework
AVFoundation.framework
AudioToolbox.framework
2.導(dǎo)入FFmepg庫文件
- 將
FFmpeg-iOS
文件下的include
和lib
拖入項目中
image.png - 設(shè)置
Header Search Paths
路徑悉盆,指向項目中include
目錄
$(SRCROOT)/FFmpeg4.2.1/FFmpeg/include
image.png
- 然后導(dǎo)入
#import "avformat.h"
在代碼中 寫av_register_all()
然后進(jìn)行編譯盯荤,如果沒有報錯,代表編譯成功焕盟。(注意要用真機(jī)運行
)
image.png
iOS運行 FFmpeg Tool
1.把所需文件拖入項目中如下
image.png
-
ffmpeg.c
ffmpeg.h
ffmpeg_opt.c
ffmpeg_filter.c
cmdutils.c
cmdutils.h
ffmpeg_hw.c
ffmpeg_videotoolbox.c
等文件在ffmpeg-4.2.1
文件夾下??
image.png -
config.h
文件 (在scratch
文件夾??下四個文件都有隨意找一個就行了)
2.ffmpeg.c
cmdutils.c
ffmpeg_filter.c
需注釋掉以下無關(guān)代碼
- 頭文件注釋
#include "compat/va_copy.h"
#include "libavresample/avresample.h"
#include "libpostproc/postprocess.h"
#include "libavutil/libm.h"
#include "libavutil/time_internal.h"
#include "libavutil/internal.h"
#include "libavutil/libm.h"
#include "libavformat/network.h"
#include "libavcodec/mathops.h"
#include "libavformat/os_support.h"
#include "libavutil/thread.h"
-
ffmpeg.c
函數(shù)調(diào)用注釋
nb0_frames = nb_frames = mid_pred(ost->last_nb0_frames[0],
ost->last_nb0_frames[1],
ost->last_nb0_frames[2]);
ff_dlog(NULL, "force_key_frame: n:%f n_forced:%f prev_forced_n:%f t:%f prev_forced_t:%f -> res:%f\n",
ost->forced_keyframes_expr_const_values[FKF_N],
ost->forced_keyframes_expr_const_values[FKF_N_FORCED],
ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_N],
ost->forced_keyframes_expr_const_values[FKF_T],
ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_T],
res);
-
cmdutils.c
文件里print_all_libs_info
函數(shù)以下兩行注釋掉也可以全部注釋掉
PRINT_LIB_INFO(avresample, AVRESAMPLE, flags, level);
PRINT_LIB_INFO(postproc, POSTPROC, flags, level);
image.png
- 其它
ffmpeg_opt.c
文件里以下兩行注釋掉
{ "videotoolbox_pixfmt", HAS_ARG | OPT_STRING | OPT_EXPERT, { &videotoolbox_pixfmt}, "" },
{ "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX },
3.下面錯誤秋秤,可在頭部導(dǎo)入#include "pthread.h"
image.png
4.解決main函數(shù)重復(fù)問題
- 把
ffmpeg.c
里面的main
改成如下
image.png
優(yōu)化集成后的問題
1.計數(shù)器置零問題 (ffmpeg.c的代碼中會訪問空屬性導(dǎo)致程序崩潰)
- 找到
ffmpeg.c
中的ffmpeg_cleanup
函數(shù)改成如下
nb_filtergraphs=0;
nb_output_files=0;
nb_output_streams=0;
nb_input_files=0;
nb_input_streams=0;
image.png
2.命令執(zhí)行結(jié)束崩潰問題
第一種方法
- FFmpeg 默認(rèn)執(zhí)行完會執(zhí)行
exit_program
方法結(jié)束進(jìn)程,而iOS下只能啟動一個進(jìn)程脚翘,如果默認(rèn)不做處理灼卢,執(zhí)行完一條命令后app就自動退出了,所以需要處理下来农。 - 在
ffmpeg.c
的ffmpeg_main
函數(shù)中鞋真,把所有調(diào)用exit_program
函數(shù) ,改為調(diào)用ffmpeg_cleanup
函數(shù)就可以了沃于。到這一步就可以使用FFmpeg給我們提供的命令啦(〃'▽'〃)
第二種方法
- 在
cmdutils.c
中的exit_program
函數(shù)改成如下
image.png
iOS 調(diào)用 FFmpeg Tool
1.FFmpeg命令簡介
ffmpeg [global_options] {[input_file_options] -i input_url} ... {[output_file_options] output_url} ...
2.常見參數(shù)
參數(shù) | 備注 |
---|---|
-i | 輸入要處理的視頻文件路徑 |
-r | 指定幀率涩咖,即1s內(nèi)的幀數(shù) |
-s | 指定分辨率 |
-b:v 2500k | 指定輸出文件的視頻比特率為 2500kbit/s |
-vf | 指定視頻過濾器 |
-an | 指定去除對音頻的影響 |
-vn | 指定去除對視頻的影響 |
-sn | 指定去除對字幕的影響 |
-dn | 指定去除對數(shù)據(jù)流的影響 |
-y | 覆蓋輸出 |
-codec: copy | 復(fù)制所有流而無需重新編碼 |
-ss | 指定從什么時間開始 |
-t | 指定需要截取多長時間 |
3.FFmpeg 命令示例更多參考文檔
//水印字幕合成
ffmpeg -i fromName -i fromOther -filter_complex [0:v][1:v]overlay=0:H-h:enable='between(t,0,1)'[tmp];[tmp][1:v]overlay=0:H-h:enable='between(t,3,4)' -t 7 -y -strict -2 toName
//多路視頻輸出 四宮格
ffmpeg -i /Users/mac/Desktop/1.mp4 -i /Users/mac/Desktop/2.mp4 -i /Users/mac/Desktop/3.mp4 -i /Users/mac/Desktop/4.mp4 -filter_complex "[0:v]pad=iw*2:ih*2[a];[a][1:v]overlay=w[b];[b][2:v]overlay=0:h[c];[c][3:v]overlay=w:h" /Users/mac/Desktop/out.mp4
//圖片轉(zhuǎn)視頻
ffmpeg -r 15 -f image2 -loop 1 -i /Users/mac/Desktop/1.png -s 1920x1080 -t 3 -vcodec mpeg4 /Users/mac/Desktop/test.mp4
//去掉視頻中的音頻
ffmpeg -i input.mp4 -vcodec copy -an output.mp4
//視頻分解為圖片
ffmpeg –i test.mp4 –r 1 –f image2 image-%3d.jpg
//視頻拼接
ffmpeg -f concat -i filelist.txt -c copy output.mp4
// 旋轉(zhuǎn)視頻
ffmpeg -i input.mp4 -vf rotate=PI/2 output.mp4
// 縮放視頻
ffmpeg -i input.mp4 -vf scale=iw/2:-1 output.mp4
//視頻變速
ffmpeg -i input.mp4 -filter:v setpts=0.5*PTS output.mp4
//音頻變速
ffmpeg -i input.mp3 -filter:a atempo=2.0 output.mp3
//視頻添加水印(main_w-overlay_w-10 視頻的寬度-水印的寬度-水印邊距)
ffmpeg -i input.mp4 -i logo.jpg -filter_complex [0:v][1:v]overlay=main_w-overlay_w-10:main_h-overlay_h-10[out] -map [out] -map 0:a -codec:a copy output.mp4
//截取部分視頻,從[80,60]的位置開始繁莹,截取寬200檩互,高100的視頻
ffmpeg -i in.mp4 -filter:v "crop=80:60:200:100" -c:a copy out.mp4
4.iOS簡單示例
- 因FFmpeg 不支持
asset-library://
協(xié)議和file://
協(xié)議故必須把需要處理的文件導(dǎo)入到沙盒中處理
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
#import <AVKit/AVKit.h>
#import "FFmpegTool.h"
#define DocumentDir [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]
#define BundlePath(res) [[NSBundle mainBundle] pathForResource:res ofType:nil]
#define DocumentPath(res) [DocumentDir stringByAppendingPathComponent:res]
extern int ffmpeg_main(int argc, char * argv[]);
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *progressLabl;
/**
*
*/
@property (nonatomic, strong) AVPlayerViewController *vc;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)click:(UIButton *)sender {
self.progressLabl.text = @"合成中。咨演。闸昨。";
sender.userInteractionEnabled = NO;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSString *imageStr = BundlePath(@"1.jpg");
NSString *videoStr = BundlePath(@"video.mp4");
NSString *outStr = DocumentPath(@"filter.mp4");
NSString *command_str = [NSString stringWithFormat:@"ffmpeg -i %@ -i %@ -filter_complex [1:v]scale=544:960[b];[0:v]scale=iw*min(1080/iw\\,1920/ih):ih*min(1080/iw\\,1920/ih),pad=1080:1920:(1080-iw)/2:(1920-ih)/2[a];[a][b]overlay=(W-w)/2:(H-h)/2 -b:v 2500k -s 1920x1080 -aspect 9:16 -y %@",imageStr,videoStr,outStr];
NSMutableArray *argv_array = [command_str componentsSeparatedByString:(@" ")].mutableCopy;
int argc = (int)argv_array.count;
char **argv = calloc(argc, sizeof(char*));
for(int i=0; i<argc; i++)
{
NSString *codeStr = argv_array[i];
argv_array[i] = codeStr;
argv[i] = (char *)[codeStr UTF8String];
}
ffmpeg_main(argc, argv);
dispatch_async(dispatch_get_main_queue(), ^{
sender.userInteractionEnabled = YES;
self.progressLabl.text = @"合成成功";
NSURL *webVideoUrl = [NSURL fileURLWithPath:outStr];
self.vc= [[AVPlayerViewController alloc] init];
self.vc.player = [[AVPlayer alloc] initWithURL:webVideoUrl];
[self presentViewController:self.vc animated:YES completion:^{
[self.vc.player play];
}];
});
});
}
@end