如何在 ffmpeg 中使用 nvenc 进行 CRF 编码?

如何在 ffmpeg 中使用 nvenc 进行 CRF 编码?

这是我当前将视频(1080p)大小从 2GB 调整到 300MB 的命令,但这需要花费大量时间:

mkdir newfiles  
for %%a in ("*.mp4") do ffmpeg -i "%%a" -c:v  libx264 -preset slow -crf 21 -c:a aac -b:a 128k -vf scale=678:-2 "newfiles\%%~na.mp4"  
pause

我尝试使用 NVIDIA GTX1070 运行 nvenc:

mkdir newfiles  
for %%a in ("*.mp4") do ffmpeg -i "%%a" -c:v h264_nvenc -preset slow -c:a aac -b:a 128k -vf scale=678:-2 "newfiles\%%~na.mp4"  
pause

输出大小始终是原始大小的 3⨉ 或 5⨉ – nvenc 不使用-crf

那么,如何使用 nvenc 和 ffmpeg 来转换/调整高质量、小尺寸的视频?我应该使用 GPU 进行编码吗?

答案1

对于基于 CRF 的编码,将以下代码片段中的以下参数传递给 FFmpeg,假设您使用的是最新版本(目前):

-c:v h264_nvenc -preset:v p7 -tune:v hq -rc:v vbr -cq:v 19 -b:v 0 -profile:v high

建议将 CQ 值固定为 19,因为它在视觉上与 0 相同,但保留了与文件大小之间的良好压缩权衡。请参阅写下关于 CRF 的更多信息。

请注意,该-cq尺度是对数的,这意味着 0 基本上是无损的,而 51 则是绝对最差的。

可以通过添加以下选项来进一步提高质量B 帧(最多限制为 3,并且这需要 H.264 主配置文件及以上版本)。

基线配置文件不支持 B 帧。要启用 B 帧,请将其传递-bf {uint}给视频编码器,这样编码器将使用 4 个 B 帧,并且编码器可以通过私有编解码器选项(范围在 32-40 之间-bf:v 4)选择性地启用前瞻功能来动态调整此帧。-rc-lookahead:v nn

这里的关键部分是-cq:v 19-rc:v vbr参数,它们允许您在遵守 CRF 值 19 的同时,使用 VBR 速率控制中的恒定质量模式调整编码器。

现在,关于 NVENC 的一些小注释,以及对其进行调整以实现高质量编码:

NVENC 与任何其他基于硬件的编码器一样,存在一些限制,特别是对于 HEVC,以下是已知的限制:

  1. 关于 Pascal:

对于 HEVC 编码,存在以下限制:

  • 不支持 32 以上的 CTU 大小。
  • HEVC 中的 B 帧也不受支持。
  • NVENC 编码器支持的纹理格式限制了编码器可以使用的色彩空间。目前,我们支持 4:2:0(8 位)和 4:4:4(10 位)。不支持 4:2:2 10 位等无关格式。这将影响需要此类色彩空间的一些工作流程。
  • 前瞻控制也限制为 32 帧。你可能需要查看请参阅编辑以了解更多详情。

图灵具有 Pascal 的所有增强功能,并增加了对 HEVC 的 B 帧支持以及使用 B 帧作为参考的能力。请参阅回答有关此功能的一个示例。

  1. 在 Maxwell Gen 2 (GM200x 系列 GPU) 上:

HEVC 编码缺少以下功能:

对 Maxwell 的影响在于,由于缺少前瞻功能和自适应样本偏移 (SAO) 环路滤波功能,在比特率受限的情况下,使用 HEVC 进行运动密集的场景可能会出现伪影(块状效应)。Pascal 和 Turing 在这方面有所改进,但根据视频编码器所用 SDK 的版本,并非所有功能都可用。

例如,Pascal 上 H.264 编码的加权预测模式需要 NVENC SDK 8.0x 及以上版本,并且此编码模式还将禁用 B 帧支持。同样,Nvidia Performance Primitives (NPP) 上运行的基于硬件的缩放器与 NVENC 的组合可能会为视频缩放应用程序带来性能改进,但代价是缩放伪影,尤其是对于放大的内容。这同样会影响视频编码管道,因为 NPP 的缩放功能在 GPU 上的 CUDA 核心上运行,因此,应逐案分析额外负载带来的性能影响,以确定性能质量权衡是否可以接受。

请记住这一点:基于硬件的编码器总是会比等效的基于软件的实现提供较少的定制,因此,您的里程和可接受的输出质量总是会有所不同。

使用 FFmpeg 中当前的 NVENC 编码器包装器实现,请注意,现在可以根据目标工作负载使用可调参数覆盖有效预设。请参阅回答如何实现这一点,如上面给出的例子所示。

供您参考:

使用 FFmpeg,您可以随时通过以下方式参考编码器的设置进行自定义:

ffmpeg -h encoder {encoder-name}

因此,对于基于 NVENC 的编码器,您可以运行:

ffmpeg -h encoder=hevc_nvenc

ffmpeg -h encoder=h264_nvenc

您还可以通过运行以下命令查看所有基于 NVENC 的编码器和基于 NPP 的缩放器(如果构建):

