提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

最近在搞一个项目,我需要向AI提供视频帧数,本来一开始摄像头是H.264的编码,我直接复制流推到AI层去推理,然后需要将事件回溯成30秒的视频截取。结果摄像头换成了HEVC编码,截取的视频不能在网页直接播放(需要JS实现调用硬解码)。一开始的方案是ffmpeg直接将HEVC转成H.264结果因为事务巨多CPU占用量过大,导致影响到了推理,因为本身选用的模型+杂七杂八的业务逻辑也要占用大量的CPU资源,所以经过研究把ffmpeg和nvcodec结合起来来平衡设备性能,算是解决了这个问题吧。


一、先安装CUDA+NVCODEC

这两个是前提条件,我在之前的文章里已经说明了具体步骤,有需要的请移步文章。
opencv+nvcodec实现视频硬解码

二、编译带NVCODEC的FFMPEG

这里使用的ffmpeg版本是4.4.2,之前也有尝试过编译5.0.1,本身没有什么错误,但是和我的opencv-4.5.1合并编译遇到了很多错误,可能是这个版本太新的缘故,所以就选择了4.4.2这个版本,实测没有任何问题,至少可以满足我的需求了。

1、安装环境

  1. 安装必要软件包
sudo apt install autoconf automake build-essential cmake git-core libass-dev libfreetype6-dev libsdl2-dev libtool libva-dev libvdpau-dev libvorbis-dev libxcb1-dev libxcb-shm0-dev libxcb-xfixes0-dev pkg-config texinfo wget zlib1g-dev
  1. 安装汇编编译器
sudo apt install nasm yasm

3.安装扩展
这里我只用到了libx264和libx265,如果你有其它的需求就自行安装即可,这些软件基本上在Ubuntu的库里都能找到,不能找到的也可以通过源代码编译安装。

注意: 必须在ffmpeg编译前就把需要的软件安装,否则勾选了这些选项会报错

sudo apt install libx264-dev libx265-dev

4.安装依赖头文件包

这里需要安装一个头文件包,里面包含了一系列用到的头文件。

git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git
cd nv-codec-headers
sudo make install

2、开始编译

可以从官网或者github下载4.4.2的源代码,这里我只演示4.4.2版本,如果你的环境和我一样,绝对可以保证完美运行,其他版本请自行测试。
FFMPEG官网

tar -xmf ffmpeg-4.4.2.tar.xz
cd ffmpeg-4.4.2/
./configure --prefix=/usr --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --disable-stripping --enable-avresample --enable-shared --enable-libx264 --enable-libx265 --enable-cuda --enable-cuvid --enable-nvenc  --enable-gpl
make -j$(nproc)
sudo make install

3、验证

ffmpeg -encoders

在这里插入图片描述
只要有红框里面的说明ffmpeg编译没有问题,具体功能还要进一步验证,找一个hevc格式或h264的视频执行下面的命令

HEVC->H.264

ffmpeg -vcodec hevc_cuvid -an -gpu 0 -i <vidoe_path> -vcodec h264_nvenc -an -gpu 0 -y output.mp4

H.264->HEVC

ffmpeg -vcodec h264_cuvid -an -gpu 0 -i <video_path> -vcodec hevc_nvenc -an -gpu 0 -y output.mp4

参数说明:
-i 视频路径,可以是绝对,可以是相对
-vcodec 视频解码器或编码器,写在-i前面的是解码,写在后面的是编码
-an 这里由于测试视频,所以禁用了音频,需要音频的可以不加这个选项
-gpu 指定哪个显卡来完成操作,只有一张显卡的可以不指定,默认显卡是从0开始的,指定了不存在的显卡会报错
-y 直接确认覆盖output.mp4假如存在的话

我用到的就这些,其他还有很多如比特率,帧率,质量等等请自行摸索,毕竟学无止境。到这里就算是讲完了,如果想看显卡的占用率的话输入以下命令

nvidia-smi dmon

在这里插入图片描述

参数就不详细解读了,简单介绍下:

Idx就是显卡索引,0是第一块,1是第二块,依次类推;pwr是功率,单位瓦特
gtemp是核心温度,工作起来会增长,太高了会降频或者触发保护
mtemp应该是显存温度,这里一直是0,不知道啥原因
sm是流处理器占用率
enc是编码器占用率
dec是解码器占用率
mclk是显存时钟,动态调整的,待机很低,工作会自行增长
pclk是核心频率,就是流处理器的频率,也是动态调整的

这里多说一句:

1、编解码本身肯定是占用显存的,这一点是没有疑问的。所以老黄说的完全独立的硬件这里是不完全对的。这句话应该是相对于cuda软解码说的,cuda本身也是可以硬算的,从某种角度来说,cuda也属于通用处理器了,而nvcodec才是专用编解码处理器

2、从占用上来看,硬件编解码应该是消耗一定的cuda性能的,这一部分可能主要是显存拷贝数据的消耗,这个目前只是我的猜测,现在还拿不出证据,具体可以通过测试AI能力是否下降来确定,就推理来说,显存一般都是够用的。


总结

不要让GPU的解码单元闲着,毕竟花钱了,也能分摊一部分CPU压力。而且有些模型可以直接将硬解码的数据送到推理里面去而不用从显存转到内存,省略了这样一个消耗。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