NVIDIA 视频编解码器 SDK v13.0

使用 FFmpeg 和 NVIDIA GPU 硬件加速

所有 NVIDIA® GPU,从 Kepler 世代开始,都支持完全加速的硬件视频编码和解码。在本文档的其余部分中,硬件编码器和硬件解码器分别称为 NVENC 和 NVDEC。

NVENC 和 NVDEC 的硬件功能通过 NVIDIA 视频编解码器 SDK 中的 API(在本文中分别称为 NVENCODE API 和 NVDECODE API)公开,用户可以通过这些 API 访问 NVENC 和 NVDEC 的硬件加速能力。

FFmpeg 是最流行的多媒体转码软件,广泛用于视频和音频转码。NVENC 和 NVDEC 可以有效地与 FFmpeg 一起使用,以显着加快视频解码、编码和端到端转码。

本文档介绍了通过 FFmpeg 在 NVIDIA GPU 上加速视频编码、解码和端到端转码的方法,FFmpeg 使用 NVIDIA 视频编解码器 SDK 中公开的 API。

硬件设置

带有 NVIDIA GPU 加速的 FFmpeg 需要具有 Linux 或 Windows 操作系统以及受支持的 NVIDIA GPU 的系统。

有关受支持 GPU 的列表,请参阅 https://developer.nvidia.com/nvidia-video-codec-sdk

对于本文档的其余部分,假设所使用的系统具有同时具有 NVENC 和 NVDEC 的 GPU。

软件设置

先决条件

FFmpeg 同时支持 Windows 和 Linux。FFmpeg 已经过编译,并在 Microsoft Visual Studio 2013 SP2 及更高版本 (Windows)、MinGW (msys2-x86_64-20161025) (Windows) 和 gcc 4.8 及更高版本 (Linux) 编译器上进行了测试。

FFmpeg 需要单独的 git 存储库 nvcodec-headers 用于 NV 加速的 ffmpeg 构建。

要编译 FFmpeg,必须在系统上安装 CUDA 工具包,尽管运行编译后的 FFmpeg 二进制文件不需要 CUDA 工具包。

在使用 FFmpeg 之前,建议参考 FFmpeg 文档,注意它使用的视频编解码器 SDK 的版本,并确保安装了该版本的视频编解码器 SDK 所需的最低驱动程序。

编译 FFmpeg

FFmpeg 是一个开源项目。下载 FFmpeg 源代码存储库并使用适当的编译器进行编译。

有关构建 FFmpeg 的更多信息,请访问:https://trac.ffmpeg.org/wiki/CompilationGuide

为 Linux 编译

所有 Linux 平台都支持带有 NVIDIA GPU 加速的 FFmpeg。

要在 Linux 上编译 FFmpeg,请执行以下操作

  • 克隆 ffnvcodec
复制
已复制!
            

git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git

  • 安装 ffnvcodec
复制
已复制!
            

cd nv-codec-headers && sudo make install && cd –

  • 克隆 FFmpeg 的公共 GIT 存储库。
复制
已复制!
            

git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg/

  • 安装必要的软件包。
复制
已复制!
            

sudo apt-get install build-essential yasm cmake libtool libc6 libc6-dev unzip wget libnuma1 libnuma-dev

  • 配置
复制
已复制!
            

./configure --enable-nonfree --enable-cuda-nvcc --enable-libnpp --extra-cflags=-I/usr/local/cuda/include --extra-ldflags=-L/usr/local/cuda/lib64 --disable-static --enable-shared

  • 编译
复制
已复制!
            

make -j 8

  • 安装库。

复制
已复制!
            

sudo make install

为 Windows 编译

所有 Windows 平台都支持带有 NVIDIA GPU 加速的 FFmpeg,通过 Media Autobuild Suite 进行编译

要在 Windows 上编译 FFmpeg,请执行以下操作

  • 克隆 Media Autobuild Suite GIT 存储库。
复制
已复制!
            

git clone https://github.com/m-ab-s/media-autobuild_suite.git

  • 转到文件夹 media-autobuild_suite 并运行 media-autobuild_suite.bat
  • 选择 64 位构建系统
  • 选择非免费许可证
  • 选择要包含在构建中的库(某些库可能适用许可证限制)

