由於儲存空間和資料傳輸速度的限制,我們可能沒辦法將錄影設備所錄製到的資訊,或是藉由軟體演算出來的畫面完好無損地保存或是傳送。影片是給人看的,但是人類的眼睛的分辨能力有限,非常細微的訊號差異其實感受不太出來,因此可以使用一些會改變原本影像訊號的方式來將其重新編碼(Encode)成和原始影像訊號看起來差異不大的格式,減少儲存影像訊號所佔用空間和加快傳送影像訊號時的速度,而這種壓縮影像訊號的方式就稱為有損壓縮(Lossy Compression)。有損壓縮影像訊號的方式有很多種,以10-bit的色彩深度來說,常見的格式為H.264、H.265、VP9,另外還有比較後來才出現的AV1格式。有些編碼格式除了可以做有損壓縮外,還可以做無損壓縮(Lossless Compression),將原始的影片畫質完整地保留下來。這篇文章並不會去比較影片編碼格式的畫質優劣,因為相同編碼格式的影片,其畫質可以藉由增加影片的位元率來提高。取而代之地,這邊文章將會實際地去對相同檔案做不同格式的轉檔,並以SSIM(structural similarity)指標為準,來比較在幾乎相同畫質下的不同格式的影片,其位元率的差異如何。



有損影片壓縮

有損影像壓縮的原則

有損(Lossy)影響壓縮,顧名思義就是將影像訊號使用破壞性壓縮,使用較少、有限的資料量來還原出接近原始的影像訊號,以縮小儲存影像訊號所需的空間。

由於影像是給人看的,因此理論上會儘量保留會對人類肉眼比較敏感的資訊,並移除或是減少人類肉眼不敏感的部份。

影片壓縮

一部影片是由很多張影像(影格)所構成,由於這些影像有時間順序,因此在進行影片編碼時,我們不需要將其所有的影像都完整地儲存下來,而是可以藉由計算連續的影格,將其有變動和沒變動的部份分開來儲存,因此沒變動的影像部份,儘管會在多個影格中出現,但也還是只需要儲存一份的資訊就好,如此一來就能把儲存空間節省下來。當然,這樣子做的話也會讓影片在解碼的時候需要去參考前後影像的資料來繪製出目前要播放出來的完整影像。

影片的位元率

影片的位元率直接影響著影片檔案的大小,這點很重要,因為有些人可能會提出這樣無理的要求:「我想要保留影片的位元率,但是要讓影片檔案變小一點。」

實際上影片檔案所需佔用的儲存空間算法如下:

儲存空間 = 平均位元率 * 影片時間長度

單看影片的位元率,即便是使用同一個編碼器所編碼出來的影片,也無法比較出兩個影片的畫質優劣。這是因為影片的壓縮如同上述所提,除了會壓縮單張影像之外,也會針對影像和影像之間的關係進行處理,處理得愈多,位元率自然就愈低,但影片畫質並不會因此下降或是提升。

若要比較相同片源的影片畫質,最好還是參考以下文章來計算重製後的影片和片源的畫質差異程度……數字會說話!

常見的壓縮格式

影片壓縮的格式有許多種,不同的壓縮格式會使用不同的演算法來對影像訊號進行壓縮,影格之間的處理方式也有所不同。愈新的影片編碼格式通常會有愈好的壓縮率,但也需要更久的運算時間來進行編碼和解碼的動作。

MPEG-4

MPEG-4(此處指MPEG-4 Part 2)是MPEG(Moving Picture Experts Group)在1990年代所制定的影片編碼標準,提供多種Profile。代表的編碼器有Xvid和DivX,前者採用GPL開源,更為流通,基於MPEG-4 ASP(Advanced Simple Profile)標準。

H.264

H.264是由多個組織組成的JVT(Joint Video Team)在2000年代所制定的標準,也被分類在MPEG-4之下(MPEG-4 Part 10),也稱為MPEG-4 AVC,可以寫成H.264/AVC。H.264可在相同畫質下提供比過去MPEG-4標準更低的位元率,且支援10-bit編碼(Hi10P)。代表的編碼器為x264。

H.265

H.265是由JVT在2010年代所制定的標準,在MPEG-H之下(MPEG-H Part 2),也稱為MPEG-H HEVC( High Efficiency Video Coding),可在相同畫質下提供比MPEG-4 AVC標準更低的位元率。代表的編碼器為x265。

VP8

由於MPEG系列的格式要商業運用的話都需要繳交授權費用,因此Google和On2 Technologies就在制定了VP8,並在2010年將On2 Technologies收購之後將VP8開源(BSD授權),使其成為可以免費授權使用的高品質影片編碼格式,常與H.264做比較。官方的編碼器為libvpx。

VP9

西元2013年,VP8的後繼格式VP9誕生,可在相同畫質下提供比過去VP8更低的位元率,且支援10-bit編碼(VP9 Profile 2)。官方的編碼器為libvpx。

AV1

