开发者问题收集

为什么python中的pyav包无法识别h264_cuvid编解码器而ffmpeg可以?

2022-03-25
1880

我有一个如下所示的 python 脚本,用于从视频中读取字节流。我想使用 h264_cuvid 代码进行 GPU 硬件加速,而不是 CPU 编码或解码。当我运行此命令时,我的 FFmpeg 确实有 h264_cuvid 编解码器:

ffmpeg -c:v h264_cuvid -i input.mp4 output_codec.mp4

它成功运行,但在 pyav 包中,当我尝试创建如下所示的 h264_cuvid 编解码器时:

import av

video = av.open(VIDEO_FILE_PATH)
target_stream = video.streams.video[0]
ctx = av.Codec('h264_cuvid', 'r').create()

它给了我一个错误,说一个未知的编解码器:

ctx = av.Codec('h264_cuvid', 'r').create()
File "av/codec/codec.pyx", line 184, in av.codec.codec.Codec.__cinit__
File "av/codec/codec.pyx", line 193, in av.codec.codec.Codec._init
av.codec.codec.UnknownCodecError: h264_cuvid
av version = 9.0.2

ffmpeg version 7:3.4.8-0ubuntu0.2

注意:我通过 pip install av 安装 av>

任何帮助都将不胜感激

2个回答

除非您从源代码编译 pyAV,否则它将使用不支持硬件加速的供应商版本的 ffmpeg 进行预编译。这样做有两个原因 (1) 更好的设备兼容性,以及 (2) 维护效率。

人们通常引用使用 hwaccel 的三个主要原因:(1) 更快的编码,(2) 更快的解码,或 (3) 更好的能源效率。关于 (1),硬件编码器在实践中往往比软件编码器生成质量更低的视频(比特率相等)。关于 (2),硬件解码器确实比软件解码器更快,但必须将帧复制回主机内存 (RAM) 以使其可用于 python 层。这会减少或抵消任何速度提升。关于 (3),如果您追求的是能源效率,那么切换到编译语言将比引入 hwaccel 更好的优化。

反对 hwaccel 的主要原因是:它很难实现并且很脆弱,因此您不仅需要一个非常有才华的人来编写初始代码,而且还需要一个同样有能力的人自愿维护它并在 hwaccel API 发生变化(它不是最稳定的)或者有错误或新功能需要添加时修复问题。

总而言之,它在 pyav 中不受支持的主要原因是它被认为影响力不够,而且 - 更重要的是 - 因为没有人愿意维护它,即它不支持维护效率。

FirefoxMetzger
2022-04-22

我已经回答了自己的问题,因为我找到了解决方案。 为了在 pyav 中使用硬件加速,您需要编译 ffmpeg,然后从源代码安装 pyav(而不是使用 pip install pyav)。您还必须将系统的 cuda 路径设置到您的 bashrc 文件中

此 bashscript 可帮助您完成所有步骤:


echo "************************  try building ffmpeg  *******************"
echo "Install nv-codec-headers"

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

cd nv-codec-headers && make -j4 && make install && cd ..

wget https://ffmpeg.org/releases/ffmpeg-4.2.1.tar.bz2
tar -xf ffmpeg-4.2.1.tar.bz2
cd ffmpeg-4.2.1
./configure --enable-cuda --enable-cuvid --enable-nvenc --enable-nonfree --extra-cflags=-I/usr/local/cuda/include --extra-ldflags=-L/usr/local/cuda/lib64 --enable-shared

make -j4
make install
cd ..

echo "************************  setting cuda path  *******************"
echo "export PATH=/usr/local/cuda/bin:/ffmpeg/libavdevice:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin" >> ~/.bashrc
echo "export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/usr/local/cuda/targets/x86_64-linux/lib:/usr/local/cuda/targets/x86_64-linux/include:/usr/local/cuda/lib64:/usr/local/cuda/include:/usr/local/cuda/extras/CUPTI/lib64:/ffmpeg/libavdevice" >> ~/.bashrc

echo "************************  try building pyav  *******************"
git clone -b hwaccel https://github.com/rvillalba-novetta/PyAV.git

cd PyAV
source scripts/activate.sh
pip3 install -r tests/requirements.txt
make -j4

python3 setup.py install
cd ..

ldconfig /usr/local/cuda/lib64
echo "*********************   ffmpeg and pyav are built successfuly ***************"
MediaJ
2022-05-03