选择所有选项后,Media Autobuild Suite 脚本将下载 MingW 环境和所有必需的依赖项。它还将克隆 FFMPEG 和其他相关存储库。然后,脚本将编译所有组件并构建最终的可执行文件,该文件可以在 build\ffmpeg-git 子文件夹中找到。

为 Windows Subsystem for Linux (WSL) 编译

WSL 支持带有 NVIDIA GPU 加速的 FFmpeg。要在 WSL 上编译 FFmpeg,请按照为 Linux 编译中指定的步骤进行操作。

常见问题和解决技巧

  • 常见编译问题

一旦编译了支持 NVIDIA 硬件加速的 FFmpeg 二进制文件,就应该测试硬件加速的视频转码,以确保一切正常运行。为了自动检测 NV 加速的视频编解码器并将视频帧保留在 GPU 内存中以进行转码,ffmpeg cli 选项“-hwaccel cuda -hwaccel_output_format cude”在后面的代码片段中使用。

FFMPEG 中的 NVENC 插件支持以下编解码器:h264_nvenc - H264 编码器 hevc_nvenc - HEVC 编码器 av1_nvenc - AV1 编码器 本文档中的命令行使用 h264_nvenc,应该替换为 hevc_nvenc 用于 HEVC 编码,av1_nvenc 用于 AV1 编码。

1:1 HWACCEL 无缩放转码

以下命令读取文件input.mp4,并将其转码为output.mp4,视频采用 H.264 编码,分辨率相同,音频编解码器相同。

复制
已复制!
            

ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -c:a copy -c:v h264_nvenc -b:v 5M output.mp4

1:1 HWACCEL 缩放转码

以下命令读取文件input.mp4,并将其转码为output.mp4,视频采用 H.264 编码,分辨率为 720p,音频编解码器相同。以下命令使用 cuvid 解码器中的内置调整大小器。

复制
已复制!
            

ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda –resize 1280x720 -i input.mp4 -c:a copy -c:v h264_nvenc -b:v 5M output.mp4

cuvid 解码器中也有内置的裁剪器。以下命令说明了裁剪的用法。(-crop (顶部)x(底部)x(左侧)x(右侧))

复制
已复制!
            

ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda –crop 16x16x32x32 -i input.mp4 -c:a copy -c:v h264_nvenc -b:v 5M output.mp4

或者,可以使用 scale_cuda 或 scale_npp 调整大小过滤器,如下所示

复制
已复制!
            

ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -vf scale_cuda=1280:720 -c:a copy -c:v h264_nvenc -b:v 5M output.mp4 ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -vf scale_npp=1280:720 -c:a copy -c:v h264_nvenc -b:v 5M output.mp4

1:N HWACCEL 缩放转码

以下命令读取文件input.mp4,并将其转码为两个不同的 H.264 视频,输出分辨率和比特率各不相同。请注意,在使用 GPU 视频编码器和解码器时,此命令还使用 FFmpeg 中的缩放过滤器 (scale_npp) 将解码后的视频输出缩放到多个所需的分辨率。这样做可以确保消除内存传输(系统内存到视频内存以及反之亦然),并确保在 GPU 硬件上以尽可能高的性能执行转码。

输入:input.mp4

输出:1080p、720p(音频与输入相同)

复制
已复制!
            

ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -vf scale_npp=1920:1080 -c:a copy -c:v h264_nvenc -b:v 5M output1.mp4 -vf scale_npp=1280:720 -c:a copy -c:v h264_nvenc -b:v 8M output2.mp4

从 YUV 或 RAW 数据进行 1:N HWACCEL 编码

从 YUV 或 RAW 文件进行编码可能会导致磁盘 I/O 成为瓶颈,建议从 SSD 进行此类编码以获得最佳性能。以下命令读取文件input.yuv,并将其编码为四个不同的 H.264 视频,输出比特率各不相同。请注意,此命令仅对所有编码操作产生单个 YUV 负载,从而实现更高效的磁盘 I/O 以提高整体编码性能。

输入:input.yuv(420p、1080p)

