iOS集成FFmpeg以及命令行的應(yīng)用

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文件下的includelib拖入項目中
    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.cffmpeg_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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子饵较,更是在濱河造成了極大的恐慌拍嵌,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件循诉,死亡現(xiàn)場離奇詭異横辆,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)打洼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門龄糊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逆粹,“玉大人募疮,你說我怎么就攤上這事∑У” “怎么了阿浓?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蹋绽。 經(jīng)常有香客問我芭毙,道長,這世上最難降的妖魔是什么卸耘? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任退敦,我火速辦了婚禮,結(jié)果婚禮上蚣抗,老公的妹妹穿的比我還像新娘侈百。我一直安慰自己,他們只是感情好翰铡,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布钝域。 她就那樣靜靜地躺著,像睡著了一般锭魔。 火紅的嫁衣襯著肌膚如雪例证。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天迷捧,我揣著相機(jī)與錄音织咧,去河邊找鬼。 笑死漠秋,一個胖子當(dāng)著我的面吹牛笙蒙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播膛堤,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼手趣,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起绿渣,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤朝群,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后中符,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姜胖,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年淀散,在試婚紗的時候發(fā)現(xiàn)自己被綠了右莱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡档插,死狀恐怖慢蜓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情郭膛,我是刑警寧澤晨抡,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站则剃,受9級特大地震影響耘柱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜棍现,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一调煎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧己肮,春花似錦士袄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至戈稿,卻和暖如春西土,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背鞍盗。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工需了, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人般甲。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓肋乍,卻偏偏與公主長得像,于是被迫代替她去往敵國和親敷存。 傳聞我的和親對象是個殘疾皇子墓造,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345