前言
FFMPEG是特別強(qiáng)大的專門用于處理音視頻的開源庫(kù)。你既可以使用它的API對(duì)音視頻進(jìn)行處理,也可以使用它提供的工具,如ffmpeg,ffplay,ffprobe,來編輯你的音視頻文件。
本文將簡(jiǎn)要介紹一下FFMPEG庫(kù)的基本目錄結(jié)構(gòu)及其功能,然后詳細(xì)介紹一下我們?cè)谌粘9ぷ髦校绾问褂胒fmpeg提供的工具來處理音視頻文件。
FFMPEG 目錄及作用
libavcodec: 提供了一系列編碼器的實(shí)現(xiàn)。
libavformat:實(shí)現(xiàn)了流協(xié)議,容器格式及基本IO訪問。
libavutil:包括了hash器,解碼器和各類工具函數(shù)
libavfilter:提供了各種音視頻過濾器
libavdevice:提供了訪問捕獲設(shè)備和回放設(shè)備的接口
libswresample:實(shí)現(xiàn)了混音和重采樣
libswscale:實(shí)現(xiàn)了色彩轉(zhuǎn)換和縮放功能。
FFMPEG基本概念
在說ffmepg命令之前,我們先要介紹一些音視頻格式的基本概念
音/視頻流
在音視頻領(lǐng)域,我們把一路音/視頻成為一路流。如我們小時(shí)候經(jīng)??吹腣CD,在里面可以選擇粵語或者國(guó)語聲音,其實(shí)就是CD視頻文件中存放了兩路音頻流,用戶選擇其中一路進(jìn)行播放。
容器
我們一般把MP4、FLV、MOV等文件格式稱之為容器。也就是在這些常用格式文件中,可以存放多路音視頻文件。以MP4為例,就可以存放一路視頻流,多路字幕流。
channel
channel是音頻中的概念,稱之為聲道。在一路音頻流中,可以有單聲道、雙聲道和立體聲。
FFMPEG命令
我們安裝使用的目的可以將FFMPEG命令分成一下幾類:
- 基本信息查詢命令
- 錄制
- 分解/復(fù)用
- 處理原始數(shù)據(jù)
- 濾鏡
- 切割與合并
- 圖/視轉(zhuǎn)換
- 直播相關(guān)
除了FFMPEG的基本信息查詢命令外,其它命令都桉下圖所示的流程處理音視頻