输出:1080p (8M)、1080p (10M)、1080p (12M)、1080p (14M)

复制
已复制!
            

ffmpeg -y -vsync 0 -pix_fmt yuv420p -s 1920x1080 -i input.yuv -filter_complex "[0:v]hwupload_cuda,split=4[o1][o2][o3][o4]" -map "[o1]" -c:v h264_nvenc -b:v 8M output1.mp4 -map "[o2]" -c:v h264_nvenc -b:v 10M output2.mp4 -map "[o3]" -c:v h264_nvenc -b:v 12M output3.mp4 -map "[o4]" -c:v h264_nvenc -b:v 14M output4.mp4

像素格式 (pix_fmt) 应分别更改为 yuv444p/p010/yuv444p16 以编码 YUV 444、420-10 和 444-10 文件。

多个 1:N HWACCEL 缩放转码

应使用此方法来实现 GPU 硬件加速转码的全部潜力。转码的典型工作负载之一包括以不同的分辨率和比特率对视频进行转码和存档,以便以后可以将其提供给不同的客户端。以下命令读取文件input1.mp4作为输入在 GPU 硬件中对其进行解码,在硬件中缩放输入,然后重新编码为 H.264 视频,以output11.mp4 分辨率为 480poutput12.mp4 分辨率为 240p,使用 GPU 硬件编码器。同时,它读取文件input2.mp4 并将其转码为 output21.mp4 分辨率为 720poutput22.mp4 分辨率为 480p 的 H.264 视频。这些都是通过单行命令行实现的。

输入:input1.mp4、input2.mp4

输出:480p 240p(来自 input1.mp4)、720p。480p(来自 input2.mp4)(音频与输入相同)

复制
已复制!
            

ffmpeg -y -hwaccel cuda -hwaccel_output_format cuda -i input1.mp4 -hwaccel cuda -hwaccel_output_format cuda -i input2.mp4 -map 0:0 -vf scale_npp=640:480 –c:v h264_nvenc -b:v 1M output11.mp4 -map 0:0 -vf scale_npp=320:240 –c:v h264_nvenc -b:v 500k output12.mp4 -map 1:0 -vf scale_npp=1280:720 –c:v h264_nvenc -b:v 3M output21.mp4 -map 1:0 -vf scale_npp=640:480 –c:v h264_nvenc -b:v 2M output22.mp4

多个 1:N 缩放转码(SW 解码->HW 缩放->HW 编码)

在某些情况下,需要在软件中执行视频解码。例如,考虑硬件编码器的容量大于解码器的情况。为了在这种情况下充分发挥编码器硬件的潜力,最好在硬件中运行部分解码工作负载(直到硬件解码器饱和),其余部分在软件中运行。

以下命令读取文件input1.mp4,在软件中对其进行解码,在硬件中缩放输入,然后将其转码为 output11.mp4 分辨率为 480poutput12.mp4 分辨率为 240p 的 H.264 视频,并同时读取文件 input2.mp4 并将其转码为 output21.mp4 分辨率为 720poutput22.mp4 分辨率为 480p 的 H.264 视频。

输入:input1.mp4、input2.mp4

输出:480p 240p(来自 input1.mp4)、720p。480p(来自 input2.mp4)(音频与输入相同)

复制
已复制!
            

ffmpeg -y -init_hw_device cuda=foo:bar -filter_hw_device foo \ -i input1.mp4 -i input2.mp4 \ -map 0:0 -vf hwupload,scale_npp=640:480 –c:v h264_nvenc -b:v 1M \ output11.mp4 \ -map 0:0 -vf hwupload,scale_npp=320:240 –c:v h264_nvenc -b:v 500k \ output12.mp4 \ -map 1:0 -vf hwupload,scale_npp=1280:720 –c:v h264_nvenc -b:v 2M \ output21.mp4 \ -map 1:0 -vf hwupload,scale_npp=640:480 –c:v h264_nvenc -b:v 1M \ output22.mp4

一旦确认基本 FFmpeg 设置工作正常,就可以使用 FFmpeg 命令行上提供的其他选项来测试编码、解码和转码。

