iOS開發 iOS整合FFmpeg及視訊格式轉碼

奮鬥吧灬青年發表於2018-08-22

 

點選下載 Demo

一、FFmpeg簡介

FFmpeg是一個開源免費跨平臺的視訊和音訊流方案,屬於自由軟體,採用LGPL或GPL許可證(依據你選擇的元件)。它提供了錄製、轉換以及流化音視訊的完整解決方案。它包含了非常先進的音訊/視訊編解碼庫libavcodec,為了保證高可移植性和編解碼質量,libavcodec裡很多codec都是從頭開發的。

FFmpeg的名稱來自MPEG視訊編碼標準,前面的“FF”代表“Fast Forward”,FFmpeg是一套可以用來記錄、轉換數字音訊、視訊,並能將其轉化為流的開源計算機程式。可以輕易地實現多種視訊格式之間的相互轉換。

FFmpeg的使用者有Google,Facebook,Youtube,優酷,愛奇藝,土豆等。

二、Mac配置FFmpeg環境

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)當命令結束之後,輸入以下命令(檢視你的安裝ffmpeg的資訊):

brew info ffmpeg

詳情請參考:Mac 配置FFmpeg環境

三、iOS整合FFmpeg

1、下載指令碼FFmpeg指令碼地址

這裡使用的是 ffmpeg-3.0 版本

2、編譯FFmpeg-iOS-build-script,獲得FFmpeg靜態庫檔案

開啟指令碼檔案,然後使用終端執行:

./build-ffmpeg.sh

編譯的時間略長,請耐心等待。在Xcode9中可能出會出現先以下編譯錯誤,如沒問題,請忽略

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.

這時只需執行以下命令即可,問題連結:https://github.com/kewlbear/FFmpeg-iOS-build-script/issues/119

sudo xcode-select --switch /Applications/Xcode.app

3、iOS專案整合FFmpeg

1)上步操作執行成功後,會生成FFmpeg-iOS檔案,將該檔案直接拖到專案中

2)配置標頭檔案搜尋路徑:在工程檔案->Bulid Setting->Search Paths->Header Search Paths新增$(SRCROOT)/$(PRODUCT_NAME)/FFmpeg-iOS/include,(請根據自己實際路徑更改)

3)在工程中新建ffmpeg資料夾,並從ffmpeg-3.0的檔案中新增如下檔案:

cmdutils_common_opts.h
cmdutils.h及cmdutils.c
config.h在scratch目錄下取個對應平臺的
ffmpeg_filter.c
ffmpeg_opt.c
ffmpeg_videotoolbox.c
ffmpeg.h及ffmpeg.c
除了config.h檔案外,別的檔案均在ffmpeg-3.0原始碼目錄中

4)編譯後會報錯,然後根據提示挨個修復,還需要匯入相應的依賴庫。

這步比較繁瑣,可以參考demo進行修改,也可以引入demo中的FFmpeg-iOS檔案

四、使用FFmpeg轉碼

1、FFmpeg使用命令列呼叫

1) 如ffmpeg -i /temp.mp3 -y /test.aac 這條指令就是呼叫ffmpeg,輸入源(-i)是/temp.mp3檔案,輸出到/test.aac,其中-y引數是若存在則直接覆蓋

2)ffmpeg -i /temp.mp4 -f flv -y /temp.flv 這條指令是輸入一個視訊檔案,將檔案轉碼為h264編碼格式的flv檔案,-f引數是指定目標格式

3)具體FFmpeg能使用哪些指令可以參考官方文件或如下部落格:http://www.cnblogs.com/wainiwann/p/4128154.html

這裡舉一個通過FFmpeg將視訊轉碼的例子。

/**
 轉換視訊
 
 @param inputPath 輸入視訊路徑
 @param outpath 輸出視訊路徑
 @param processBlock 進度回撥
 @param completionBlock 結束回撥
 */
- (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語法,可根據需求自行更改
    // !#$ 為分割標記符,也可以使用空格代替
    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];
}

// 執行指令
- (void)runCmd:(NSString *)commandStr{
    // 判斷轉換狀態
    if (self.isRuning) {
        NSLog(@"正在轉換,稍後重試");
    }
    self.isRuning = YES;
    
    // 根據 !#$ 將指令分割為指令陣列
    NSArray *argv_array = [commandStr componentsSeparatedByString:(@"!#$")];
    // 將OC物件轉換為對應的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 = @"執行引數:";
    for (NSString *temp in argv_array) {
        finalCommand = [finalCommand stringByAppendingFormat:@"%@",temp];
    }
    NSLog(@"%@",finalCommand);
    
    // 傳入指令數及指令陣列
    ffmpeg_main(argc,argv);
    
    // 執行緒已殺死,下方的程式碼不會執行
}

2、獲取轉碼進度條

1) 如果想呼叫C裡面函式需要寫一個橋接類,建立任意一個Cocoa Touch Class,點h檔案中所有東西都刪除掉,點m中留下標頭檔案,點h 中可宣告c函式 在點m中呼叫 就能完成C和OC之間的通訊

  1. 監控開始和完成狀態,在C++函式中呼叫OC方法,來傳遞狀態資訊,結束執行緒前呼叫stopRuning()結束方法

  2. 獲取視訊檔案總時間長度,ffmpeg_opt.c的open_input_file方法中會有時長資訊ic->duration,為long long int型別資料

  3. 定時獲取當前進度時間,ffmpeg.c的print_report方法中會輸出Log,從log中獲取當前的進度資訊,為char info[1024]型別資料

  4. 製作進度條,轉換百分比為當前進度除以總時長。注意事項:更改進度條的時候,是在非主執行緒,所以無法更改UI,需要在主執行緒執行更改UI操作

示例請參考Demo中FFmpegConverOC的使用


參考連結:
iOS 整合FFmpeg(通過ffmpeg.h進行呼叫):https://www.jianshu.com/p/35ba59292e70
iOS專案中編譯和整合FFmpeg:https://www.jianshu.com/p/8eef655e1e7c
(iOS) FFmpeg學習筆記:https://www.jianshu.com/p/bdc78b45354c



作者:張聰2018
連結:https://www.jianshu.com/p/70b0af4d0ec7
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。

相關文章