什么是“费率控制”?这是视频编码器在决定给定帧花费多少位时所做的事情。(有损)视频编码的目标是尽可能多地保存位,减少原始输入文件的文件大小,同时保留尽可能多的质量。速率控制是确定尺寸和质量之间权衡的关键步骤。

速率控制有多种形式 - 你会认识到术语“1通”和“2通”,“CBR”和“VBR”,也许你知道“VBV编码”或“CRF”

你为什么要关心?通常情况下,您会看到应用错误类型的速率控制模式或错误比特率的视频编码命令的示例。这篇文章是关于不同模式的简要指南; 它解释了你何时使用哪个,作为最终用户。请注意,这与速率 - 失真优化的细节无关。

序言:变量与恒定比特率

许多人更熟悉音频编码器中的速率控制,特别是像我这样长大的MP3用户。为了翻录我们的CD,我们一直使用恒定比特率(CBR)编码,稍后,可变比特率(VBR)编码出现了。可变比特率确保您在给定约束条件下(由VBR质量级别设置)以尽可能高的质量实现尽可能低的文件大小。

简而言之,VBR允许编码器使用更多位来“编码难以编码的东西”,并为文件中易于压缩的部分保存位。在压缩方面有什么困难和容易的?例如,视频中的大量运动需要更多比特来编码,因为相邻视频帧之间的差异将更大。高空间细节和复杂纹理也很难编码。

你的编码方案是什么?