本章列出了使用 NVENC 和 NVDEC 加速视频编码、解码和转码的 FFmpeg 命令。

视频编码

编码视频的质量取决于编码器使用的各种功能。要编码 720p YUV,请使用以下命令。

复制
已复制!
            

ffmpeg -y -vsync 0 –s 1280x720 –i input.yuv -c:v h264_nvenc output.mp4

这将生成 MP4 格式的输出文件 (output.mp4),其中包含 H264 编码的视频。

视频编码可以大致分为两种类型的用例

  • 延迟容忍型高质量:在这些类型的用例中,允许延迟。可以使用编码器功能,例如 B 帧、前瞻、参考 B 帧、可变比特率 (VBR) 和更高的 VBV 缓冲区大小。典型的用例包括云转码、录制和存档等。
  • 低延迟:在这些类型的用例中,延迟应较低,并且可以低至 16 毫秒。在这种模式下,禁用 B 帧,使用恒定比特率模式,并且 VBV 缓冲区大小保持非常低。典型的用例包括实时游戏、直播和视频会议等。由于上述限制,此编码模式会导致较低的编码质量。

NVENCODEAPI 支持多种用于调整质量、性能和延迟的功能,这些功能通过 FFmpeg 命令行公开。建议根据用例启用功能和命令行选项。

视频解码

FFmpeg 视频解码器使用起来非常简单。要解码来自input.mp4的输入比特流,请使用以下命令。

复制
已复制!
            

ffmpeg -y -vsync 0 -c:v h264_cuvid -i input.mp4 output.yuv

这将生成 NV12 格式的输出文件 (output.yuv)。

要在单个 FFmpeg 进程中同时解码多个输入比特流,请使用以下命令。

复制
已复制!
            

ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input1.264 -hwaccel cuda -hwaccel_output_format cuda -i input2.264 -hwaccel cuda -hwaccel_output_format cuda -i input3.264 -filter_complex "[0:v]hwdownload,format=nv12[o0];[1:v]hwdownload,format=nv12[o1];[2:v]hwdownload,format=nv12[o2]" -map "[o0]" -f rawvideo output1.yuv -map "[o1]" -f rawvideo output2.yuv -map "[o2]" -f rawvideo output3.yuv


这为每个解码操作使用一个单独的线程,所有线程共享一个 Cuda 上下文,并生成 NV12 格式的输出文件 (outputN.yuv)。

延迟容忍型高质量转码的命令行

输入:input.mp4

输出:与输入相同的分辨率,比特率 = 5M(音频与输入相同)

  • 慢速预设
复制
已复制!
            

ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -c:a copy -c:v h264_nvenc -preset p6 -tune hq -b:v 5M -bufsize 5M -maxrate 10M -qmin 0 -g 250 -bf 3 -b_ref_mode middle -temporal-aq 1 -rc-lookahead 20 -i_qfactor 0.75 -b_qfactor 1.1 output.mp4

  • 中速预设

在上面的命令行中使用 -preset p4 代替 -preset p6。

  • 快速预设

在上面的命令行中使用 -preset p2 代替 -preset p6。

低延迟转码的命令行

输入:input.mp4 (30fps)

输出:与输入相同的分辨率,比特率 = 5M(音频与输入相同)

  • 低延迟高质量
复制
已复制!
            

ffmpeg -y -vsync 0 -hwaccel cuda -hwaccel_output_format cuda -i input.mp4 -c:a copy -c:v h264_nvenc -preset p6 -tune ll -b:v 5M -bufsize 167K -maxrate 10M -qmin 0 output.mp4

  • 低延迟高性能

在上面的命令行中使用 -preset p2 代替 -preset p6。

前瞻

前瞻通过使编码器能够缓冲指定数量的帧、估计其复杂性并根据其复杂性在这些帧之间适当分配比特,从而提高视频编码器的速率控制精度。这通常会带来更好的质量,因为编码器可以将比特与复杂性成比例地分配到更多帧上。前瞻帧数应至少为 B 帧数 + 1,以避免 CPU 停顿。建议使用 10-20 帧的前瞻以获得最佳质量效益。

