码率控制(一):理解码率控制模式(x264,x264,vpx)

码率控制(一):理解码率控制模式(x264,x264,vpx)

什么是“码率控制”?它是编码器决定为每帧视频分配多少比特的工具。


视频编码(有损)的目标是尽可能多的节省比特(码率)的同时尽量保持视频质量。码率控制是平衡码率和质量的重要工具。

码率控制有多种方式,你将会了解到"1-pass","2-pass","CBR","VBR","VBV Encoding"和"CRF"等。

下面是不同码率控制模式的简单示例,它告诉你作为终端用户应该在什么时候用什么模式。注意这里不包含RDO的具体细节。

序言:可变码率 VS 固定码率

很多人可能更熟悉音频编码器,尤其是那些经历了MP3年代的人。不过从CD的发展史来说,最开始使用固定码率(Constant Bitrate,CBR)编码,后来发展出了可变码率(Variable Bitrate,VBR)。VBR可以确保在给定限制下使用最少的比特情况下保持最高质量。

简单说,VBR可以使编码器在难编码的地方花费更多比特,在编码简单的地方花费更少比特。对编码来说“难编码”和“容易编码”代表什么呢?通常有大量运动的视频需要更多比特,空间细节丰富和纹理复杂的视频也较难编码。

编码场景有哪些?

选择哪种码率控制模式往往取决于你的应用场景。通常有以下几种常见场景:

  1. 存档:压缩一个文件存到硬盘或网盘上。这时你希望文件编码后质量尽可能好同时码率尽可能低,但是你不关心压缩后文件的具体大小。

  2. 流媒体:你想要通过网络传输一个文件。这是你要确保文件码率不超过网络带宽,或者你需要在不同带宽下提供不同码率的文件。(例如,在网上看视频网络不好时将视频从高清切换到低清)。

  3. 直播流:和2类似,但是你需要尽快编码(实时),并且直播时你无法提前预知视频内容。

  4. 面向设备的编码:例如你想向DVD或蓝光碟上存放文件,你想使文件编码后达到特定大小(正好占满碟片空间)。

了解使用场景可以帮助你选择码率控制模式。

码率控制模式

下面介绍不同的码率控制模式,这些模式基于ffmpeg中的x264x265libvpx编码器。你可以在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 BunnyTears 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

猜你喜欢

转载自blog.csdn.net/Dillon2015/article/details/105825814