點擊下載 Demo
一、FFmpeg簡介
FFmpeg是一個開源免費跨平臺的視頻和音頻流方案,屬于自由軟件,采用LGPL或GPL許可證(依據(jù)你選擇的組件)。它提供了錄制、轉(zhuǎn)換以及流化音視頻的完整解決方案。它包含了非常先進的音頻/視頻編解碼庫libavcodec,為了保證高可移植性和編解碼質(zhì)量,libavcodec里很多codec都是從頭開發(fā)的。
FFmpeg的名稱來自MPEG視頻編碼標準,前面的“FF”代表“Fast Forward”,F(xiàn)Fmpeg是一套可以用來記錄、轉(zhuǎn)換數(shù)字音頻、視頻,并能將其轉(zhuǎn)化為流的開源計算機程序??梢暂p易地實現(xiàn)多種視頻格式之間的相互轉(zhuǎn)換。
FFmpeg的用戶有Google,F(xiàn)acebook,Youtube,優(yōu)酷,愛奇藝,土豆等。
二、Mac配置FFmpeg環(huán)境
1、安裝homebrew
"homebrew"是Mac平臺的一個包管理工具,提供了許多Mac下沒有的Linux工具等,而且安裝過程很簡單。
如果已安裝則忽略此步驟
打開終端輸入以下命令行:
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
2、安裝FFmpeg
1)利用上面的homebrew安裝FFmpeg:
brew install ffmpeg
2)當命令結(jié)束之后,輸入以下命令(查看你的安裝ffmpeg的信息):
brew info ffmpeg
詳情請參考:Mac 配置FFmpeg環(huán)境
三、iOS集成FFmpeg
1、下載腳本FFmpeg腳本地址
這里使用的是 ffmpeg-3.0 版本
2、編譯FFmpeg-iOS-build-script,獲得FFmpeg靜態(tài)庫文件
打開腳本文件,然后使用終端運行:
./build-ffmpeg.sh
編譯的時間略長,請耐心等待。在Xcode9中可能出會出現(xiàn)先以下編譯錯誤,如沒問題,請忽略
xcrun -sdk iphoneos clang is unable to create an executable file.
C compiler test failed.
If you think configure made a mistake, make sure you are using the latest
version from Git. If the latest version fails, report the problem to the
ffmpeg-user@ffmpeg.org mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "config.log" produced by configure as this will help
solve the problem.
這時只需執(zhí)行以下命令即可,問題鏈接:https://github.com/kewlbear/FFmpeg-iOS-build-script/issues/119
sudo xcode-select --switch /Applications/Xcode.app
3、iOS項目集成FFmpeg
1)上步操作執(zhí)行成功后,會生成FFmpeg-iOS文件,將該文件直接拖到項目中
2)配置頭文件搜索路徑:在工程文件->Bulid Setting->Search Paths->Header Search Paths添加$(SRCROOT)/$(PRODUCT_NAME)/FFmpeg-iOS/include,(請根據(jù)自己實際路徑更改)
3)在工程中新建ffmpeg文件夾,并從ffmpeg-3.0的文件中添加如下文件:
cmdutils_common_opts.h
cmdutils.h及cmdutils.c
config.h在scratch目錄下取個對應(yīng)平臺的
ffmpeg_filter.c
ffmpeg_opt.c
ffmpeg_videotoolbox.c
ffmpeg.h及ffmpeg.c
除了config.h文件外,別的文件均在ffmpeg-3.0源碼目錄中
4)編譯后會報錯,然后根據(jù)提示挨個修復(fù),還需要導(dǎo)入相應(yīng)的依賴庫。
這步比較繁瑣,可以參考demo進行修改,也可以引入demo中的FFmpeg-iOS文件
四、使用FFmpeg轉(zhuǎn)碼
1、FFmpeg使用命令行調(diào)用
1) 如ffmpeg -i /temp.mp3 -y /test.aac 這條指令就是調(diào)用ffmpeg,輸入源(-i)是/temp.mp3文件,輸出到/test.aac,其中-y參數(shù)是若存在則直接覆蓋
2)ffmpeg -i /temp.mp4 -f flv -y /temp.flv 這條指令是輸入一個視頻文件,將文件轉(zhuǎn)碼為h264編碼格式的flv文件,-f參數(shù)是指定目標格式
3)具體FFmpeg能使用哪些指令可以參考官方文檔或如下博客:http://www.cnblogs.com/wainiwann/p/4128154.html
這里舉一個通過FFmpeg將視頻轉(zhuǎn)碼的例子。
/**
轉(zhuǎn)換視頻
@param inputPath 輸入視頻路徑
@param outpath 輸出視頻路徑
@param processBlock 進度回調(diào)
@param completionBlock 結(jié)束回調(diào)
*/
- (void)converWithInputPath:(NSString *)inputPath
outputPath:(NSString *)outpath
processBlock:(void (^)(float process))processBlock
completionBlock:(void (^)(NSError *error))completionBlock {
self.processBlock = processBlock;
self.completionBlock = completionBlock;
self.isBegin = NO;
// ffmpeg語法,可根據(jù)需求自行更改
// !#$ 為分割標記符,也可以使用空格代替
NSString *commandStr = [NSString stringWithFormat:@"ffmpeg!#$-ss!#$00:00:00!#$-i!#$%@!#$-b:v!#$2000K!#$-y!#$%@", inputPath, outpath];
// 放在子線程運行
[[[NSThread alloc] initWithTarget:self selector:@selector(runCmd:) object:commandStr] start];
}
// 執(zhí)行指令
- (void)runCmd:(NSString *)commandStr{
// 判斷轉(zhuǎn)換狀態(tài)
if (self.isRuning) {
NSLog(@"正在轉(zhuǎn)換,稍后重試");
}
self.isRuning = YES;
// 根據(jù) !#$ 將指令分割為指令數(shù)組
NSArray *argv_array = [commandStr componentsSeparatedByString:(@"!#$")];
// 將OC對象轉(zhuǎn)換為對應(yīng)的C對象
int argc = (int)argv_array.count;
char** argv = (char**)malloc(sizeof(char*)*argc);
for(int i=0; i < argc; i++) {
argv[i] = (char*)malloc(sizeof(char)*1024);
strcpy(argv[i],[[argv_array objectAtIndex:i] UTF8String]);
}
// 打印日志
NSString *finalCommand = @"運行參數(shù):";
for (NSString *temp in argv_array) {
finalCommand = [finalCommand stringByAppendingFormat:@"%@",temp];
}
NSLog(@"%@",finalCommand);
// 傳入指令數(shù)及指令數(shù)組
ffmpeg_main(argc,argv);
// 線程已殺死,下方的代碼不會執(zhí)行
}
2、獲取轉(zhuǎn)碼進度條
1) 如果想調(diào)用C里面函數(shù)需要寫一個橋接類,創(chuàng)建任意一個Cocoa Touch Class,點h文件中所有東西都刪除掉,點m中留下頭文件,點h 中可聲明c函數(shù) 在點m中調(diào)用 就能完成C和OC之間的通信
監(jiān)控開始和完成狀態(tài),在C++函數(shù)中調(diào)用OC方法,來傳遞狀態(tài)信息,結(jié)束線程前調(diào)用stopRuning()結(jié)束方法
獲取視頻文件總時間長度,ffmpeg_opt.c的open_input_file方法中會有時長信息ic->duration,為long long int類型數(shù)據(jù)
定時獲取當前進度時間,ffmpeg.c的print_report方法中會輸出Log,從log中獲取當前的進度信息,為char info[1024]類型數(shù)據(jù)
制作進度條,轉(zhuǎn)換百分比為當前進度除以總時長。注意事項:更改進度條的時候,是在非主線程,所以無法更改UI,需要在主線程執(zhí)行更改UI操作
示例請參考Demo中FFmpegConverOC的使用
參考鏈接:
iOS 集成FFmpeg(通過ffmpeg.h進行調(diào)用):http://m.itdecent.cn/p/35ba59292e70
iOS項目中編譯和集成FFmpeg:http://m.itdecent.cn/p/8eef655e1e7c
(iOS) FFmpeg學(xué)習(xí)筆記:http://m.itdecent.cn/p/bdc78b45354c