AV1是由多個組織組成的開放媒體聯盟(AOMedia)在2018年開發出來的影片編碼格式,其編碼技術主要來自於Google開天窗的VP10(VP9的下一代),因此可以在相同畫質下提供比過去VP9更低的位元率。官方的編碼器為libaom。

影片壓縮格式的優劣

通常愈晚出來的影片格式壓縮效果會愈好,但也會需要更多的運算時間來進行編碼和解碼的動作。像是H.264、H.265、VP9、AV1這樣的格式,它們雖然都有支援10-bit編碼,但若沒有辦法被硬體編碼或解碼的話,就需要用到大量的CPU運算資源透過軟體程式來進行編碼或解碼,在硬體等級比較不好的電腦設備上若無法順暢地編解也等同無用武之地。現階段最流行的10-bit影片編碼格式還是H.265,雖然它不是最好的,但因為它有最多的硬體設備支援,所以是最實用的。

H.264(x264)、H.265(x265)、VP9、AV1的比較

接下來才是本篇文章的重頭戲,筆者將會使用一個解析度為1920x1080、FPS為24、像素格式為yuv420ple、長度為30秒的無損壓縮的片源,來實際對H.264、H.265、VP9和AV1格式進行轉檔測試。

測試用的影片檔

這個測試用的影片檔案來自於這個網站提供的Big Buck Bunny影片逐格PNG檔。筆者下載了其4:30~5:00的片段的圖檔,也就是big_buck_bunny_06480.pngbig_buck_bunny_07200.png,並利用以下指令透過x265編碼成無損壓縮的H.265影片,位元率為194249Kbps。

ffmpeg -r 24 -start_number 06480 -i big_buck_bunny_%05d.png -vcodec libx265 -x265-params lossless=1 -preset veryslow -pix_fmt yuv420p10le out.mp4

可以透過這個連結下載壓製好的檔案。

如果以VP9格式來做無損壓縮的話,使用的指令如下:

ffmpeg -i 'Big Buck Bunny.mp4' -vcodec vp9 -lossless 1 -speed 0 'Big Buck Bunny.webm'

這個以VP9壓縮後的影片,位元率為209155Kbps,約為x265壓製出來的108%。由此可知,10-bit無損壓縮下,x265是比VP9還要好上一點的。

編碼器

為了編碼出不同格式的檔案,筆者使用了多種不同的編碼器,都是透過FFmpeg 4.2.1來操作。列表如下:

  • x264 snapshot-20190211-2245:用來進行H.264的編碼。
  • x265 3.2:用來進行H.265的編碼。
  • libvpx 1.8.1:用來進行VP9的編碼。
  • libaom 1.0.0-20200110:用來進行AV1的編碼。

畫質差異分析工具

為了比較影片檔案之間的畫質差異,筆者使用了FFmpeg來計算PSNR和SSIM(作法可參考這篇文章),也用FFmpeg來擷取影片中的影格畫面,並使用ImageDifferencer 1.0.1來比較影像在壓縮前與壓縮後的差異(可參考這篇文章)。

片源的影格擷取

以下是從片源的第16秒所取得的影格畫面:

vcodec-10bit

使用的FFmpeg指令如下:

ffmpeg -i 'Big Buck Bunny.mp4' -ss 16 -frames:v 1 'Big Buck Bunny.png'

CRF(Constant Rate Factor)和qscale

CRF是x264、x265、libvpx、libaom用來控制影片畫質的參數,數值愈低畫質愈高(位元率相對愈高),x264和x265的CRF範圍都是0~51;libvpx和libaom的CRF範圍是0~63。

若要使用CRF來控制x264和x265的編碼畫質,FFmpeg指令寫法如下:

ffmpeg -i 輸入影片路徑 -vcodec libx264/libx265 -crf 20 -preset veryslow 輸出影片路徑

其中,-preset veryslow參數可以儘可能地在保有相同的畫質下,減少位元率。(如果要讓位元率與畫質擁有極致的比例,可以使用-preset placebo,不過編碼速度會很慢!)

若要使用CRF來控制libvpx-vp9的編碼畫質,FFmpeg指令寫法如下:

ffmpeg -i 輸入影片路徑 -vcodec libvpx-vp9 -b:v 0 -crf 20 -speed 0 輸出影片路徑

其中,-speed 0的功用類似x264和x265的-preset veryslow

若要使用CRF來控制libaom的編碼畫質,FFmpeg指令寫法如下:

ffmpeg -i 輸入影片路徑 -vcodec libaom-av1 -b:v 0 -crf 20 -strict -2 輸出影片路徑

其中,-strict -2是用來允許使用FFmpeg實驗性的功能(因為AV1還是FFmpeg 4.2.1的實驗性功能)。

開始比較

底下將會以先前這篇8-bit影片編碼比較的文章作為基準,針對其中根據SSIM找出的三種畫質等級(視覺無損標準畫質筆者可接受的最低畫質)來將片源分別用x264、x265、VP9、AV1進行有損壓縮,最後再來比較這些SSIM指標相近的影片,其位元率的高低。