选择速率控制模式很大程度上取决于您的使用案例。通常,有许多不同的场景都会影响您设计编码管道的方式:

  1. 存档 - 您希望压缩文件以将其存储在存档中,例如在外部硬盘驱动器或网络存储上。文件应尽可能以最低的文件大小保存,但您不关心确切的大小。
  2. 流式传输 - 您希望使用典型的视频点播(VoD)流式解决方案(如HTTP渐进式下载或HTTP自适应流式传输)通过Internet发送文件。您需要确保文件不超过某个比特率,或者您需要以不同的标称比特率提供同一文件的不同表示(对于自适应流
  3. 直播 - 与2.一样,但您希望尽可能快地完成编码,并且您事先不了解内容。
  4. 设备编码 - 您希望将文件放在DVD,蓝光等设备上。您希望确保文件最终具有特定大小。

了解该方案有助于您选择速率控制模式。


速率控制模式

现在,让我们深入了解不同的模式。我将在我的基础上通过流行的H.264和H.265编码器支持的模式后X264X265,以及libvpx,如可用ffmpeg您可以在文档中找到有关编码器支持的选项的更多信息

对于x265,您可能需要编译ffmpeg --enable-libx265对于x265,并非所有参数都可以直接传递,因此您必须使用该-x265-params选项。对于libvpx,需要使用ffmpeg进行编译--enable-libvpx

需要注意的是:默认情况下,像x264这样的编码器不会不必要地“填充”带有位的帧。这意味着如果您有一个非常容易编码的场景,您的比特率可能总是低于您指定的比特率。不要担心这一点 - 请记住,如果浪费的话,达到确切的目标比特率没有意义

恒定QP(CQP)

量化参数控制压缩的用于在帧中的每个宏块的量。较大的值意味着会有更高的量化,更多的压缩和更低的质量。较低的值意味着相反。在H.264中,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背后的想法的更多信息,您可以阅读本教程(如果您不怕某些数学)。

除非你知道自己在做什么并明确想要这个,否则不要使用这个模式!设置固定的QP意味着得到的比特率将根据每个场景的复杂性而变化很大,并且会导致输入视频的编码效率相当低。您可能会浪费空间而无法控制实际比特率。

适用于:视频编码研究
利于:几乎所有其他内容

请注意,Netflix建议使用固定QP编码进行每次点击编码优化,以实现每个场景的最佳编码。然而,这需要对各个编码镜头进行大量处理和仔细组装,因此除非您实现整个框架,否则它不应该是“一刀切”的方法。

平均比特率(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型流媒体,这导致短片段内的巨大质量变化。

不是一个恒定的比特率模式!虽然ABR在技术上是VBR模式,但它并不比指定恒定比特率好多,因为它不能可靠地提供高质量。

适合:快速和脏的编码
坏:几乎任何东西

恒定比特率(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>

输出文件需要是.ts(MPEG-2 TS),因为MP4不支持NAL填充。请注意,如果您的源易于编码,此模式将浪费带宽,但它确保比特率在整个流中保持不变。你会在这里找到更多的笔记在某些应用程序中使用此模式可能有意义,但您通常希望允许流在可能的情况下使用较低的比特率。

对于VP9,您需要这样:

ffmpeg -i <input> -c:v libvpx-vp9 -b:v 1M -maxrate 1M -minrate 1M <output>

适用于:保持恒定的比特率(duh); 视频流(例如Twitch

适合:档案; 有效使用带宽

2通道平均比特率(2通ABR)

允许编码器执行两次(或更多次)使得它可以及时估计前方的内容。它可以计算第一遍中编码帧的成本,然后在第二遍中更有效地使用可用位。这确保了在特定比特率约束下输出质量最佳。

ffmpeg -i <input> -c:v libx264 -b:v 1M -pass 1 -f mp4 /dev/null
ffmpeg -i <input> -c:v libx264 -b:v 1M -pass 2 <output>.mp4

对于x265,替换libx264libx265并在私有选项字段中设置pass选项:

ffmpeg -i <input> -c:v libx264 -b:v 1M -x265-params pass=1 -f mp4 /dev/null
ffmpeg -i <input> -c:v libx264 -b:v 1M -x265-params pass=2 <output>.mp4

对于VP9,它就像x264:

ffmpeg -i <input> -c:v libvpx-vp9 -b:v 1M -pass 1 -f webm /dev/null
ffmpeg -i <input> -c:v libvpx-vp9 -b:v 1M -pass 2 <output>.webm

这是为流式传输编码文件的最简单方法。有两点需要注意:你不知道最终的质量是什么,所以你必须做一些测试,以确保你的比特率实际上足够高,可以用于某些复杂的内容。此模式的另一个缺点是可能存在比特率的本地峰值,这意味着您可能发送超过客户端可以接收的峰值。至于选择的比特率,YouTube的给你的建议对上传设置,但请记住,这些都为有你上传优化的良好品质,所以在实践中,你可以选择较低的比特率,太。

适合:达到某个目标比特率; 设备编码不适合
如果您需要快速编码(例如,直播)

恒定质量(CQ)/恒定速率因子(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)。23是x264的良好默认值,28是x265的默认值。18(或x265为24)应在视觉上透明; 任何更低的东西可能只是浪费文件大小。±6的值将导致原始比特率的大约一半或两倍。对于VP9,CRF可以是0到63.建议值为15-35。

此模式的唯一缺点是您不知道生成的文件大小或比特率的波动。

请注意,具有相同结果比特率的双通和CRF编码应该在质量上相同。主要的区别在于,使用两遍,您可以控制文件大小(如果这是一个要求),而使用CRF,您只需指定所需的质量。

适合:档案; 实现最佳质量

利于:流媒体; 获得一定的比特率/文件大小

约束编码(VBV)

视频缓冲校验提供了一种方法,以保证比特率被限制在一定的最大值。这对于流式传输非常有用,因为您现在可以确定在一定时间范围内不会发送比您承诺的更多的位。VBV既可以用于2遍VBR(在两遍中使用它),也可以用于CRF编码 - 它可以“添加”到已经呈现的速率控制模式。后一种模式也称为“上限CRF”。

使用-maxrate-bufsize选项打开VBV 以设置最大比特率和预期的客户端缓冲区大小:

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>

注意:如果你这样做了直播流应用程序,要加快编码过程中,与x264x265您可以添加-tune zerolatency-preset ultrafast选项。它们会降低某种比特率(即压缩效率)的质量,但会显着加快该过程。因为libvpx-vp9,你想设置-quality realtime-speed 5有关详细信息,请参阅H.264VP9指南

要使用受约束的ABR-VBV编码的此方法:

ffmpeg -i <input> -c:v libx264 -b:v 1M -maxrate 1M -bufsize 2M -pass 1 -f mp4 /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 mp4 /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 webm /dev/null
ffmpeg -i <input> -c:v libvpx-vp9 -b:v 1M -maxrate 1M -bufsize 2M -pass 2 <output>

注意:这里也可以使用一次通过方法 - 根据x264开发人员 - 通常与两次通过一样好,但它不会有效地压缩剪辑。

你应该如何设置bufsize?这取决于您在比特率中需要多少可变性。一个好的默认设置是缓冲区大小是最大速率的两倍,但建议可能会因流设置而异。如果您的客户端缓冲区较小(只需几秒钟),您的bufsize应该与maxrate大小相同。如果要限制流的比特率,请尝试将bufsize设置为最大速率的一半或更低。

当您将VBV应用于CRF编码时,诀窍是找到一个CRF值,该值平均会产生所需的最大比特率,但不会更多。如果您的编码始终“最大化”您的最大比特率,则您的CRF可能设置得太低。在这种情况下,编码器会尝试花费它没有的位。另一方面,如果你有一个高CRF,使比特率不总是达到最大值,你仍然可以降低它以获得一些质量。例如,您在没有 VBV的CRF 18 进行编码您的剪辑最终的平均比特率为3.0 Mbit / s。但是你想要你的VBV设置限制为1.5 Mbit / s,所以你需要将CRF降低到大约24,才能获得一半的比特率。

适用于:带宽限制下的流媒体; 直播(使用CRF,1遍); VoD流媒体(目标比特率,2遍)

利于:想要玩游戏的人; 档案


比较例

这是不同速率控制算法之间的快速比较。我拿了免费的Big Buck BunnyTears of Steel视频序列,并分别选择了三个不同的部分(长度为30秒)。请注意,这些序列是未压缩的原始素材。然后使用libx264及其默认设置对视频进行编码唯一不同的是不同的速率控制模式。我设置了不同的目标比特率(750,1500,3000,7500 kbit / s)和最大速率(VBV)和QP / CRF值(17,23,29,35)。您可以在GitHub上找到用于比较脚本

请注意,这种比较并非详尽无遗或完全具有代表性。通常,您希望尝试各种类型的不同序列以及不同的编码器。我计划在不久的将来更新这些测试。不过,这些测试应该让您了解不同模式的作用。

让我们从不同的比特率控制模式开始。左列为3000 kbit / s,右列为7500 kbit / s。我排除了其他目标比特率,因为它们没有在图表中显示出很大的差异,因为比特率已经处于如此低的水平,以至于编码器没有很多关于如何分配它的选择。这些行是Big Buck Bunny(BBB)和Tears of Steel(ToS)的不同剪辑。该线表示对各个帧大小的LOESS平滑 - 它表示比特率在剪辑持续时间内如何变化。

你可以看到 - 特别是前四个内容 - ABR(绿松石线)和ABR + VBV(紫色)错误地估计了剪辑的复杂性。实际上,Big Buck Bunny序列以淡入,平滑渐变和低运动开始,这意味着压缩它的质量要好不多。2遍方法正确地以较低的比特率开始并节省带宽。视频片段的最后三分之一包含大量空间细节,这使得2遍模式消耗了它在开始时保存的更多位。

对于第二个Big Buck Bunny剪辑,不同的编码模式实际上比预期更好地对齐,尽管再次可见2-pass如何导致比特率比其他模式更极端的变化。

当然,还有一些片段很容易编码(或者复杂程度变化很小)。这里,速率控制模式差别不大。

对于基于质量的模式(CQP和CRF),我只显示CRF / QP 17和23的结果,它们处于质量范围的“好”端(就像3000和7500 kbit / s一样“好”)全高清视频的价值)。曲线的顺序是反向的 - 更低意味着更好的质量:

这里,可以看到与2遍相同的趋势:比特率遵循内容复杂性。但是,对于CRF,它更受限制,在不需要的地方节省了比特。最有趣的情况是左下角:CRF在常数QP上保存比特率,就像它通常那样,但它在恒定偏移中这样做。我不得不猜测为什么会这样 - 也许这篇文章将通过一些进一步的分析进行更新。

通常我们可以看到CRF方法如何很好地匹配内容,只要我们事先知道得到的平均比特率是什么......这就是CRF + VBV发挥作用的地方:

为给定的CRF选择正确的目标/最大比特率通常是猜测工作,完全取决于源视频。但是,正确完成后,您不会过多地限制质量,将其推至极限(如3000 kbit / s和CRF 17的情况)。你也不想让比特率变化太大。CRF 23是默认设置libx264,你可以看到,给定适当的目标比特率设置(如7500 kbit / s),这种编码模式可以让比特率变化到足以解决内容复杂性的差异,仍然保持对VBV的符合性模型。

总结

理解不同的速率控制模式并不容易。不幸的是,最简单的解决方案(仅指定比特率)是根本不推荐的解决方案,但Web使用此方法继续传播代码示例。

总结一下,这是你应该做的,取决于你的用例:

  1. 档案 - CRF,为您提供您想要的品质。
  2.  - 双通CRF或ABR,VBV-比特率。
  3. 实时流式传输 - 一次通过CRF或ABR与VBV的比特率,或CBR,如果你可以浪费比特。
  4. 设备编码 - 通常是两遍ABR。