關(guān)于ffmpeg
關(guān)于ffmpeg盾碗,我們首先需要知道它是什么纽什,ffmpeg官網(wǎng)對ffmpeg進行了定義:
一個針對音視頻的錄制/轉(zhuǎn)換/串流傳輸?shù)目缙脚_解決方案纪岁。
當(dāng)然,在about頁面介紹得更加詳細庇谆,可以說ffmpeg是針對音視頻領(lǐng)域的全能操作框架。在現(xiàn)如今的互聯(lián)網(wǎng)世界中凭疮,關(guān)于音視頻的操作處理饭耳,或直接或間接都會依賴到這個框架(當(dāng)然也有其他音視頻框架)。
怎樣使用ffmpeg
ffmpeg有兩種使用方法:
- 自定義開發(fā)使用
- 命令行使用
因為ffmpeg的音視頻處理能力都封裝在對應(yīng)的庫文件中执解,因此我們再可以在自己的代碼工程中嵌入對應(yīng)的庫文件寞肖,然后就可以調(diào)用它的基礎(chǔ)能力,通過各種組合實現(xiàn)我們想要的功能衰腌,這就是自定義開發(fā)使用新蟆。
而且ffmpeg自身也會把這些功能庫統(tǒng)一封裝并套殼,打包成一個可執(zhí)行文件右蕊,可以接受各種輸入命令栅葡,比如在windows上就是ffmpeg.exe文件,我們可以下載這個可執(zhí)行文件尤泽,然后再命令行窗口執(zhí)行對應(yīng)的命令行代碼欣簇。
命令行
我們以windows平臺為例,在官網(wǎng)下載最新的可執(zhí)行文件坯约,不出意外熊咽,你會下載到三個可執(zhí)行文件,分別是:
- ffmpeg闹丐,用于音視頻進行修改(錄制横殴,采集,裁剪卿拴,轉(zhuǎn)換等)處理的能力
- ffprobe,用于分析音視頻文件的相關(guān)信息
- ffplay衫仑,發(fā)播放音視頻
把文件所在路徑添加到系統(tǒng)路徑即可在命令行窗口進行調(diào)用。
比如查看媒體文件的一些信息
ffprobe -show_streams sample.mp4 // 顯示sample.mp4內(nèi)部的流的信息
比如視頻文件的格式轉(zhuǎn)換
// mp4轉(zhuǎn)換為avi
ffmpeg -i sample.mp4 -c copy output.avi
命令行的參數(shù)和組合形式非常多堕花,具體可以參考官網(wǎng) Command Line Tools Documentation文狱。
也可以先看看阮一峰 FFmpeg 視頻處理入門教程,我認為他的教程都非常詳細且易懂
自定義開發(fā)
自定義開發(fā)則是撇開了ffmpeg的殼,只獲取其內(nèi)部功能實現(xiàn)的庫文件缘挽,把庫文件集成到我們工程中瞄崇,通過調(diào)用ffmpeg提供的API來實現(xiàn)我們自己的功能呻粹,這個會涉及到了c/cpp開發(fā)。
關(guān)于自定義開發(fā)更多細節(jié)就不舉例了苏研,這不是本文的重點等浊,而且后面會專門在ffmpeg的基礎(chǔ)上進行功能開發(fā)。
小結(jié)
相對而言命令行的方式更簡單一些摹蘑,因為命令行相當(dāng)于已經(jīng)提前封裝了一些功能實現(xiàn)的邏輯代碼筹燕,自定義開發(fā)的使用復(fù)雜的多,因為自定義開發(fā)則需要自己實現(xiàn)邏輯衅鹿。但是自定義開發(fā)比較靈活庄萎,而且更適合精細化的,自定義程度較高的那些需求塘安,而且更容易讓我們理解音視頻處理的一些過程糠涛。
其實這兩種使用方式?jīng)]有本質(zhì)區(qū)別,命令行在library之上增加了中間層兼犯,把一些功能實現(xiàn)凝結(jié)為幾個命令參數(shù)以達到簡化開發(fā)的目的忍捡。而自定義則直接拿開中間層,直接接觸library切黔。
ffmpeg的功能模塊
libavcodec
提供音視頻的編解碼能力libavformat
提供處理各種音視頻容器格式的能力砸脊,比如封裝,解封裝libavutil
提供一些實用的功能函數(shù)libavfilter
提供音視頻流的濾鏡效果libavdevice
提供操作輸入和輸出設(shè)備的能力纬霞。例如凌埂,從攝像頭獲取視頻數(shù)據(jù)以及將視頻數(shù)據(jù)輸出到屏幕libswresample
實現(xiàn)音頻混合和重采樣能力libswscale
實現(xiàn)視頻幀的顏色轉(zhuǎn)換和縮放能力
如果使用命令行模式,一般會把上述的庫全部打包起來诗芜,而如果是自定義開發(fā)則是按需使用瞳抓,比如如果不涉及設(shè)備操作可以不要libavdevice,不需要濾鏡功能可以不要libavfilter...
這些支持庫都是跨平臺的伏恐,既可以是動態(tài)庫也可以是靜態(tài)庫孩哑,
ffmpeg的一些基礎(chǔ)概念
time_scale
time_scale 可以稱作時間刻度,具體的含義是把一秒鐘分為多少個刻度
翠桦。
time_scale = 10 // 表示把一秒鐘分為10份横蜒,10個刻度,每個刻度代表1/10秒
time_scale = 1000 // 表示把一秒鐘分為1000份销凑,1000個刻度丛晌,每個刻度代表1/1000秒
time_base
time_base是ffmpeg中一個非常重要的概念,一般稱作時間基斗幼,或者可以說是ffmpeg中的時間基礎(chǔ)單位澎蛛。
現(xiàn)實世界所使用的時間基礎(chǔ)單位一般是是秒,因為秒對于普通人而言已經(jīng)足夠精確了孟岛,使用毫秒或者微秒毫無必要瓶竭,但是在ffmpeg中不是以秒為基礎(chǔ)單位,而是把秒分為若干份渠羞,以一份作為ffmpeg中的時間基礎(chǔ)單位斤贰。
time_base = 1/24 //表示把1s分為24份,以1/24作為ffmpeg的時間的基礎(chǔ)單位次询。
time_base = 1/1000 //表示把1s分為1000份荧恍,以1/1000作為ffmpeg的時間的基礎(chǔ)單位。
ffmpeg中大量的時間表示(AVStram屯吊,AVPacket,AVFrame中的PTS,DTS)送巡,都是以time_base作為基礎(chǔ)單位的,而不是現(xiàn)實時間盒卸。
PTS/DTS/pts_time
-
DTS(Decoding Time Stamp骗爆,解碼時間戳)
- 指示解碼器應(yīng)該在什么時間點開始解碼該幀(解碼順序)
-
PTS(Presentation Time Stamp,顯示時間戳)
- 指示幀應(yīng)該在什么時間點被呈現(xiàn)給用戶蔽介。PTS 是在解碼后確定的時間戳摘投,用于視頻幀或音頻幀的渲染或播放順序。
-
pts_time
- 當(dāng)前媒體幀的顯示時間虹蓄,單位為秒
DTS犀呼,PTS一般都是以time_base為單位的。
關(guān)于pts,pts_time,time_base之間的計算方式
time_base = 1/75;
Frame pts pts_time
0 0 0 x 1/75 = 0.00 (表示該幀在第0秒顯示)
1 3 3 x 1/75 = 0.04 (表示該幀在第0.04秒顯示)
2 6 6 x 1/75 = 0.08 (表示該幀在第0.08秒顯示)
3 9 9 x 1/75 = 0.12 (表示該幀在第0.12秒顯示)
AVStream
在ffmpeg中薇组,讀取或者寫入視頻文件時外臂,內(nèi)部會構(gòu)建一個數(shù)據(jù)結(jié)構(gòu)AVFormatContext,這個結(jié)構(gòu)中包含了視頻的相關(guān)信息律胀,其中一個信息就是AVStram數(shù)組,每一個AVStream都包含了一種數(shù)據(jù)宋光,比如音頻和視頻分別代表一個AVStram結(jié)構(gòu),我們可以從中獲取比如時長炭菌,幀數(shù)跃须,編解碼器信息,time_base等
一旦我們獲取了AVStream娃兽,我們就可以讀取該Stream所代表的數(shù)據(jù)菇民。
AVPacket
在ffmpeg中,在視頻文件讀取到基本信息之后投储,就可以讀取正式數(shù)據(jù)內(nèi)容用于解碼第练,而這個用于解碼的數(shù)據(jù)格式就是AVPacket.
AVPakcet內(nèi)部包括待一段解碼的數(shù)據(jù)data,size,pts,dts玛荞,time_base娇掏,stream_id(表示packet讀取自哪個AVStream)等。
AVFrame
AVFrame則是解碼后的原始數(shù)據(jù)勋眯,表示一個可以被使用幀婴梧,注意這并不一定是視頻幀下梢,也可能是音頻幀,因為視頻和音頻都使用AVFrame的數(shù)據(jù)結(jié)構(gòu)塞蹭。
AVFrame內(nèi)包含可播放數(shù)據(jù)孽江,寬,高(視頻)番电,幀類型(視頻)岗屏,采樣數(shù)(音頻),音頻格式漱办,PTS等
一般如果是視頻这刷,AVFrame表示得是YUV或者RGB圖片;如果是音頻娩井,則AVFrame表示得是PCM數(shù)據(jù)暇屋。
此時的得到的數(shù)據(jù)可以直接被播放。
音視頻同步
在獲得了可用的音頻或者視頻幀之后洞辣,也并不是直接發(fā)送到對應(yīng)的設(shè)備進行播放即可率碾,一般需要我們進行音視頻同步控制,因為會出現(xiàn)音頻和視頻因為各種差異導(dǎo)致獲得可用幀的速度差別很大屋彪,比如視頻很快播放完所宰,但是音頻才播了一點點。因此我們需要通過PTS和time_base來控制每一幀的播放速度畜挥。
至于同步方法仔粥,一般是需要建立一個時間坐標(biāo)系作為參考,然后計算每一幀的顯示時間戳是否對應(yīng)了正確的時間蟹但,否則就等待躯泰。
邏輯流程與數(shù)據(jù)格式轉(zhuǎn)換
根據(jù)上面的對一些數(shù)據(jù)類型的簡單介紹,我們已經(jīng)可以得到一個音頻文件播放過程的邏輯流程了
同樣的华糖,把可播放的原始數(shù)據(jù)保存成文件則是這個過程的逆過程麦向,大同小異。
總結(jié)
本文主要對ffmpeg使用方法客叉,核心模塊诵竭,ffmpeg中的一些基本概念做了介紹,后面將會站在自定義開發(fā)的角度上兼搏,分析ffmpeg的數(shù)據(jù)結(jié)構(gòu)的詳情卵慰,和一個視頻被播放的完整過程實現(xiàn),最終會講講在Android平臺的使用方式佛呻。