碼率控制(一):理解碼率控制模式(x264,x264,vpx)
什麼是“碼率控制”?它是編碼器決定爲每幀視頻分配多少比特的工具。
視頻編碼(有損)的目標是儘可能多的節省比特(碼率)的同時儘量保持視頻質量。碼率控制是平衡碼率和質量的重要工具。
碼率控制有多種方式,你將會瞭解到"1-pass","2-pass","CBR","VBR","VBV Encoding"和"CRF"等。
下面是不同碼率控制模式的簡單示例,它告訴你作爲終端用戶應該在什麼時候用什麼模式。注意這裏不包含RDO的具體細節。
序言:可變碼率 VS 固定碼率
很多人可能更熟悉音頻編碼器,尤其是那些經歷了MP3年代的人。不過從CD的發展史來說,最開始使用固定碼率(Constant Bitrate,CBR)編碼,後來發展出了可變碼率(Variable Bitrate,VBR)。VBR可以確保在給定限制下使用最少的比特情況下保持最高質量。
簡單說,VBR可以使編碼器在難編碼的地方花費更多比特,在編碼簡單的地方花費更少比特。對編碼來說“難編碼”和“容易編碼”代表什麼呢?通常有大量運動的視頻需要更多比特,空間細節豐富和紋理複雜的視頻也較難編碼。
編碼場景有哪些?
選擇哪種碼率控制模式往往取決於你的應用場景。通常有以下幾種常見場景:
-
存檔:壓縮一個文件存到硬盤或網盤上。這時你希望文件編碼後質量儘可能好同時碼率儘可能低,但是你不關心壓縮後文件的具體大小。
-
流媒體:你想要通過網絡傳輸一個文件。這是你要確保文件碼率不超過網絡帶寬,或者你需要在不同帶寬下提供不同碼率的文件。(例如,在網上看視頻網絡不好時將視頻從高清切換到低清)。
-
直播流:和2類似,但是你需要儘快編碼(實時),並且直播時你無法提前預知視頻內容。
-
面向設備的編碼:例如你想向DVD或藍光碟上存放文件,你想使文件編碼後達到特定大小(正好佔滿碟片空間)。
瞭解使用場景可以幫助你選擇碼率控制模式。
碼率控制模式
下面介紹不同的碼率控制模式,這些模式基於ffmpeg中的x264,x265和libvpx編碼器。你可以在ffmpeg文檔找到詳細參數介紹。
注意:編碼器默認不會“填塞”比特。意味着,當編碼簡單的幀時,實際使用比特可能低於設定的比特,這時編碼器不會浪費比特強行達到設定比特。
固定QP(Constant QP,CQP)
量化參數(Quantization Parameter,QP)控制着壓縮大小。QP越大壓縮率越高同時質量越低,QP越小壓縮率越低同時質量越高。在H.264和H.265中,QP的範圍是0-51間的整數。你可以很容易的在x264和x265中設置固定QP來編碼。注意:libvpx沒有固定QP模式。
ffmpeg -i <input> -c:v libx264 -qp 23 <output>
ffmpeg -i <input> -c:v libx265 -x265-params qp=23 <output>
可以參考這個教程瞭解更多QP的作用原理。
除非你明確的知道你想要做什麼,否則不要使用這個模式。採用CQP模式會導致根據場景複雜度不同比特率波動很大,你無法控制實際比特率。
好處:視頻編碼研究。
壞處:幾乎其他所有應用。
平均比特率(Average Bitrate,ABR)
下面是給定編碼器一個目標碼率,編碼器計算如何達到這個碼率:
ffmpeg -i <input> -c:v libx264 -b:v 1M <output>
ffmpeg -i <input> -c:v libx265 -b:v 1M <output>
ffmpeg -i <input> -c:v libvpx-vp9 -b:v 1M <output>
避免使用這個模式!x264的主要開發者之一說你應該永遠不要使用它。爲什麼?因爲編碼器不知道後面還未編碼的內容,所以它不得不猜測如何達到給定碼率。這意味着碼率要一直變化,尤其是在開始時。對於 HAS-type流,這會導致在短時間內質量巨大波動。
ABR不是一種恆定碼率模式而是可變碼率模式。
好處:快速編碼。
壞處:幾乎其他所有應用。
恆定碼率(Constant Bitrate,CBR)
通過設置nal-hrd可以使編碼器強制保持在特定碼率。
ffmpeg -i <input> -c:v libx264 -x264-params "nal-hrd=cbr:force-cfr=1" -b:v 1M -minrate 1M -maxrate 1M -bufsize 2M <output>
輸出文件必須是MPEG-2 TS文件,因爲mp4不支持NAL填充。注意這種模式對於簡單的視頻會浪費帶寬,但是它保證整個流的碼率一致。你可以在這裏找到更多用例。在某些應用中使用這種模式是有意義的,但是你可能希望在可能的時候碼率更低。
對於VP9使用CBR的命令如下:
ffmpeg -i <input> -c:v libvpx-vp9 -b:v 1M -maxrate 1M -minrate 1M <output>
好處:保持恆定碼率;視頻流(例如:Twitch)。
壞處:文檔存儲;高效使用帶寬的場景。
2-Pass Average Bitrate (2-Pass ABR)
如果允許編碼器兩遍(或更多)編碼那麼它就可以預先估計未來還未編碼的內容。它可以在第一遍編碼是計算編碼代價,然後在第二遍編碼是更高效的利用比特。這種模式使得在特定碼率下輸出的質量最好。
對於x264:
ffmpeg -i <input> -c:v libx264 -b:v 1M -pass 1 -f null /dev/null
ffmpeg -i <input> -c:v libx264 -b:v 1M -pass 2 <output>.mp4
對於x265:
ffmpeg -i <input> -c:v libx265 -b:v 1M -x265-params pass=1 -f null /dev/null
ffmpeg -i <input> -c:v libx265 -b:v 1M -x265-params pass=2 <output>.mp4
對於VP9:
ffmpeg -i <input> -c:v libvpx-vp9 -b:v 1M -pass 1 -f null /dev/null
ffmpeg -i <input> -c:v libvpx-vp9 -b:v 1M -pass 2 <output>.webm
這是對流進行編碼的最簡單的方法。但有兩點注意:你不知道最終結果的質量如何,所以你必須進行多次實驗以確保給定的碼率足夠編碼複雜內容。另一點是這種模式碼率可能出現局部峯值,意味着發送能力可能超過客戶端的接受能力。對於碼率的選擇,你可以參考YouTube的推薦設置,但是注意這些都是爲了讓你上傳高質量的照片而優化的,實際中你可以選擇更低的碼率。
好處:達到特定碼率;面向設備的編碼。
壞處:如果你需要快速編碼(例如,直播流)。
Constant Quality (CQ) / Constant Rate Factor (CRF)
CRF可以保持整個視頻流質量恆定。
ffmpeg -i <input> -c:v libx264 -crf 23 <output>
ffmpeg -i <input> -c:v libx265 -crf 28 <output>
ffmpeg -i <input> -c:v libvpx-vp9 -crf 30 -b:v 0 <output>
在H.264和H.265中,CRF取值爲0到51間的整數(和QP類似)。x264默認值是23,x265默認值是28。CRF增減6會導致碼率減半或加倍。對於VP9,CRF取值範圍0到63,推薦值爲15-35。
這種模式缺點是無法確定最終文件的碼率和碼率波動。
好處:文檔存儲;達到儘可能好的質量。
壞處:流媒體;需要特定碼率(或文件大小)。
VBV(Video Buffering Verifier)
對於VBV可以確保碼率不超過某個最大值。這對於流媒體非常有用,你現在可以確定你不會發送比你承諾的更多的比特。VBV可以和2-pass VBR(在兩遍編碼中都使用)或CRF一起使用。
ffmpeg -i <input> -c:v libx264 -crf 23 -maxrate 1M -bufsize 2M <output>
ffmpeg -i <input> -c:v libx265 -crf 28 -x265-params vbv-maxrate=1000:vbv-bufsize=2000 <output>
VP9有類似的模式,不叫VBV,但是原理一樣:
ffmpeg -i <input> -c:v libvpx-vp9 -crf 30 -b:v 2M <output>
如果你在直播流中應用VBV,且你想加速編碼過程,你可以使用-tune zerolatency和-preset ultrafast選項。這會犧牲一部分質量來加速編碼。
在受約束的ABR-VBV中使用這種模式:
ffmpeg -i <input> -c:v libx264 -b:v 1M -maxrate 1M -bufsize 2M -pass 1 -f null /dev/null
ffmpeg -i <input> -c:v libx264 -b:v 1M -maxrate 1M -bufsize 2M -pass 2 <output>
對x265:
ffmpeg -i <input> -c:v libx265 -b:v 1M -x265-params pass=1:vbv-maxrate=1000:vbv-bufsize=2000 -f null /dev/null
ffmpeg -i <input> -c:v libx265 -b:v 1M -x265-params pass=2:vbv-maxrate=1000:vbv-bufsize=2000 <output>
對VP9:
ffmpeg -i <input> -c:v libvpx-vp9 -b:v 1M -maxrate 1M -bufsize 2M -pass 1 -f null /dev/null
ffmpeg -i <input> -c:v libvpx-vp9 -b:v 1M -maxrate 1M -bufsize 2M -pass 2 <output>
如何設置bufsize?這取決於你期望碼率的波動情況。一個好的設置方法是將bufsize設爲maximum rate的兩倍。如果客戶端緩存比較小,設置bufsize等於maxrate。如果你想限制碼流的碼率,設置bufsize爲maximum rate的一半或更小。
好處:帶寬受限的流媒體;直播流(使用CRF,1-pass);VoD流。
壞處:文檔存儲。
對比實驗
下面是不同碼率控制算法的比較。使用Big Buck Bunny和Tears of Steel序列,每個序列截取三段(每段30秒)。使用libx264編碼器,除了碼率控制模式不同外,其他都是默認設置。設置了不同的目標碼率(750,1500,3000,7500kbit/s)和最大碼率(針對VBV)和QP/CRF值(17,23,29,35)。
注意這個實驗並不充分,你可以嘗試更多的序列和使用不同編碼器。
下圖是使用不同碼率控制模式的結果。左邊是3000kbit/s的結果,右邊是7500kbit/s的結果。另兩種結果的圖像差不多,這裏不再展示。每條線代表不同模式下碼流的碼率變化情況。
從BBB1看出,ABR(藍綠色線)和ABR+VBV(紫色線)開始時錯估了視頻複雜度,實際是BBB視頻的開始部分比較平滑,運動比較小只需要很少的比特就可以保證質量。2-pass模式在開始時正確估計了複雜度,起始使用了低碼率節省了帶寬。視頻的後1/3部分,空間細節豐富使得2-pass模式消耗了大量比特,超過了起始節省的比特。
BBB2視頻裏,不同模式實際上比預期要好。但是2-pass的波動還是比其他模式更多。
下面是CQP和CRF的實驗情況,這裏只展示了CRF/CQP爲17和23的結果。CRF的效果更好。
下面是CRF+VBV在不同碼率下的結果。爲CRF選擇合適的目標碼率和最大碼率通常需要多次嘗試,完全取決於視頻源。
翻譯自Understanding Rate Control Modes (x264, x265, vpx)
感興趣的請關注微信公衆號Video Coding