要启用前瞻,请在 FFmpeg 命令行上使用 -rc-lookahead N (N = 帧数) 选项。

自适应量化 (AQ)

此功能通过根据序列的空间和时间特性调整编码量化参数 (QP)(在速率控制算法评估的 QP 之上)来提高视觉质量。NVENC 支持两种 AQ,下面将进行解释。AQ 内部使用 CUDA 进行复杂度估计,这可能会对性能和图形引擎利用率产生轻微影响。

空间 AQ

空间 AQ 模式根据帧的空间特性调整 QP 值。由于低复杂度的平坦区域比高复杂度的详细区域在视觉上更容易感知到质量差异,因此额外的比特被分配给帧的平坦区域,代价是具有高空间细节的区域。虽然空间 AQ 提高了编码视频的可感知视觉质量,但所需的比特重新分配会导致大多数情况下峰值信噪比 (PSNR) 下降。因此,在基于 PSNR 的评估期间,应关闭此功能。空间 AQ 算法可以通过指定 aq-strength 参数来控制,该参数控制 QP 值的变化,值越大,QP 变化越大。AQ 强度范围为 1-15。

要启用空间 AQ,请在 FFmpeg 命令行上使用 -spatial-aq 1 选项,以及 -aq-strength 8(范围为 1 到 15)。如果未指定值,则驱动程序会自动选择强度。

时间 AQ

时间 AQ 尝试根据序列的时间特性调整编码量化参数 (QP)(在速率控制算法评估的 QP 之上)。时间 AQ 通过调整 QP 来改善编码帧的质量,QP 适用于在帧之间恒定或运动缓慢但具有高空间细节的区域,从而使它们成为未来帧的更好参考。与将额外的比特分配给参考帧中的此类区域相比,将其分配给被参考帧中的残差更好,因为它有助于提高整体编码视频质量。如果帧内的大部分区域运动很少或没有运动,但具有高空间细节(例如,高细节的非移动背景),则启用时间 AQ 将获得最大的好处。

时间 AQ 的潜在缺点之一是,启用时间 AQ 可能会导致 GOP 内每帧消耗的比特数波动很大。I/P 帧将消耗比平均 P 帧大小更多的比特,而 B 帧将消耗更少的比特。虽然目标比特率将在 GOP 级别保持,但帧大小将在 GOP 内从一个帧波动到下一个帧,幅度大于不使用时间 AQ 的情况。如果 GOP 内的每个帧大小都需要严格的 CBR 配置文件,则不建议启用时间 AQ。要启用时间 AQ,请在 FFmpeg 命令行上使用 -temporal_aq 1 选项。

各种因素都会影响 GPU 上硬件加速转码的性能。为您的工作负载获得最佳性能需要进行一些调整。本节提供了一些用于衡量和优化端到端转码性能的技巧。

NVIDIA 视频编解码器 SDK 文档发布了 GPU 硬件加速编码器和解码器的性能作为独立数字,使用 SDK 中包含的高性能编码或解码应用程序进行测量。虽然 FFmpeg 软件经过高度优化,但其性能略低于 SDK 文档中报告的性能,这主要是由于软件开销和 FFmpeg 代码中的额外设置/初始化时间。因此,为了使用 FFmpeg 获得高转码吞吐量,必须使硬件编码器和解码器引擎饱和,以便一个会话的初始化时间开销隐藏在其他会话的转码时间之后。这可以通过在硬件上运行多个并行编码/解码会话来实现(请参阅从 YUV 或 RAW 数据进行 1:N HWACCEL 编码)。在这种情况下,FFmpeg 的聚合转码性能与理论上预期的硬件性能非常接近。

衡量聚合性能

要衡量 GPU 硬件加速聚合性能,请按照以下步骤操作

  1. 并行运行多个并发会话(例如 4 个 FFmpeg 会话),每个会话都执行转码。
  2. 确保输入具有大量帧(建议超过 15 秒的视频),以便可以忽略初始化时间开销。
  3. 测量每个转码所需的时间。
  4. 导出每秒帧数 (FPS) 的聚合性能。

减少初始化时间的设置

