为什么使用 b 帧不会减少我的视频大小(使用 ffmpeg 和 nvenc)?

为什么使用 b 帧不会减少我的视频大小(使用 ffmpeg 和 nvenc)?

我有这个命令

ffmpeg -i input.mp4 -vcodec h264_nvenc -rc vbr_hq -cq 19 -rc-lookahead:v 32 -preset slow -profile:v main -c:a copy output.mp4

对于我的一分钟测试视频,它会在大约 5 秒内生成一个大约 82.5 MB 的文件。

我尝试添加使用 B 帧的选项:-bf:v 3,但它只会增加约 1.5 秒的编码时间,而文件大小不会改变。B 帧的使用已得到确认ffprobe -show_frames output.mp4 | grep "pict_type"。我遗漏了什么吗?我认为 B 帧应该会减小文件大小。我的显卡是 GeForce GTX 1650 Max-Q,它应该支持它。我的目标是在良好的编码速度下实现视觉无损,所以我使用 GPU 而不是 CPU。文件大小并不是一个大问题,但越小越好。我正在刻录字幕。

为什么使用 B 帧不会减小视频大小?它是否在某种程度上提高了其感知质量(我希望我的设置根本不可能实现)?

几个附加问题:

  1. 我需要吗-rc-lookahead:v 32?我看到它被广泛使用(例如这里),但默认值应该是 40,所以我不确定这个。
  2. -cq 19如果我追求感知无损,我是否真的应该使用这个值?它来自这里但我确实找不到这个值的其他来源。

答案1

在基于硬件的编码器实现中使用 B 帧,特别是 NVENC(无论是 H.264 还是 HEVC 包装器)不会直接影响编码文件的输出大小,其他所有因素保持不变。

B 帧通常会增加处理输出所需的解码器资源,这就是基线配置文件禁用它的原因。

如果您想要明确控制输出大小,则必须根据需要将目标比特率 ( -b:v)、最大比特率 ( -maxrate:v) 和缓冲区大小 ( -bufsize:v) 设置为适当的值。NVENC 的默认值非常高,约为 ~256 kb/s。因此,您必须手动设置上述这些值,或者通过传递 明确取消设置-b:v 0

关于速率控制前瞻 (私有选项-rc-lookahead:v) 的问题,这在与多个 B 帧 (-bf:v n其中n > 2) 结合时非常有用。在这种情况下,编码器将在 0 和您指定的 B 帧数量之间动态选择 B 帧的数量。

实际上,B 帧很棒,因为它们可以提高图像质量,但它们会消耗大量比特率,从而对高运动内容的感知质量 (PQ) 产生负面影响。这是直播等某些应用中需要考虑的一个因素。

请注意,任何形式的加权预测都不能与 NVENC 中的 B 帧结合使用,因此在切换任一选项之前,请仔细权衡您的编码要求。

对于您的工作量,您可以考虑以下两种方法(如上所述,有关比特率控制的注意事项):

1. VBR码率控制下的恒定质量模式: 对于-cq,请注意,当速率控制(通过-rc:vNVENC 切换)设置为 VBR(可变比特率)及其变体时,这将切换为恒定质量编码模式。它使用的尺度是对数的, 为1最高质量模式,51为最低质量模式。 的默认设置0表示自动。

2.恒定量化参数码率控制方式:

constqp此模式要求通过私有编解码器选项明确将速率控制模式设置为,rc:v constqp并且存在参数-qp:v,有效值从 到0。这可以通过分别通过和51设置的最小和最大允许量化值进一步限制。-qmin:v {int}-qmax:v {int}

在我的测试中,我能够使用上述方法 (2) 获得最佳效果,即设置一个恒定量化器并将速率控制方法选择为constqp,如下面两个例子所示:

(a). 使用量化值 0:

ffmpeg -y -i dnce.mkv -vf 'hwupload_cuda=0,yadif_cuda=0:-1:0,scale_cuda=w=1920:h=1080' -c:v h264_nvenc -rc:v constqp -tune:v hq -preset:v p7 -qp:v 0 -b:v 0 -c:a copy nv-test-7.ts

(b). 使用量化值 19:

ffmpeg -y -i dnce.mkv -vf 'hwupload_cuda=0,yadif_cuda=0:-1:0,scale_cuda=w=1920:h=1080' -c:v h264_nvenc -rc:v constqp -tune:v hq -preset:v p7 -qp:v 19 -b:v 0 -c:a copy nv-test-8.ts

在这些情况下,QP 为 0 的编码产生了 8.8 GB 的输出,而后者在 QP 为 19 时产生了 1.3GB 的输出文件。在这两种情况下,输出都必须进行去隔行处理。

我得到最令人困惑的结果是使用恒定质量模式,如上文 (1) 所述:

(a)在VBR模式下使用目标质量等级0:

ffmpeg -y -i dnce.mkv -vf 'hwupload_cuda=0,yadif_cuda=0:-1:0,scale_cuda=w=1920:h=1080' -c:v h264_nvenc -rc:v vbr -tune:v hq -preset:v p7 -cq:v 0 -b:v 0 -c:a copy nv-test-3.ts

(b)在VBR模式下使用目标质量等级19:

ffmpeg -y -i dnce.mkv -vf 'hwupload_cuda=0,yadif_cuda=0:-1:0,scale_cuda=w=1920:h=1080' -c:v h264_nvenc -rc:v vbr -tune:v hq -preset:v p7 -cq:v 19 -b:v 0 -c:a copy nv-test-4.ts

在这种情况下,CQ 设置为 0 和 19 的输出大小分别为 797 和 790MB。

您的里程可能会有所不同,这取决于您的输入文件和正在使用的底层多路复用器,因为 FFmpeg 中的每个多路复用器都有不同的开销等。

注意不要混合和匹配参数,就像我之前的回答一样,这会导致观察结果出现偏差,无法经得起进一步的审查。

相关内容