FFmpeg全名是Fast Forward MPEG(Moving Picture Experts Group),為開源的影音多媒體處理框架,可以進行影音的解碼、編碼、編碼轉換、混合、抽取、串流和濾鏡,無論影音格式是從哪個地方出來的,從過去到現在的影音格式它幾乎都能夠支援。當然,它也可以利用libvpx這款VP8的官方編碼器來進行VP8編碼。



libvpx官方有提供指令工具vpxenc來操作libvpx,但基於它無法同時處理音訊的原因,我們很少會直接使用它,而是會透過其它前端的介面來使用它的libvpx函式庫。一般來說,使用libvpx進行影片編碼會選擇使用--end-usage參數設定編碼模式,有VBR(變動位元率)、CBR(固定位元率)和CQ(Constrained Quality, 約束品質)三種編碼模式能選;--cq-level參數設定CQ模式的品質等級,數值愈低畫質愈高(位元率相對愈高);--target-bitrate用來設定VBR和CQ模式時位元率的最大值,或是CBR模式時位元率的固定值。此外,vpxenc還提供--best--good--rt--cpu-used參數來控制影片壓縮效果,原則上--cpu-used的數值愈小就會愈慢,而有更好的壓縮效果。--best--good--rt其實分別是--deadline=best--deadline=good--deadline=rt的簡寫。--rt即Read Time,會將--cpu-used的數值,代入以下公式,來限制CPU使用率,換句話說CPU效能愈強,壓縮效果愈好。

#{{{
\text{CPU使用率} = {100 \times { 16 - \text{cpu-used} \over 16}} \text{%}
}}}#

使用FFmpeg指令工具來操作libvpx編碼器時,vpxenc--cq-level參數會對應到FFmpeg的-crf參數,數值範圍為4 ~ 63;--target-bitrate參數會對應到FFmpeg的-b:v(-vb)參數,預設值是200k--deadline參數會對應到FFmpeg的-deadline參數,預設值為good--cpu-used參數會對應到FFmpeg的-cpu-used參數,預設值是1

--deadline參數設為best時,--cpu-used參數無作用;當--deadline參數設為good時,--cpu-used參數的有效數值範圍是0 ~ 5;當--deadline參數設為rt時,--cpu-used參數的有效數值範圍是0 ~ 15。

透過FFmpeg輸出最大位元率為3Mbps的VP8影片的指令如下:

ffmpeg -i 輸入的影音檔案路徑 -vcodec libvpx -b:v 3M 輸出的影音檔案路徑

但如果不是要將影片用於網路直播串流(Live Streaming)的話,不是很建議使用這樣的方式來進行VP8影片的編碼。

CQ與二次編碼(2-pass)

替FFmpeg傳入-crf參數,即可使用VP8的CQ編碼模式。不過libvpx的CQ編碼模式有點特別,如果只用它來進行一次編碼的話,那麼它就算是恆定量化(Constant Quantizer),也就是不管場景多複雜,都用同樣的品質等級來編碼。但如果進行二次編碼,CQ編碼模式就算是真正的CRF(Constant Rate Factor)模式,可以根據場景的複雜度來微調品質等級。雖然二次編碼很耗時,但能有效地降低位元率,同時提升畫質。

在這個模式下,-b:v參數依然可以用來設定位元率上限。如果不想設定位元率上限,可以代入0。要注意的是,如果不設定-b:v參數,最大位元率會被預設為200k

透過FFmpeg輸出標準畫質的VP8影片的指令如下:

ffmpeg -i 輸入的影音檔案路徑 -vcodec libvpx -b:v 0 -crf 12 輸出的影音檔案路徑

使用最高的壓縮效果來輸出標準畫質的VP8影片的指令如下:

ffmpeg -i 輸入的影音檔案路徑 -vcodec libvpx -b:v 0 -crf 20 -deadline best 輸出的影音檔案路徑

若是進行二次編碼的話,第一次編碼的目的是收集編碼影片來源時所得到的資訊(預設會在工作目錄中被存成ffmpeg2pass-0.log檔案),第二次是利用已收集到的資訊和相同的影片來源的不同場景重新用微調過的品質等級進行編碼。

在原本的編碼指令加上-pass 1參數表示要進行第一次編碼;-pass 2參數表示要進行第二次編碼。

例如要使用最高的壓縮效果來輸出標準畫質的VP8影片,第一次編碼的指令如下:

ffmpeg -i 輸入的影音檔案路徑 -vcodec libvpx -b:v 0 -crf 20 -deadline best -pass 1 -an -sn 輸出的影音檔案路徑

以上指令,另外用了-an-sn參數使FFmpeg不要去處理音軌和字幕軌。第一次編碼時並不會真正地輸出影片。

第二次編碼的指令如下:

ffmpeg -i 輸入的影音檔案路徑 -vcodec libvpx -b:v 0 -crf 20 -deadline best -pass 2 -y 輸出的影音檔案路徑

以上指令,另外用了-y參數來覆蓋第一次編碼所輸出的空檔案。

此外,只用-b:v參數設定最大位元率而不設-crf參數的VBR編碼模式也可以進行二次編碼,使輸出的位元率能更接近最大位元率,提升影片畫質。

例如要輸出最大位元率為3Mbps的VP8影片,第一次編碼的指令如下:

ffmpeg -i 輸入的影音檔案路徑 -vcodec libvpx -b:v 3M -pass 1 -an -sn 輸出的影音檔案路徑

第二次編碼的指令如下:

ffmpeg -i 輸入的影音檔案路徑 -vcodec libvpx -b:v 3M -pass 2 輸出的影音檔案路徑

CBR

雖然VP8有提供CBR編碼模式,可以設定固定位元率讓編碼出來的影片大小能夠被預估。但實際上就算進行二次CBR編碼,編碼出來的影片位元率和目標位元率還是會有一段不小的差距,所以這邊就不介紹了。

透明影片

VP8支援擁有透明層(Alpha Channel)的影片,這類影片經常被使用在網頁上。只要影像來源是擁有透明層(像是PNG或是GIF圖檔)的話,編碼成VP8時,預設的像素格式就會是yuva420p。如果FFmpeg在編碼時出現「Transparency encoding with auto_alt_ref does not work」的訊息,加上-auto-alt-ref 0參數可以解決。

以下是一個透明影片(點擊浮現):