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



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參數,數值範圍為0 ~ 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。不建議使用-deadline best,因為非常慢!

VBR與二次編碼(2-pass)

透過FFmpeg輸出平均位元率為3Mbps的VP9影片的指令如下:

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

如果要讓輸出影片的平均位元率更接近-b:v所設定的位元率,就要使用二次編碼。第一次編碼的目的是收集編碼影片來源時所得到的資訊(預設會在工作目錄中被存成ffmpeg2pass-0.log檔案),第二次是利用已收集到的資訊和相同的影片來源編碼出位元率有被精確控制過的影片。

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

例如輸出平均位元率為3Mbps的VP9影片,第一次編碼的指令如下:

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

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

第二次編碼的指令如下:

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

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

有了比較精確的平均位元率,就可以用以下公式來預估影片輸出後的大小:

#{{{
{ \text{平均位元率(Kbps, Kb/s)} \times \text{時間(s, 秒)} \over \text{8(b/B)} } = \text{影片的大小(KB)}
}}}#

CQ與二次編碼(2-pass)

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

在這個模式下,-b:v參數依然可以用來設定平均位元率。如果不想設定平均位元率,可以代入0。要注意的是,如果不設定-b:v參數,平均位元率會被預設為200k。同時使用-crf參數和非0的平均位元率是一件蠻弔詭的事情,應該是為了避免單純以品質為基準來進行編碼會使得某些場景複雜的片段位元率過高,而不利於網路串流,藉由指定平均位元率,可以在一定程度保有原先的品質設定下,讓影片比較順暢地串流。

透過FFmpeg輸出視覺無損的VP9影片的指令如下:

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

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

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

使用次高的壓縮效果來輸出視覺無損的VP9影片的指令如下:

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

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

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

ffmpeg -i 輸入的影音檔案路徑 -vcodec libvpx-vp9 -b:v 0 -crf 27 -cpu-used 0 -pass 1 -an -sn 輸出的影音檔案路徑

第二次編碼的指令如下:

ffmpeg -i 輸入的影音檔案路徑 -vcodec libvpx-vp9 -b:v 0 -crf 27 -cpu-used 0 -pass 2 輸出的影音檔案路徑

4:2:0/4:2:2/4:4:4和8-bit/10-bit/12-bit影片編碼

預設情況下,FFmpeg使用libvpx來編碼VP9時,會根據影片輸入源來決定輸出的色彩取樣方式和色彩深度。常見的色彩取樣方式為4:2:0(支援硬體解碼),特殊情況下才會去用到4:2:2或是4:4:4。色彩取樣對於畫面的呈現差異並不明顯,但對於後製寬容度的影響比較大。而色彩深度則影響到影片的顏色表現範圍,這個要看影片來源,如果影片原本就是用10-bit深度的設備進行錄製或是製作的話,那麼降轉成8-bit時就會出現色班、色塊等色階不連續的情況。

FFmpeg指令工具可以利用-pix_fmt參數來設定輸出影片的像素格式來決定其色彩取樣方式和像素格式,搭配VP9編碼時,會自動選擇適當的VP9 Profile來使用。

像素格式yuv420p,代表要使用8-bit 4:2:0進行編碼;yuv422p,代表要使用8-bit 4:2:2進行編碼;yuv444p,代表要使用8-bit 4:4:4進行編碼;yuv420p10le,代表要使用10-bit 4:2:0進行編碼;yuv422p10le,代表要使用10-bit 4:2:2進行編碼;yuv444p10le,代表要使用10-bit 4:4:4進行編碼。yuv420p12le,代表要使用12-bit 4:2:0進行編碼;yuv422p12le,代表要使用12-bit 4:2:2進行編碼;yuv444p12le,代表要使用12-bit 4:4:4進行編碼。

透過FFmpeg輸出視覺無損的10-bit VP9影片的指令如下:

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

無損壓縮

VP9支援無損壓縮,加上-lossless 1參數就好了,不要設定-crf-b:v參數。

使用次高的壓縮效果來輸出無損畫質的VP9影片,指令如下:

ffmpeg -i 輸入的影音檔案路徑 -vcodec libvpx-vp9 -lossless 1 -cpu-used 0 輸出的影音檔案路徑

透明影片

VP9支援擁有透明層(Alpha Channel)的影片,這類影片經常被使用在網頁上。只要影像來源是擁有透明層(像是PNG或是GIF圖檔)的話,編碼成VP9時,預設的像素格式就會是yuva420p

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