为了准备更长的视频以进行流式传输分发,它们通常被拆分为更小的块,并且每个块都单独编码。这种基于块的编码避免了错误传播,为流式传输带宽自适应提供了清晰的边界,并有助于服务器上转码工作负载的并行化。然而,使用 GPU 硬件加速转码较小的视频块提出了一个挑战,因为每个 FFmpeg 进程的初始化时间开销变得非常显着。

为了在将 M 个输入文件转码为 MN 个输出文件时最大程度地减少开销(即,当 M 个输入中的每一个都转码为 N 个输出时),最好最大程度地减少启动的 FFmpeg 进程数(请参阅从 YUV 或 RAW 数据进行 1:N HWACCEL 编码以获取示例命令行)。

此外,请遵循以下提示以减少 FFmpeg 初始化时间开销

  • 设置以下环境变量
复制
已复制!
            

export CUDA_VISIBLE_DEVICES=0 // (Use ID for the GPU device which you plan to use for transcode) export CUDA_DEVICE_MAX_CONNECTIONS=2

声明

本文档仅供参考,不得视为对产品的特定功能、状况或质量的保证。NVIDIA Corporation(“NVIDIA”)对本文档中包含的信息的准确性或完整性不作任何明示或暗示的陈述或保证,并且对本文档中包含的任何错误不承担任何责任。NVIDIA 对因使用此类信息或因使用此类信息而可能导致的侵犯第三方专利或其他权利的行为的后果或使用不承担任何责任。本文档不承诺开发、发布或交付任何材料(如下定义)、代码或功能。

NVIDIA 保留随时修改、增强、改进和对本文档进行任何其他更改的权利,恕不另行通知。

客户在下订单之前应获取最新的相关信息,并应验证此类信息是否为最新且完整。

NVIDIA 产品根据订单确认时提供的 NVIDIA 标准销售条款和条件销售,除非 NVIDIA 和客户的授权代表签署的个别销售协议(“销售条款”)另有约定。NVIDIA 特此明确反对将任何客户通用条款和条件应用于购买本文档中引用的 NVIDIA 产品。本文档未直接或间接地形成任何合同义务。

NVIDIA 产品并非设计、授权或保证适用于医疗、军事、航空、航天或生命维持设备,也不适用于 NVIDIA 产品的故障或故障可能合理预期会导致人身伤害、死亡或财产或环境损害的应用。NVIDIA 对在此类设备或应用中包含和/或使用 NVIDIA 产品不承担任何责任,因此此类包含和/或使用由客户自行承担风险。

NVIDIA 不作任何陈述或保证,保证基于本文档的产品适用于任何特定用途。NVIDIA 不一定对每个产品的所有参数进行测试。客户全权负责评估和确定本文档中包含的任何信息的适用性,确保产品适合并满足客户计划的应用,并为应用执行必要的测试,以避免应用或产品的默认设置。客户产品设计中的缺陷可能会影响 NVIDIA 产品的质量和可靠性,并可能导致超出本文档中包含的附加或不同条件和/或要求。NVIDIA 对可能基于或归因于以下原因的任何默认设置、损坏、成本或问题不承担任何责任:(i) 以任何与本文档相悖的方式使用 NVIDIA 产品;或 (ii) 客户产品设计。

商标

NVIDIA、NVIDIA 徽标以及 cuBLAS、CUDA、CUDA Toolkit、cuDNN、DALI、DIGITS、DGX、DGX-1、DGX-2、DGX Station、DLProf、GPU、Jetson、Kepler、Maxwell、NCCL、Nsight Compute、Nsight Systems、NVCaffe、NVIDIA Deep Learning SDK、NVIDIA Developer Program、NVIDIA GPU Cloud、NVLink、NVSHMEM、PerfWorks、Pascal、SDK Manager、Tegra、TensorRT、TensorRT Inference Server、Tesla、TF-TRT、Triton Inference Server、Turing 和 Volta 是 NVIDIA Corporation 在美国和其他国家/地区的商标和/或注册商标。其他公司和产品名称可能是与其关联的各自公司的商标。

© 2010-2025 NVIDIA Corporation。保留所有权利。 上次更新时间:2025 年 1 月 27 日。