視覺無損(#{{ SSIM \approx 0.9925}}#)

「視覺無損」(visually lossless)的畫質,也就是雖然不是真的無損,但人類肉眼看起來的結果是跟片源一模一樣的。x264使用21作為CRF參數值來進行轉檔後,可以得到位元率為2879Kbps的影片。此時的影片與片源的PSNR為46.972455,SSIM為0.992194。

影格擷取如下:

vcodec-10bit

與原始影格的差異如下:

vcodec-10bit

從上圖可以看出x264在壓縮影像的時候會先從丟失邊緣的細節開始。

當x265的CRF參數設為22時,可以得到位元率為2423Kbps的影片。此時的影片與片源的PSNR為40.536643,SSIM為0.973012。

影格擷取如下:

vcodec-10bit

與原始影格的差異如下:

vcodec-10bit

從上圖可以看出x265在壓縮影像的時候也會先從丟失邊緣的細節開始。

當VP9的CRF參數設為22時,可以得到位元率為3955Kbps的影片。此時的影片與片源的PSNR為48.028055,SSIM為0.992675。

影格擷取如下:

vcodec-10bit

與原始影格的差異如下:

vcodec-10bit

從上圖可以猜測出VP9在壓縮影像的時候會均勻地改變整張影像的亮度和色彩,以保留更多的細節。

當AV1的CRF參數設為26時,可以得到位元率為1823Kbps的影片。此時的影片與片源的PSNR為47.767069,SSIM為0.992540。

影格擷取如下:

vcodec-10bit

與原始影格的差異如下:

vcodec-10bit

從上圖可以猜測出AV1在壓縮影像的時候,採取的策略類似x265。

標準畫質(#{{ SSIM \approx 0.9874}}#)

當x264的CRF參數設為25時,可以得到位元率為1823Kbps的影片。此時的影片與片源的PSNR為44.359683,SSIM為0.987000。

當x265的CRF參數設為26時,可以得到位元率為1503Kbps的影片。此時的影片與片源的PSNR為44.960221,SSIM為0.987482。

當VP9的CRF參數設為30時,可以得到位元率為2481Kbps的影片。此時的影片與片源的PSNR為45.331133,SSIM為0.987505。

當AV1的CRF參數設為33時,可以得到位元率為1189Kbps的影片。此時的影片與片源的PSNR為45.217437,SSIM為0.987623。

筆者可接受的最低畫質(#{{ SSIM \approx 0.9728}}#)

CRF太高的話,轉出來的畫質實在是傷眼睛,可以明顯看到影像出現色塊。筆者覺得SSIM約為0.9728時是可接受的最低畫質。

當x264的CRF參數設為31時,可以得到位元率為935Kbps的影片。此時的影片與片源的PSNR為40.536643,SSIM為0.973012。

影格擷取如下:

vcodec-10bit

與原始影格的差異如下:

vcodec-10bit

與視覺無損的影格差異如下:

vcodec-10bit

從上圖可以看出x264在更低的位元率時主要會丟失更多邊緣的細節。

當x265的CRF參數設為32時,可以得到位元率為730Kbps的影片。此時的影片與片源的PSNR為40.991893,SSIM為0.972977。

影格擷取如下:

vcodec-10bit

與原始影格的差異如下:

vcodec-10bit

與視覺無損的影格差異如下:

vcodec-10bit

當VP9的CRF參數設為40時,可以得到位元率為1247Kbps的影片。此時的影片與片源的PSNR為41.482149,SSIM為0.973558。

影格擷取如下:

vcodec-10bit

與原始影格的差異如下:

vcodec-10bit

與視覺無損的影格差異如下:

vcodec-10bit

從上圖可以看出VP9在低位元率的時候並不太會偏重丟失哪方面的細節。

當AV1的CRF參數設為44時,可以得到位元率為570Kbps的影片。此時的影片與片源的PSNR為40.975739,SSIM為0.971974。

影格擷取如下:

vcodec-10bit

與原始影格的差異如下:

vcodec-10bit

與視覺無損的影格差異如下:

vcodec-10bit

結論

在畫質等級為「視覺無損」時,如果x264的位元率是100%,則x265是84.16%,VP9是137.37%,AV1是63.32%。因此在高畫質的情況下,使用x265、AV1都是不錯的選擇。

在畫質等級為「標準畫質」時,如果x264的位元率是100%,則x265是82.45%,VP9是136.09%,AV1是65.22%。因此在標準畫質的情況下,依然還是使用x265、AV1才是不錯的選擇。

在畫質等級為「筆者可接受的最低畫質」時,如果x264的位元率是100%,則x265是78.07%,VP9是133.37%,AV1是60.96%。因此在低畫質的情況下,仍然還是使用x265、AV1才是不錯的選擇。

FFmpeg指令方面,x264可接受的CRF範圍是21~31,x265可接受的CRF範圍是22~32,VP9可接受的CRF範圍是22~40,AV1可接受的CRF範圍是26~44。

另外如果與先前這篇8-bit影片編碼比較的文章對比的話,可以發現在相同SSIM下,10-bit影片的位元率要比8-bit影片還要來得低。