然后將編碼的數(shù)據(jù)包傳送給解碼器(除非為數(shù)據(jù)流選擇了流拷貝,請(qǐng)看進(jìn)一步描述)。解碼器產(chǎn)生未壓縮的幀(原始視頻/PCM音頻/...),可以通過濾波進(jìn)一步處理(見下一節(jié))。在過濾之后,幀被傳送到編碼器,編碼器并輸出編碼的數(shù)據(jù)包,最后,這些傳遞給復(fù)用器,將編碼的數(shù)據(jù)包寫入輸出文件。
默認(rèn)情況下,ffmpeg只包含輸入文件中每種類型(視頻、音頻、字幕)的一個(gè)流,并將其添加到每個(gè)輸出文件中,它根據(jù)一下標(biāo)準(zhǔn)挑選每一個(gè)的‘最佳’:對(duì)于視頻,它是具有最高分辨率的流;對(duì)于音頻:它是具有最多channel的流,對(duì)于字幕,是第一個(gè)字幕流。在相同類型的幾個(gè)流相等的情況下,選擇具有最低索引的流。
您可以通過-vn/-an/-sn/-dn選項(xiàng)來禁用某些默認(rèn)配置。要進(jìn)行全面的手動(dòng)控制,請(qǐng)使用-map選項(xiàng),該選項(xiàng)禁用剛描述的默認(rèn)值。下面我們就來詳細(xì)介紹一下這些命令。
基本信息查詢命令
FFMPEG可以使用下面的參數(shù)進(jìn)行基本信息查詢。例如,想查詢一下現(xiàn)在使用的FFMPEG都支持哪些filter,就可以用ffmpeg-filters來查詢。詳細(xì)參數(shù)說明如下:
-version 顯示版本。
-formats 顯示可用的格式(包括設(shè)備)
-demuxers 顯示可用的demuxers.
-muxers 顯示可用的muxers.
-devices 顯示可用的設(shè)備
-codecs 顯示libavcoder已知的所有編解碼器。
-decoders 顯示可用的解碼器
-encoders 顯示可用的編碼器
-bsfs 顯示可用的比特流filter.
-formats 顯示可用的格式
-protocols 顯示可用的協(xié)議
-filters 顯示可用的過濾器
-pix_fmts 顯示可用的像素格式
-sample_fmts 顯示可用的采樣格式
-layouts 顯示channel名稱和標(biāo)準(zhǔn)channel布局。
-colors 顯示識(shí)別的顏色名稱
命令基本格式及參數(shù)
下面是FFMPEG的基本命令格式:
ffmpeg[global_options]{[input_file_options] -i input_url} ...
{[output_file_options]output_url} ...
ffmepg通過-i選項(xiàng)讀取任意數(shù)量的輸入“文件”(可以是常規(guī)文件,管道,網(wǎng)絡(luò)流,抓去設(shè)備等,并寫入任意數(shù)量的輸出“文件)。
原則上,每個(gè)輸入/輸出 ”文件”都可以包含任意數(shù)量的不同類型的視頻流(視頻/音頻/字幕/附件/數(shù)據(jù))。流的數(shù)量和/或類型是由容器格式來限制。選擇從哪個(gè)輸入進(jìn)入到哪個(gè)輸出將自動(dòng)完成或使用-map選項(xiàng)。
要引入選項(xiàng)中的輸入文件,您必須使用他們的索引(從0開始)。例如:第一個(gè)輸入文件是0,第二個(gè)輸入文件是1,等等。類似地,文件內(nèi)的流被他們的索引引用。例如:2:3是指第三個(gè)輸入文件中的第四個(gè)流。
上面就是FFMPEG處理音視頻的常用命令,下面是一些常用參數(shù):
主要參數(shù)
-f fmt(輸入/輸出)強(qiáng)制輸入或輸出文件格式。格式通常是自動(dòng)檢測(cè)輸入文件,并從輸出文件的文件擴(kuò)展名中猜測(cè)出來,所以在大多數(shù)情況下這個(gè)選項(xiàng)是不需要的。
-i url(輸入) 輸入文件的網(wǎng)址
-y(全局參數(shù))覆蓋輸出文件而不詢問
-n(全局參數(shù))不要覆蓋輸出文件,如果指定的輸出文件已經(jīng)存在,請(qǐng)立即退出,
-c[:stream_specifier]codec(輸入/輸出,每個(gè)流)選擇一個(gè)編碼器(當(dāng)在輸出文件之前使用)或解碼器(當(dāng)前文件之前使用時(shí))用于一個(gè)或多個(gè)流。codec是解碼器/編碼器的名稱或copy(僅輸出)以指示該流不被重新編碼。如:ffmpeg -i INPUT -map 0 -c:v libx264 -c:a copy OUTPUT
-codec[:stream_specifier]編解碼期(輸入/輸出,每個(gè)流)同-c
-t duration (輸入/輸出)當(dāng)用作輸入選項(xiàng)(在-i之前)時(shí),限制從輸入文件讀取的數(shù)據(jù)的持續(xù)時(shí)間。當(dāng)用作輸出選項(xiàng)時(shí)(在輸出url之前),在持續(xù)時(shí)間到達(dá)持續(xù)時(shí)間之后停止輸出
-ss 位置(輸入/輸出)當(dāng)用作輸入選項(xiàng)時(shí)(在-i之前),在這個(gè)輸入文件中尋找位置。請(qǐng)注意,在大多數(shù)格式中年,不可能精確搜索,因此ffmpeg將在位置之前尋找最近的搜索點(diǎn)。當(dāng)轉(zhuǎn)碼和-accurate_ seek被啟用時(shí)(默認(rèn)),搜索點(diǎn)和位置之間的這個(gè)額外的分段將被解碼和丟棄。當(dāng)進(jìn)行流失式復(fù)制或使用-no accurate_seek時(shí),他將被保留。當(dāng)作輸出選項(xiàng)(在輸出url之前)時(shí),解碼但丟棄輸入,直到時(shí)間戳到達(dá)位置。
-frames[:stream_specifier]framecount(output,per-stream)停止在幀計(jì)數(shù)幀之后寫入流
-fulter[:stream_specifier]filtergraph(output,per-stream)創(chuàng)建由filtergraph指定的過濾器圖,并使用它來過濾流。filtergraph是用于流的filtergraph的描述,并且必須具有相同類型的流的單個(gè)輸入和單個(gè)輸出。在過濾器圖形中,輸入與標(biāo)簽中的標(biāo)簽相關(guān)聯(lián),標(biāo)簽中的輸出與標(biāo)簽相關(guān)聯(lián)。有關(guān)filtergraph語法的更多信息,請(qǐng)參閱ffmpeg-filters手冊(cè)。
視頻參數(shù)
-vframes num(輸出)設(shè)置要輸出的視頻的數(shù)量,對(duì)于-frames:v,這是一個(gè)過時(shí)別名,您應(yīng)該使用它。
-r[:stream_specifier]fps(輸入/輸出,每個(gè)流)設(shè)置幀率(Hz,分?jǐn)?shù)或縮寫)。作為輸入選項(xiàng),忽略存儲(chǔ)在文件中的任何時(shí)間戳,根據(jù)速率生成新的時(shí)間戳。這與用于-framerate選項(xiàng)不同(它在FFmpeg的舊版本中使用的是相同的)。如果有疑問,請(qǐng)使用-frameerater而不是輸入選項(xiàng)-r.作為輸出選項(xiàng),復(fù)制或丟棄輸入幀以實(shí)現(xiàn)恒定輸出幀頻fps
-s[:stream_specifier]大小(輸入/輸出,每個(gè)流)設(shè)置窗口大小.作為輸入選項(xiàng),這是video_size專用的快捷方式,由某些分幀器識(shí)別,其幀尺寸未被存儲(chǔ)在文件中。作為輸出選項(xiàng),這會(huì)將縮放視頻過濾器插入到相應(yīng)規(guī)律起圖形的末尾。請(qǐng)直接使用比例過濾器將其插入到開頭或其它地方。格式是“wxh”(默認(rèn),與源相同)。
-aspect[:stream_specifier]寬高比(輸出,每個(gè)流)設(shè)置方面指定的視頻顯示寬高比.aspect可以是懸浮點(diǎn)數(shù)字符串,也可以是num:den形式的字符串,其中num和den是寬高比的分子和分母,例如:"4:3","16:9","1.333"和"1.777"是有效的參數(shù)值。如果與-vcodec副本一起使用,則會(huì)影響存儲(chǔ)在容器級(jí)別的寬高比,但不會(huì)影響存儲(chǔ)在編碼幀中的寬高比(如果存在).
-vn(輸出)禁用視頻錄制
-vcodec編解碼器(輸出)設(shè)置視頻編解碼器,這是-codec:v的別名
-vf filtergraph(輸出)創(chuàng)建由filtergraph指定的過濾器圖,并使用他來過濾流。
音頻參數(shù)
-aframes(輸出)設(shè)置要輸出的音頻幀的數(shù)量。這是-frames:a的一個(gè)過時(shí)的別名.
-ar[:stream_specifier]freq(輸入/輸出,每個(gè)流)設(shè)置音頻采樣率。對(duì)于輸出流,它默認(rèn)設(shè)置為相應(yīng)的輸入流的頻率,對(duì)于輸出流,此選項(xiàng)僅適用于音頻捕獲設(shè)備和原始分路由,并映射到相應(yīng)的分路由器選件。
-ac[:stream_specifier]通道(輸入/輸出,每個(gè)流)設(shè)置音頻通道的數(shù)量,對(duì)于輸出流,它默認(rèn)設(shè)置為輸入音頻通道的數(shù)量。對(duì)于輸入流,此選項(xiàng)僅適用于音頻捕獲設(shè)備和原始分路由器,并映射到相應(yīng)的分路由器選件。
-an(輸出)禁用錄音。
-acodec編解碼器(輸入/輸出)設(shè)置音頻編解碼器,這是-codec的別名:a
-sample_fmt[:stream_specifier]sample_fmt(輸出,每個(gè)流)設(shè)置音頻采樣格式。使用-sample_fmt獲取支持的樣本格式列表
-af fiftergraph(輸出)創(chuàng)建由filtergraph指定的過濾器圖,并使用它來過濾流
錄制
首先通過下面的命令查看一下mac上都有哪些設(shè)備。
ffmpeg -f avfoundation -list_devices true -i ""
錄屏
ffmpeg -f avfoundation -i 1 -r 30 out.yuv
-f: 指定使用avfoundation采集數(shù)據(jù)
-i: 指定從哪兒采集數(shù)據(jù),它是一個(gè)文件索引號(hào)。在我的mac上,1代表桌面(可以通過上面的命令查詢?cè)O(shè)備索引號(hào))。
-r:指定幀率,桉ffmpeg官方文檔說-r與-framerate作用相同,但實(shí)際測(cè)試時(shí)發(fā)現(xiàn)不同,-framerate用于限制輸入,而-r用于限制輸出。
錄屏+聲音
ffmepg -f avfoundation -i 1:10 -r 29.97 -c:v libx264 -crf 0 -c:a libfdk_aac -profiler:a aac_he_v2 -b:a 32K out.flv
-i 1:0 冒號(hào)前面的"1"代表的是屏幕索引號(hào),冒號(hào)后面的"0"代表的是聲音索引號(hào)
-c:v與參數(shù)-vcodec一樣,表示視頻編碼器。c是codec的縮寫,v是video的縮寫
-crf 是x264的參數(shù),0表示無損壓縮
-c:a 與參數(shù)-acodec一樣,表示音頻編碼器。
-profile是fdk_aac的參數(shù)。aac_he_v2表示使用AAC_HE_v2壓縮數(shù)據(jù)
-b:a 制定音頻采樣率,b是bitrate的縮寫,a是audio的縮寫
錄視頻
ffmpeg -framerate 30 -f avfoundation -i 0 out.mp4
-framerate 限制視頻的采集幀率,這個(gè)必須要根據(jù)提示要求進(jìn)行設(shè)置,如果不設(shè)置就會(huì)報(bào)錯(cuò)。
-f 指定使用avfoundation采集數(shù)據(jù)
-i 指定視頻設(shè)備的索引號(hào)
視頻+音頻
ffmepg -framerate 30 -f avfoundation -i 0:0 out.mp4
錄音
ffmpeg -f avfoundation -i:0 out.wav
錄制音頻裸數(shù)據(jù)
ffmpeg -f avfoundation -i:0 -ar 44100 -f s16le out.pcm
分解與復(fù)用
流拷貝是通過將copy參數(shù)提供給-codec選項(xiàng)來選擇流的模式,它使得ffmpeg省略了?指定流的解碼和編碼步驟,所以它只能進(jìn)行多路分解和多路復(fù)用。這對(duì)于更改容器的格式或修改容器級(jí)元數(shù)據(jù)很有用,在這種情況下,上圖將簡(jiǎn)化為:

