Ubuntu上,ffmpeg如何使用cuda硬件解码、编码、转码加速

本文使用 Ubuntu 环境。Ubuntu 直接使用 APT 安装的就支持 CUDA 加速。本文使用这样下载的版本进行演示,你自己编译或者其他源的版本可能会不同。

ffmpeg 的一些介绍,以及 macOS 版本的 ffmpeg 硬件加速请见《macOS上如何安装(不需要编译安装或者brew)、使用ffmpeg转码的教程,以及如何使用硬件加速 - ZhongUncle's CSDN》

如果你了解转码的流程,那么直接跳过前两节,通过侧边栏跳转到"使用FFMPEG硬件加速转码"部分直接看命令。

转码的流程(解码、编码、转码的区别)

任何转码都分为解码、编码这样一个步骤。简单来说,解码就是把视频文件转换成显示的视频,编码就是把视频转换成视频文件。

关于解码和编码举 2 个例子:

  • 相机:相机就是通过把传感器的信号转换成某种视频格式,也就是编码,这样推流也好,存储也好,都好处理一些,毕竟与特特定传感器的信号格式无关了。
  • 看视频:看视频就是把传输来的视频格式解码成特定信号,传给显示器等设备,让你看到。

ffmpeg 如果没有任何特殊选项,默认是使用软件解码、编码。硬件加速解码就是利用某种专为某些格式解码、编码设计的芯片进行操作。

一个常识:特定设计的芯片要比 CPU 通用处理器快很多,功耗也小很多。

软、硬解码编码的区别

软件解码、编码就是利用 CPU 运行一个软件,然后由这个软件进行解码、编码的操作。这样的好处就是如果一个格式更新了,或者一些特殊类型的编码都可以实现。而硬件编码在制造芯片的时候就已经写死了,无法更改了,所以基本上更新一代,就多支持几个格式。比如 980 Ti 的编码器只支持 4:2:0 的 4K H.265 的格式,如下:

但是到 1080 Ti 的时候,就多支持了三种:

需要注意,虽然视频编解码器一般都是和 GPU 同时出现,但是这玩意不是用 CUDA 等光栅单元实现的,是单独的一部分。比如 Tesla A100 这种特别强的 GPU 并不支持硬件编解码加速,因为没有硬件编解码器。(也不是所有计算卡的都没有,比如 V100、P100 都有)

此外,这玩意是有数量的,不是说支持硬件加速,你上 10 条视频一起处理和单独处理 1 条的速度一样,后面会演示这个现象。

使用FFMPEG硬件加速转码

简单的开始

好了,在了解基础信息之后,可以开始转码了。下面是最简单的命令:

复制代码
ffmpeg -c:v h264_cuvid -i input.mp4 -c:v h264_nvenc output.mp4

其中:

  • 前面的-c:v h264_cuvid是用来解码的。如果你用过 Mac 上的硬件加速,会发现这种不太一样,它强制说明了解码器(如果不用这个会怎样呢,后面演示给你看)。
  • 后面的-c:v h264_nvenc是用来编码的。

此外,如果你看过官方文档,会发现和官方文档的使用方法不一样,如果使用官方文档中的命令,很容易转码的时候出现问题。

设置码率和帧率

如果使用上述的命令进行转码,那么码率和帧数很可能会不同(比如帧率 30 变 25,码率 6m 变 2m),所以我们要制定码率和帧数:

复制代码
ffmpeg -c:v h264_cuvid -i input.mp4 -c:v h264_nvenc -b:v 6000k -r 30 output.mp4

其中:

  • -b:v 6000k表示码率是6000k
  • -r 30表示转码后的帧率为30帧。

此时转码速率为 16x,要比核显快很多。此时显卡情况如下:

不指定硬件解码器会怎样?

前面提到它强制说明了解码器,那么如果不用这个会怎样呢?

如果不使用硬件解码器,那么就需要使用 CPU 进行软解,所以 CPU 使用率会很高,但是转码速度并不会有太大区别(有些时候会快一些):

这种方式也有自己的使用场景:当你要修复一个视频的编码器的时候,最好用软解码,因为硬件解码器很可能无法正确识别已经有问题的编码。比如我有一个视频,用有的播放器看的时候,会无法看 11 分钟之后的内容,那么如果使用硬件解码器,会出现下面的问题:

复制代码
[h264_cuvid @ 0x55ed4090d540] cuvid decode callback error
Error while decoding stream #0:0: Generic error in an external library

