启用 GPU 视频解码器/编码器
TorchAudio 可以利用底层 FFmpeg 库支持的基于硬件的视频解码和编码功能,这些库在运行时被链接。
使用 NVIDIA 的 GPU 解码器和编码器,还可以直接传递 CUDA 张量,即将视频解码为 CUDA 张量或从 CUDA 张量编码视频,而无需在 CPU 之间移动数据。
这显著提高了视频处理吞吐量。然而,请注意,并非所有视频格式都支持硬件加速。
本页介绍了如何构建支持硬件加速的 FFmpeg。有关 GPU 解码器和编码器性能的详细信息,请参阅 NVDEC 教程 和 NVENC 教程。
概述
在 TorchAudio 中使用它们需要额外的 FFmpeg 配置。
接下来,我们将探讨如何通过 NVIDIA 的视频编解码 SDK 启用 GPU 视频解码。要在 TorchAudio 中使用 NVENC/NVDEC,需要满足以下条件。
-
支持硬件视频解码/编码的 NVIDIA GPU。
-
编译时启用了 NVDEC/NVENC 支持的 FFmpeg 库。†
-
支持 CUDA 的 PyTorch / TorchAudio。
TorchAudio 的官方二进制发行版已编译为与 FFmpeg 库兼容,并且包含了使用硬件解码/编码的逻辑。
以下内容展示了如何构建支持 NVDEC/NVENC 的 FFmpeg 4 库。您也可以使用 FFmpeg 5 或 6。
以下步骤在 Ubuntu 上进行了测试。
† 有关 NVDEC/NVENC 和 FFmpeg 的详细信息,请参考以下文章。
-
https://docs.nvidia.com/video-technologies/video-codec-sdk/11.1/nvdec-video-decoder-api-prog-guide/
-
https://developer.nvidia.com/blog/nvidia-ffmpeg-transcoding-guide/
检查 GPU 和 CUDA 版本
首先,检查可用的 GPU。这里,我们安装了带有 CUDA Toolkit 11.2 的 Tesla T4。
$ nvidia-smi
Fri Oct 7 13:01:26 2022
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 460.32.03 Driver Version: 460.32.03 CUDA Version: 11.2 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 Tesla T4 Off | 00000000:00:04.0 Off | 0 |
| N/A 56C P8 10W / 70W | 0MiB / 15109MiB | 0% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
| No running processes found |
+-----------------------------------------------------------------------------+
检查计算能力
稍后,我们需要了解该 GPU 支持的计算能力版本。以下页面列出了 GPU 及其对应的计算能力。T4 的计算能力为 7.5
。
https://developer.nvidia.com/cuda-gpus
安装 NVIDIA 视频编解码头文件
要使用 NVDEC/NVENC 构建 FFmpeg,我们首先需要安装 FFmpeg 用于与 Video Codec SDK 交互的头文件。
由于系统中已经安装了 CUDA 11,我们使用 n11
标签之一。
gitclonehttps://git.videolan.org/git/ffmpeg/nv-codec-headers.git
cdnv-codec-headers
gitcheckoutn11.0.10.1
sudomakeinstall
安装位置可以通过 make PREFIX=<DESIRED_DIRECTORY> install
进行更改。
Cloning into 'nv-codec-headers'...
remote: Enumerating objects: 819, done.
remote: Counting objects: 100% (819/819), done.
remote: Compressing objects: 100% (697/697), done.
remote: Total 819 (delta 439), reused 0 (delta 0)
Receiving objects: 100% (819/819), 156.42 KiB | 410.00 KiB/s, done.
Resolving deltas: 100% (439/439), done.
Note: checking out 'n11.0.10.1'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b <new-branch-name>
HEAD is now at 315ad74 add cuMemcpy
sed 's#@@PREFIX@@#/usr/local#' ffnvcodec.pc.in > ffnvcodec.pc
install -m 0755 -d '/usr/local/include/ffnvcodec'
install -m 0644 include/ffnvcodec/*.h '/usr/local/include/ffnvcodec'
install -m 0755 -d '/usr/local/lib/pkgconfig'
install -m 0644 ffnvcodec.pc '/usr/local/lib/pkgconfig'
安装 FFmpeg 依赖项
接下来,我们安装 FFmpeg 构建过程中所需的工具和库。最低要求是 Yasm。在这里,我们还额外安装了 H264 视频编解码器和 HTTPS 协议,稍后将用于验证安装。
sudoapt-qqupdate
sudoapt-qqinstall-yyasmlibx264-devlibgnutls28-dev
... Omitted for brevity ...
STRIP install-libavutil-shared
Setting up libx264-dev:amd64 (2:0.152.2854+gite9a5903-2) ...
Setting up yasm (1.3.0-2build1) ...
Setting up libunbound2:amd64 (1.6.7-1ubuntu2.5) ...
Setting up libp11-kit-dev:amd64 (0.23.9-2ubuntu0.1) ...
Setting up libtasn1-6-dev:amd64 (4.13-2) ...
Setting up libtasn1-doc (4.13-2) ...
Setting up libgnutlsxx28:amd64 (3.5.18-1ubuntu1.6) ...
Setting up libgnutls-dane0:amd64 (3.5.18-1ubuntu1.6) ...
Setting up libgnutls-openssl27:amd64 (3.5.18-1ubuntu1.6) ...
Setting up libgmpxx4ldbl:amd64 (2:6.1.2+dfsg-2) ...
Setting up libidn2-dev:amd64 (2.0.4-1.1ubuntu0.2) ...
Setting up libidn2-0-dev (2.0.4-1.1ubuntu0.2) ...
Setting up libgmp-dev:amd64 (2:6.1.2+dfsg-2) ...
Setting up nettle-dev:amd64 (3.4.1-0ubuntu0.18.04.1) ...
Setting up libgnutls28-dev:amd64 (3.5.18-1ubuntu1.6) ...
Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
Processing triggers for libc-bin (2.27-3ubuntu1.6) ...
构建支持 NVDEC/NVENC 的 FFmpeg
接下来我们下载 FFmpeg 4 的源代码。这里我们使用的是 4.4.2 版本。
wget-qhttps://github.com/FFmpeg/FFmpeg/archive/refs/tags/n4.4.2.tar.gz
tar-xfn4.4.2.tar.gz
cdFFmpeg-n4.4.2
接下来我们配置 FFmpeg 构建。请注意以下内容:
-
我们提供诸如
-I/usr/local/cuda/include
、-L/usr/local/cuda/lib64
等标志,以便让构建过程知道 CUDA 库的位置。 -
我们提供诸如
--enable-nvdec
和--enable-nvenc
等标志来启用 NVDEC/NVENC。 -
我们还提供计算能力为
75
的 NVCC 标志,这对应于 T4 的7.5
。† -
我们将库安装在
/usr/lib/
目录下。
† 配置脚本通过编译示例代码来验证 NVCC。默认情况下,它使用旧的计算能力(如
30
),而 CUDA 11 不再支持该计算能力。因此,需要设置正确的计算能力。
prefix=/usr/
ccap=75
./configure\
*-prefix="${prefix}"\
*-extra-cflags='-I/usr/local/cuda/include'\
*-extra-ldflags='-L/usr/local/cuda/lib64'\
*-nvccflags="-gencode arch=compute_${ccap},code=sm_${ccap} -O2"\
*-disable-doc\
*-enable-decoder=aac\
*-enable-decoder=h264\
*-enable-decoder=h264_cuvid\
*-enable-decoder=rawvideo\
*-enable-indev=lavfi\
*-enable-encoder=libx264\
*-enable-encoder=h264_nvenc\
*-enable-demuxer=mov\
*-enable-muxer=mp4\
*-enable-filter=scale\
*-enable-filter=testsrc2\
*-enable-protocol=file\
*-enable-protocol=https\
*-enable-gnutls\
*-enable-shared\
*-enable-gpl\
*-enable-nonfree\
*-enable-cuda-nvcc\
*-enable-libx264\
*-enable-nvenc\
*-enable-cuvid\
*-enable-nvdec
install prefix /usr/
source path .
C compiler gcc
C library glibc
ARCH x86 (generic)
big-endian no
runtime cpu detection yes
standalone assembly yes
x86 assembler yasm
MMX enabled yes
MMXEXT enabled yes
3DNow! enabled yes
3DNow! extended enabled yes
SSE enabled yes
SSSE3 enabled yes
AESNI enabled yes
AVX enabled yes
AVX2 enabled yes
AVX-512 enabled yes
XOP enabled yes
FMA3 enabled yes
FMA4 enabled yes
i686 features enabled yes
CMOV is fast yes
EBX available yes
EBP available yes
debug symbols yes
strip symbols yes
optimize for size no
optimizations yes
static no
shared yes
postprocessing support no
network support yes
threading support pthreads
safe bitstream reader yes
texi2html enabled no
perl enabled yes
pod2man enabled yes
makeinfo enabled no
makeinfo supports HTML no
External libraries:
alsa libx264 lzma
bzlib libxcb zlib
gnutls libxcb_shape
iconv libxcb_xfixes
External libraries providing hardware acceleration:
cuda cuvid nvenc
cuda_llvm ffnvcodec v4l2_m2m
cuda_nvcc nvdec
Libraries:
avcodec avformat swscale
avdevice avutil
avfilter swresample
Programs:
ffmpeg ffprobe
Enabled decoders:
aac hevc rawvideo
av1 mjpeg vc1
h263 mpeg1video vp8
h264 mpeg2video vp9
h264_cuvid mpeg4
Enabled encoders:
h264_nvenc libx264
Enabled hwaccels:
av1_nvdec mpeg1_nvdec vp8_nvdec
h264_nvdec mpeg2_nvdec vp9_nvdec
hevc_nvdec mpeg4_nvdec wmv3_nvdec
mjpeg_nvdec vc1_nvdec
Enabled parsers:
h263 mpeg4video vp9
Enabled demuxers:
mov
Enabled muxers:
mov mp4
Enabled protocols:
file tcp
https tls
Enabled filters:
aformat hflip transpose
anull null trim
atrim scale vflip
format testsrc2
Enabled bsfs:
aac_adtstoasc null vp9_superframe_split
h264_mp4toannexb vp9_superframe
Enabled indevs:
lavfi
Enabled outdevs:
License: nonfree and unredistributable
现在我们将进行构建和安装
makeclean
make-j
sudomakeinstall
... Omitted for brevity ...
INSTALL libavdevice/libavdevice.so
INSTALL libavfilter/libavfilter.so
INSTALL libavformat/libavformat.so
INSTALL libavcodec/libavcodec.so
INSTALL libswresample/libswresample.so
INSTALL libswscale/libswscale.so
INSTALL libavutil/libavutil.so
INSTALL install-progs-yes
INSTALL ffmpeg
INSTALL ffprobe
检查安装
为了验证我们构建的 FFmpeg 是否支持 CUDA,我们可以检查可用的解码器和编码器列表。
ffprobe-hide_banner-decoders|greph264
VFS..D h264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
V..... h264_cuvid Nvidia CUVID H264 decoder (codec h264)
ffmpeg-hide_banner-encoders|grep264
V..... libx264 libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (codec h264)
V....D h264_nvenc NVIDIA NVENC H.264 encoder (codec h264)
以下命令从远程服务器获取视频,使用 NVDEC (cuvid) 进行解码,并使用 NVENC 重新编码。如果此命令无法正常工作,则说明 FFmpeg 安装存在问题,TorchAudio 也将无法使用这些功能。
$src="https://download.pytorch.org/torchaudio/tutorial-assets/stream-api/NASAs_Most_Scientifically_Complex_Space_Observatory_Requires_Precision-MP4_small.mp4"
$ffmpeg-hide_banner-y-vsync0\
*hwaccelcuvid\
*hwaccel_output_formatcuda\
*c:vh264_cuvid\
*resize360x240\
*i"${src}"\
*c:acopy\
*c:vh264_nvenc\
*b:v5Mtest.mp4
请注意,这里有 Stream #0:0 -> #0:0 (h264 (h264_cuvid) -> h264 (h264_nvenc))
,这意味着视频是通过 h264_cuvid
解码器和 h264_nvenc
编码器进行处理的。
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'https://download.pytorch.org/torchaudio/tutorial-assets/stream-api/NASAs_Most_Scientifically_Complex_Space_Observatory_Requires_Precision-MP4_small.mp4':
Metadata:
major_brand : mp42
minor_version : 512
compatible_brands: mp42iso2avc1mp41
encoder : Lavf58.76.100
Duration: 00:03:26.04, start: 0.000000, bitrate: 1294 kb/s
Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 960x540 [SAR 1:1 DAR 16:9], 1156 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc (default)
Metadata:
handler_name : ?Mainconcept Video Media Handler
vendor_id : [0][0][0][0]
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s (default)
Metadata:
handler_name : #Mainconcept MP4 Sound Media Handler
vendor_id : [0][0][0][0]
Stream mapping:
Stream #0:0 -> #0:0 (h264 (h264_cuvid) -> h264 (h264_nvenc))
Stream #0:1 -> #0:1 (copy)
Press [q] to stop, [?] for help
Output #0, mp4, to 'test.mp4':
Metadata:
major_brand : mp42
minor_version : 512
compatible_brands: mp42iso2avc1mp41
encoder : Lavf58.76.100
Stream #0:0(eng): Video: h264 (Main) (avc1 / 0x31637661), cuda(tv, bt709, progressive), 360x240 [SAR 1:1 DAR 3:2], q=2-31, 5000 kb/s, 29.97 fps, 30k tbn (default)
Metadata:
handler_name : ?Mainconcept Video Media Handler
vendor_id : [0][0][0][0]
encoder : Lavc58.134.100 h264_nvenc
Side data:
cpb: bitrate max/min/avg: 0/0/5000000 buffer size: 10000000 vbv_delay: N/A
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 128 kb/s (default)
Metadata:
handler_name : #Mainconcept MP4 Sound Media Handler
vendor_id : [0][0][0][0]
frame= 6175 fps=1712 q=11.0 Lsize= 37935kB time=00:03:26.01 bitrate=1508.5kbits/s speed=57.1x
video:34502kB audio:3234kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.526932%
使用 TorchAudio 中的 GPU 解码器/编码器
检查安装
在确保 FFmpeg 正确支持硬件加速后,我们需要检查 TorchAudio 是否能正确识别它。
在 torchaudio.utils.ffmpeg_utils
中提供了一些实用函数来查询 FFmpeg 的能力。
您可以首先使用 get_video_decoders()
和 get_video_encoders()
来检查 GPU 解码器和编码器(如 h264_cuvid
和 h264_nvenc
)是否在列表中。
通常系统中可能存在多个 FFmpeg 安装,而 TorchAudio 加载的版本可能与预期不同。在这种情况下,使用 ffmpeg
检查安装情况并无帮助。您可以使用 get_build_config()
和 get_versions()
等函数来获取 TorchAudio 加载的 FFmpeg 库的相关信息。
from torchaudio.utils import ffmpeg_utils
print("Library versions:")
print(ffmpeg_utils.get_versions())
print("\nBuild config:")
print(ffmpeg_utils.get_build_config())
print("\nDecoders:")
print([k for k in ffmpeg_utils.get_video_decoders().keys() if "cuvid" in k])
print("\nEncoders:")
print([k for k in ffmpeg_utils.get_video_encoders().keys() if "nvenc" in k])
Library versions:
{'libavutil': (56, 31, 100), 'libavcodec': (58, 54, 100), 'libavformat': (58, 29, 100), 'libavfilter': (7, 57, 100), 'libavdevice': (58, 8, 100)}
Build config:
*-prefix=/usr --extra-version=0ubuntu0.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
Decoders:
['h264_cuvid', 'hevc_cuvid', 'mjpeg_cuvid', 'mpeg1_cuvid', 'mpeg2_cuvid', 'mpeg4_cuvid', 'vc1_cuvid', 'vp8_cuvid', 'vp9_cuvid']
Encoders:
['h264_nvenc', 'nvenc', 'nvenc_h264', 'nvenc_hevc', 'hevc_nvenc']
使用硬件解码器和编码器
一旦安装和运行时链接工作正常,您可以通过以下方式测试 GPU 解码。