由于沒有解碼或編碼,速度非???,沒有質(zhì)量損失,但是,由于許多因素,在某些情況下可能無法正常工作,應(yīng)用過濾器顯然也是不可能的,因?yàn)檫^濾器處理未壓縮的數(shù)據(jù)。
抽取音頻流
ffmpeg -i input.mp4 -acodec copy -vn out.aac
acodec: 指定音頻編碼器,copy指明只拷貝,不做編解碼。
vn:c 代表視頻,n代表no也就是無視頻的意思。
抽取視頻流
ffmpeg -i input.mp4 -vcodec copy ano out.h264
vcodec:指定視頻編碼器,copy指明只拷貝,不做編解碼。
an: a代表視頻,n代表no,也就是無視頻的意思。
轉(zhuǎn)格式
ffmpeg -i out.mp4 -vcodec copy -acodec copy out.flv
上面的命令表示的是音頻,視頻都是直接copy,只是將mp4的封裝格式轉(zhuǎn)成了flv.
音頻合并
ffmpeg -i out.h264 -i out.aac -vcodec copy -acodec copy out.mp4
處理原始數(shù)據(jù)
提取YUV數(shù)據(jù)
ffmpeg -i input.mp4 -an -c:v rawvideo -pixel_foramt yuv420p out.yuv
ffplay -s wxh out.yuv
-c:v rawvideo 指定將視頻轉(zhuǎn)成原始數(shù)據(jù)
-pixel_format yuv420p 指定轉(zhuǎn)換格式為yuv420p