打开视频发现转码的是黑屏,但是不指定解码器就可以正确转码。

在只有一个编码器上进行多个作业会怎样?

前面提到编码器、解码器是有数量的。并不是多少个都一样快,比如上面我们发现 3060 转码是 16x,如果同时进行两个转码任务,那么会发现总和差不多也是 16x。

这个结果可能会让你很沮丧,但是你想哈,比如直播和录像的时候,你实际上只需要 1x 的速度啊,这样的话相当于你可以同时至多跑 16 个流(实际上会少一些,因为并不是每个任务都是恒定 1x 的,保险起见要留余量),这就很不错了。

编码质量

FFMPEG

转码除了修复编码问题,一般都是换编码格式(比如 h265 转 h264)和文件格式。

同编码同文件文件格式的转码较少,不过我也试了,质量非常不错,和软转没啥区别。

我之前写过一篇 macOS 上 ffmpeg 硬件加速转码的博客:《macOS上如何安装(不需要编译安装或者brew)、使用ffmpeg转码的教程,以及如何使用硬件加速 - ZhongUncle's CSDN》,里面有个对比,是 mp4 转 mov 的同时,降低码率从 42m 到 10m,对比如下:

CUDA 硬件转码的情况如下:

会发现 3060 的质量要比 8 代酷睿的 QSV 质量好一些,真不错,就是功耗大。

OBS

硬件编码器是有个支持码率范围的,超过和过低都会有较大的画质损耗或者编码问题。

英伟达官方建议 OBS 直播设置的的分辨率、码率、帧数设置如下(下图是机翻的,"1440点"是"1440P",也就是 2k):

在游玩燕云十六声的时候,使用 OBS 录屏(nvenc h264 编码)8000k码率的和软编码画质差不多。采用 40Mbps 编码的时候,要比软编码差一点,但差的不是很多。关于这部分我会单独开一篇博客,之前用的是 MX250 这种英伟达 GPU,编码速度和质量要比 QSV 差很多。这里简单列一下截图:

我这里是按照个人习惯设置的,并没有按照 Nvidia 的建议设置,因为我一开始不知道官方推荐值。

麦田这种事物比较密集的场景很适合看码率损耗(你还可以用色彩多的画面检查,这个更明显),如下,可以看到麦穗虽然已经无法看清,但是远观并不糊(下面的图二次压缩过,但是也够看出来损耗可以接受了):

希望能帮到有需要的人~

参考资料/扩展阅读

NVIDIA FFmpeg Transcoding Guide - Nvidia Developer Technical Blog:ffmpeg 中 cuda 硬件转码的一些技术介绍。

Using FFmpeg with NVIDIA GPU Hardware Acceleration:ffmpeg 中 cuda 硬件编码、解码的技术文档。

Video Encode and Decode GPU Support Matrix - Nvidia Developer:这里你可以查看哪些 GPU 支持什么编、解码器。

NVIDIA NVENC OBS Guide - Nvidia:这里英伟达介绍了如何使用 OBS 直播。

Broadcasting 101: A Beginner's Guide to Live Streaming:这里介绍了直播需要的设备规格和一些额外的链接。

相关推荐
欧云服务器5 天前
怎么让脚本命令可以同时在centos、debian、ubuntu执行?
ubuntu·centos·debian
智渊AI5 天前
Ubuntu 20.04/22.04 下通过 NVM 安装 Node.js 22(LTS 稳定版)
ubuntu·node.js·vim
The️5 天前
Linux驱动开发之Read_Write函数
linux·运维·服务器·驱动开发·ubuntu·交互
再战300年5 天前
Samba在ubuntu上安装部署
linux·运维·ubuntu
qwfys2005 天前
How to install golang 1.26.0 to Ubuntu 24.04
ubuntu·golang·install
木尧大兄弟5 天前
Ubuntu 系统安装 OpenClaw 并接入飞书记录
linux·ubuntu·飞书·openclaw
小虾爬滑丫爬5 天前
ubuntu上设置Tomcat 开机启动
ubuntu·tomcat·开机启动
老师用之于民5 天前
【DAY25】线程与进程通信:共享内存、同步机制及实现方案
linux·c语言·ubuntu·visual studio code
小虾爬滑丫爬5 天前
Ubuntu 上设置防火墙
ubuntu·防火墙
林开落L5 天前
解决云服务器内存不足:2 分钟搞定 Ubuntu swap 交换区配置(新手友好版)
运维·服务器·ubuntu·swap交换区