關(guān)于ffmpeg基礎(chǔ)知識入門

關(guān)于ffmpeg

關(guān)于ffmpeg,我們首先需要知道它是什么,ffmpeg官網(wǎng)對ffmpeg進行了定義:

image.png

一個針對音視頻的錄制/轉(zhuǎn)換/串流傳輸?shù)目缙脚_解決方案。

image.png

當然,在about頁面介紹得更加詳細,可以說ffmpeg是針對音視頻領(lǐng)域的全能操作框架。在現(xiàn)如今的互聯(lián)網(wǎng)世界中,關(guān)于音視頻的操作處理,或直接或間接都會依賴到這個框架(當然也有其他音視頻框架)。

怎樣使用ffmpeg

ffmpeg有兩種使用方法:

  • 自定義開發(fā)使用
  • 命令行使用

因為ffmpeg的音視頻處理能力都封裝在對應的庫文件中,因此我們再可以在自己的代碼工程中嵌入對應的庫文件,然后就可以調(diào)用它的基礎(chǔ)能力,通過各種組合實現(xiàn)我們想要的功能,這就是自定義開發(fā)使用。

而且ffmpeg自身也會把這些功能庫統(tǒng)一封裝并套殼,打包成一個可執(zhí)行文件,可以接受各種輸入命令,比如在windows上就是ffmpeg.exe文件,我們可以下載這個可執(zhí)行文件,然后再命令行窗口執(zhí)行對應的命令行代碼。

命令行

我們以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é)

相對而言命令行的方式更簡單一些,因為命令行相當于已經(jīng)提前封裝了一些功能實現(xiàn)的邏輯代碼,自定義開發(fā)的使用復雜的多,因為自定義開發(fā)則需要自己實現(xiàn)邏輯。但是自定義開發(fā)比較靈活,而且更適合精細化的,自定義程度較高的那些需求,而且更容易讓我們理解音視頻處理的一些過程。

其實這兩種使用方式?jīng)]有本質(zhì)區(qū)別,命令行在library之上增加了中間層,把一些功能實現(xiàn)凝結(jié)為幾個命令參數(shù)以達到簡化開發(fā)的目的。而自定義則直接拿開中間層,直接接觸library。

image.png

ffmpeg的功能模塊

image.png
  • 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,解碼時間戳)

    • 指示解碼器應該在什么時間點開始解碼該幀(解碼順序)
  • PTS(Presentation Time Stamp,顯示時間戳)

    • 指示幀應該在什么時間點被呈現(xiàn)給用戶。PTS 是在解碼后確定的時間戳,用于視頻幀或音頻幀的渲染或播放順序。
  • pts_time

    • 當前媒體幀的顯示時間,單位為秒

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等

image.png

一旦我們獲取了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)等。

image.png

AVFrame

AVFrame則是解碼后的原始數(shù)據(jù),表示一個可以被使用幀,注意這并不一定是視頻幀,也可能是音頻幀,因為視頻和音頻都使用AVFrame的數(shù)據(jù)結(jié)構(gòu)。

AVFrame內(nèi)包含可播放數(shù)據(jù),寬,高(視頻),幀類型(視頻),采樣數(shù)(音頻),音頻格式,PTS等

一般如果是視頻,AVFrame表示得是YUV或者RGB圖片;如果是音頻,則AVFrame表示得是PCM數(shù)據(jù)。

image.png

此時的得到的數(shù)據(jù)可以直接被播放。

音視頻同步

在獲得了可用的音頻或者視頻幀之后,也并不是直接發(fā)送到對應的設(shè)備進行播放即可,一般需要我們進行音視頻同步控制,因為會出現(xiàn)音頻和視頻因為各種差異導致獲得可用幀的速度差別很大,比如視頻很快播放完,但是音頻才播了一點點。因此我們需要通過PTS和time_base來控制每一幀的播放速度。

至于同步方法,一般是需要建立一個時間坐標系作為參考,然后計算每一幀的顯示時間戳是否對應了正確的時間,否則就等待。

邏輯流程與數(shù)據(jù)格式轉(zhuǎn)換

根據(jù)上面的對一些數(shù)據(jù)類型的簡單介紹,我們已經(jīng)可以得到一個音頻文件播放過程的邏輯流程了

image.png

同樣的,把可播放的原始數(shù)據(jù)保存成文件則是這個過程的逆過程,大同小異。

總結(jié)

本文主要對ffmpeg使用方法,核心模塊,ffmpeg中的一些基本概念做了介紹,后面將會站在自定義開發(fā)的角度上,分析ffmpeg的數(shù)據(jù)結(jié)構(gòu)的詳情,和一個視頻被播放的完整過程實現(xiàn),最終會講講在Android平臺的使用方式。

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

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

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