ffmpeg入門到實戰-ffmpeg是怎麼轉碼的?

白狼棧發表於2021-06-28

閱讀目錄

視訊是怎麼被播放的?

我們知道,當下大多數播放器都是基於ffmpeg二次開發的。你有沒有想過,你用播放器開啟一個視訊的時候,是怎麼看到的畫面,怎麼聽到的聲音?

我們用這張圖簡單描繪出視訊被播放的流程。

image

下面稍微解釋下圖中的含義。

  1. 解封裝:播放器將輸入的封裝格式(mp4、mkv)的資料分離,產生音訊流和視訊流兩部分,注意此時這兩部分資料還只是壓縮的資料,類似分流,後面我們也會介紹如何從視訊檔案中抽離出音訊和視訊。
  2. 下一步就是解碼操作了,我們說解碼就是將視訊、音訊壓縮的編碼資料,解碼成為非壓縮的視訊、音訊原始資料。這裡將音訊解碼為pcm格式的資料,將視訊解碼為yuv格式的資料。
  3. 音視訊同步播放:把解封裝和解碼分別拿到的視訊資訊和音視訊資料,傳送給顯示卡和音效卡即可播放。

ffmpeg命令的格式

我們在音視訊基礎概念一文中介紹轉碼的時候,丟擲過一條轉碼的命令,如下

ffmpeg -i input.flv output.mp4

對於ffmpeg命令的基本格式,參考ffmpeg官網

ffmpeg [global_options] {[input_file_options] -i input_url} ... {[output_file_options] output_url} ...

翻譯過來就是

ffmpeg [全域性選項] {[輸入檔案選項] -i 輸入檔案} ... {[輸出檔案選項] 輸出檔案} ...

... 表示一條命令可能會有多個輸入和多個輸出。

比如我們可以通過輸入多個檔案轉碼後輸出多個檔案

ffmpeg -i input1 -i input2 \
    -acodec … -vcodec … output1 \
    -acodec … -vcodec … output2 \
    -acodec … -vcodec … output3

據不完全統計,ffmpeg命令的選項數量就有小几萬,所以不僅要多掌握學習技巧,更多的是多積累經驗,靠死記硬背是完全行不通的。

那麼多的選項,體現在一條命令上,一個基本的通用規則就是:

輸入檔案選項只作用於它後面的第一個輸入檔案,自然,輸出檔案選項也只作用於它後面的第一個輸出檔案。所以是有順序要求的。

全域性選項倒是可以隨便寫,比如有個全域性選項 -y,詢問我們是否要覆蓋輸出,下面兩種寫法都可以

ffmpeg -y -i input.flv output.mp4
ffmpeg -i input.flv -y output.mp4

但是,如果命令很長很長(比如我們前面給的音視訊案例,一條命令甚至都有幾百個字元),類似這種全域性選項,最好寫在輸入檔案前面或者輸出檔案前面。

另外,千萬不要先寫輸出檔案,再寫輸入檔案,至少應該寫完輸入檔案,再寫輸出檔案,比如下面這樣就是不好的寫法

ffmpeg output.mp4 -i input.flv

良好的習慣才是好的開始。

ffmpeg轉碼輸出的過程

ffmpeg -i input.flv output.mp4

還是上面這條簡單的轉碼命令,對於類似這樣的一條命令,對於ffmpeg,又是怎麼處理的呢?

我們用下面這個圖來表示轉碼輸出的過程。

image

具體描述如下

  1. ffmpeg 呼叫一個包含解複用器demuxer的libavformat庫,從輸入檔案中讀取包含編碼的資料包
  2. 然後將編碼的資料包傳遞給解碼器(decoder)(流複製操作忽略該步驟)
  3. 解碼器(decoder)產生未壓縮的幀(即原始幀)可以進一步被濾鏡處理
  4. 接下來,被濾鏡處理的原始資料被傳遞給編碼器(encoder)
  5. 編碼器對傳遞過來的資料進行編碼並輸出編碼資料包
  6. 最後,這些資料被複用器(muxer)寫入輸出檔案。

任何複雜的命令,都必須經過上面這樣的轉碼過程,底層程式碼你可以不看,但是整個過程必須瞭解。

相關文章