for i in encoders decoders filters; do
    echo $i:; ffmpeg -hide_banner -${i} | egrep -i "npp|cuvid|nvenc|cuda"
done

我的测试平台上的示例输出:

encoders:
 V..... h264_nvenc           NVIDIA NVENC H.264 encoder (codec h264)
 V..... nvenc                NVIDIA NVENC H.264 encoder (codec h264)
 V..... nvenc_h264           NVIDIA NVENC H.264 encoder (codec h264)
 V..... nvenc_hevc           NVIDIA NVENC hevc encoder (codec hevc)
 V..... hevc_nvenc           NVIDIA NVENC hevc encoder (codec hevc)
decoders:
 V..... h263_cuvid           Nvidia CUVID H263 decoder (codec h263)
 V..... h264_cuvid           Nvidia CUVID H264 decoder (codec h264)
 V..... hevc_cuvid           Nvidia CUVID HEVC decoder (codec hevc)
 V..... mjpeg_cuvid          Nvidia CUVID MJPEG decoder (codec mjpeg)
 V..... mpeg1_cuvid          Nvidia CUVID MPEG1VIDEO decoder (codec mpeg1video)
 V..... mpeg2_cuvid          Nvidia CUVID MPEG2VIDEO decoder (codec mpeg2video)
 V..... mpeg4_cuvid          Nvidia CUVID MPEG4 decoder (codec mpeg4)
 V..... vc1_cuvid            Nvidia CUVID VC1 decoder (codec vc1)
 V..... vp8_cuvid            Nvidia CUVID VP8 decoder (codec vp8)
 V..... vp9_cuvid            Nvidia CUVID VP9 decoder (codec vp9)
filters:
 ... hwupload_cuda     V->V       Upload a system memory frame to a CUDA device.
 ... scale_npp         V->V       NVIDIA Performance Primitives video scaling and format conversion

答案2

对于-crf来自 libx264 的替换可能是-cq-qp来自 h264_nvenc:

-crf选择恒定质量模式的质量

-cq设置 VBR 速率控制中恒定质量模式的目标质量级别(0 至 51,0 表示自动)

-qp恒定量化参数速率控制方法(从 -1 到 51)(默认 -1)

最快的硬件加速编码方法:

ffmpeg -hwaccel cuvid -c:v h264_cuvid -resize 640x480 -i input.mp4 -c:v h264_nvenc -cq 21 -c:a copy output.mp4

-resize输入分辨率(在硬件中);不需要使用 ffmpeg 来编译--enable-libnpp过滤scale_npp器。

更多信息:

ffmpeg -h encoder=h264_nvenc

ffmpeg -h denoder=h264_cuvid

答案3

我不是这方面的专家,但我做了大量研究,特别是使用 Nvidia 硬件编码器加速,将蓝光翻录文件存档为与原始翻录文件相比无区别且透明的压缩文件,这些文件包含 HEVC/h.265 视频流。我做这件事时很小心,所以在进行任何特定设置之前,我建议测试每部电影的两个特定部分。我选择的两个部分是电影中最暗的部分和快动作部分。

我在两次测试中都直接播放了音频,但只渲染了大约 1 分钟,原因如下:前瞻需要规定数量的帧,并且比特率会因场景而异。以下是我使用 FFMPEG 测试 1 分钟视频(从 30 分 00 秒到 31 分 00 秒)的方法。

-qp此外,我使用 22、23、24 的 HEVC/h.265测试了文件。我看不出更低的数值有什么区别。高于 24 的数值确实会在黑暗场景、带有发光光的场景或天空从白色到蓝色的平滑渐变中开始出现色带。

ffmpeg -hwaccel auto -ss 00:30:01 -to 00:31:01 -i input.mkv -map 0:v:0 -map 0:a:0 -map 0:s:0 -c copy -c:v hevc_nvenc -rc constqp -qp 24 -b:v 0K -c:a copy output.mkv

分别-map 0对第一个视频、音频和字幕流进行解复用(虽然字幕在技术上不是一个流,但为了简单起见,我将其称为流)并将它们分配给重新复用文件中的第一个流。其余设置已在本页前面说明或可查阅。

做记录:
容器必须是 MKV 才能在字幕中重新混合……无论出于什么原因……我就是无法让 MP4 工作。再说一遍,我在这方面不是专业人士,但我从中得到的结果非常好。

在我检查了 1 分钟的测试文件并喜欢所看到的内容后,我继续处理没有的电影-ss 00:30:01 -to 00:31:01。我建议您在查看文件时逐帧播放 1 分钟的渲染。

答案4

.......-rc constqp -qp 21 来自 FFMPEG 的消息 所选预设已弃用。使用 p1 到 p7 + -tune 或快速/中速/慢速。FFMPEG 2023/feb。

以下是最新信息,表明 2020 年 7 月版的链接没有损坏https://developer.nvidia.com/blog/introducing-video-codec-sdk-10-presets/ 我正在使用 -preset 'slow' -b:v 0,它在 65mbit H265 源上推送 20mbits,在 2080 4K 上推送 1.3 倍实时 ~32fps。'hq' 将是我的第二选择,速度要快得多。

相关内容