iOS集成FFmpeg及視頻格式轉(zhuǎn)碼

點擊下載 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之間的通信

  1. 監(jiān)控開始和完成狀態(tài),在C++函數(shù)中調(diào)用OC方法,來傳遞狀態(tài)信息,結(jié)束線程前調(diào)用stopRuning()結(jié)束方法

  2. 獲取視頻文件總時間長度,ffmpeg_opt.c的open_input_file方法中會有時長信息ic->duration,為long long int類型數(shù)據(jù)

  3. 定時獲取當前進度時間,ffmpeg.c的print_report方法中會輸出Log,從log中獲取當前的進度信息,為char info[1024]類型數(shù)據(jù)

  4. 制作進度條,轉(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容