最近整理一些視頻,我發現太多了,就想把一些本來就需要轉碼的視頻縮小一下。因為轉碼的時候為了彌補損失,我將碼率增大了 10-20%,但是如果將 H264 轉 HEVC(當然也可以是其他格式),那么或許不用增大碼率甚至可以減少碼率。
但是碼率縮小多少好呢?
HEVC 的體積一般是 H264 的 50-80%,但是這個跨度也不小。
肉眼觀察太難評了,而且每次都這樣很麻煩,我就找了一些技術評判方法,來找到合理的縮小值。
FFMPEG 支持 SSIM(Structural Similarity Index,結構相似性指數),可以評估兩個視頻之間的差別。我們就使用這個指標。
在轉碼的時候,我們首先要考慮原視頻的碼率。因為碼率極大的情況下,碼率哪怕只有原來的 5%,效果也不會下降太多。而在低碼率的情況下,下降 50% 就會帶來很大的影響。
其次我們需要考慮我們能接受的損失程度是多少。要做到這點,需要通過實驗,建立 SSIM 和人肉眼看到的情況之間的關系。
SSIM 測試
這里需要說明一下,SSIM 只是一個參考,它只是從某種角度上表示轉碼前后的損失度,重點還是我們肉眼看到的情況。
首先這個測試分兩類:第一次我用 Blackmagic Camera 這個 App 拍攝 220Mbps 碼率的 4K H264 視頻,文件大小 80MB;第二次我截取一個 5700Kbps 1080P 流媒體電影片段,文件大小 100 MB,分別代表兩種可能的情況。
本節轉碼時,編碼均使用顯卡加速。
對比測試命令如下:
ffmpeg -i 第一個文件路徑 -i 第二個文件路徑 -lavfi "[0:v]settb=AVTB,setpts=PTS-STARTPTS[main];[1:v]settb=AVTB,setpts=PTS-STARTPTS[ref];[main][ref]ssim" -f null -
這里我使用的是
-lavfi "[0:v]settb=AVTB,setpts=PTS-STARTPTS[main];[1:v]settb=AVTB,setpts=PTS-STARTPTS[ref];[main][ref]ssim"
,而不是網上常見的-filter_complex ssim
,是因為我的兩個視頻如果用這個會識別錯誤。你可以根據你自己的情況修改一下。
你會看到一個類似編碼的過程,然后看到最終的結果:
SSIM Y:0.986175 (18.593297) U:0.995715 (23.680221) V:0.995205 (23.192565) All:0.989270 (19.693974)
它分別顯示了 YUV 和總共的 SSIM。
可以看到在高碼率的情況下,視頻壓到 10% 碼率的時候曲線才出現了波動,當然在肉眼觀察的時候也發現此處開始,畫質有明顯的下降,比如沒有那么銳利了(由于素材不咋地,就不放截圖了)。
我們把圖表縱軸上下限修改一下,可以更精確的看到變化情況:
當在常見的流媒體碼率下,只要壓到 50% 左右,SSIM 就開始有較大損失,雖然肉眼可以發現畫質損失了,但是不明顯,依舊屬于能看。但是當壓到 10% 的時候,那就很無語了。
注意下圖的上下限和上圖不一樣。
下面第一張是原文件,第二張是 45% 碼率的,第三張是 10% 碼率的。可以看到第三張的畫質損失嚴重:
根據數據可以發現,如果碼率相比 100% 碼率的情況下, SSIM 差距達到 0.01,那么畫質會有肉眼可見的損失。如果達到 0.05 -0.1,那么會有很嚴重的畫質損失。
SSIM 僅供參考
這里再次強調一下,SSIM 只是一個參考,它只是從某種角度上表示轉碼前后的損失度,重點還是我們肉眼看到的情況。不要本末倒置。
比如在一些特殊情況下,兩個完全不同的視頻的 SSIM 可能能達到 0.9 的級別。只不過我們在測試原視頻和轉碼文件的時候這個指標可以當做參考。
同碼率下轉碼一定有損失
首先這種換編碼的轉化一定有損失,那怕不降低碼率甚至提高 20% 的碼率也會有損失,上面的測試中你也可以看到 100% 的時候 SSIM 也不為 1(5700K 測試 為 0.992643,而 220m 的結果為 0.896002)。如果你使用--lossless
可以保證無損,但是碼率會高很多,不劃算。
關于無損轉碼的詳細說明可以看 x265 - readthedocs。
選擇 75% 碼率
根據上面的測試,我們可以看到 50% 左右一定會損失畫質,只是不明顯罷了,但是 50% 到 100% 這區間,可以看到變化不大,我們可以取中間值。
此外,在 Blackmagic Camera App 中, H264 的編碼為 220Mbps,而 HEVC 的編碼為 160Mbps,約為73%。
所以選擇 75% 碼率是一個比較合理的選項。
在完整轉碼一個約 680 MB 的文件視頻后,得到 SSIM 為 0.989270,肉眼可見沒啥區別。證明這個比例是比較合適的,節約了四分之一的體積,雖然小文件沒什么區別,但是 1TB 變成 0.75 TB,還是差距巨大的
H264 轉 HEVC
在使用 FFMPEG 將 H264 轉為 HEVC,請使用以下命令:
ffmpeg -c:v h264_cuvid -i 輸入文件路徑 -c:v hevc_nvenc -b:v 碼率 -tag:v hvc1 輸出文件路徑
解釋一下:
-c:v libx265
:表示使用 libx265 軟件編碼器。-b:v 碼率
:這里設置碼率,需要注意如果是大碼率,比如上面的 220Mbps 這種級別,不要使用220m
,而是應該使用220000k
,因為前者可能會導致轉碼后的碼率非常低,比如我在測試過程中發現,使用220m
轉碼后只有7562 kb/s
,這差距太大了。-tag:v hvc1
:這部分是為了支持 Apple 的 HEVC,不然你轉碼完的視頻會發現無法使用 Mac 等蘋果設備的播放器播放。
如果你需要使用 Nvidia 硬件加速,那么使用以下命令:
ffmpeg -c:v h264_cuvid -i 輸入文件路徑 -c:v hevc_nvenc -b:v 碼率 -tag:v hvc1 輸出文件路徑
解釋一下:
-c:v h264_cuvid
表示使用硬件解碼器。如果你的格式出現問題,那么不要用這個,使用軟件解碼兼容性更高,而且速度沒啥區別,就是 CPU 利用率高。-c:v hevc_nvenc
:表示使用 NVENC 的 HEVC 硬件編碼器。
希望能幫到有需要的人~
參考資料/擴展閱讀
Structural similarity index measure - Wikipedia:SSIM 的維基百科,里面解釋了 SSIM 是如何計算的。
H.265/HEVC Video Encoding Guide - FFMPEG:FFMPEG 官方關于 HEVC 的編碼指南。如果你需要使用 HEVC 編碼,那么建議看看這個指南。
11.237 ssim - FFmpeg Filters Documentation:FFMPEG 關于 SSIM 的文檔。
此外感謝豆包幫我把輸出轉換成表格,方便我制圖。