硬件加速不是一个东西,是一族互不兼容的方案。 能不能用、用哪一条,只能在这台机器上查,不能按经验写。
3.11.7 讲最外层的协议,这一节讲最底层——谁来算那些像素。 这一节的结论跟机器绑得最死,换台机器就得重查。
一、五种方案,互不兼容
按平台分,常见的就这五种:
方案 平台 典型名字
DXVA2 Windows(老) dxva2 D3D11VA Windows 8 以上 d3d11va NVDEC/NVENC NVIDIA 显卡 cuda/cuvid/nvenc VAAPI Linux 核显 vaapi VideoToolbox macOS videotoolbox
这五种之间不能互换:在 Windows 上写的 vaapi 参数,移到 Mac 上一定不认。 所以「硬件加速能不能用」这个问题,必须先问「在哪台机器上」。
同一个平台上也常常有好几种并存,比如 Windows 上 DXVA2 和 D3D11VA 就都在。 新的一般优先用,但老显卡可能只支持老的那一种。
二、本机 h264 的五种硬件配置
一个具体解码器到底能接哪几种硬件方案,是可以逐条读出来的:
设备类型号 名字 像素格式 本机支持
4 dxva2 dxva2_vld 是 0 d3d11va d3d11va_vld 否 7 d3d11 d3d11 是 12 d3d12 d3d12 是 2 cuda cuda 是
本机 h264 有四条可用:dxva2、d3d11、d3d12、cuda。 第二行标了「否」——它在表里,但这份构建判定不可用。
「在表里」和「能用」是两个状态,跟 3.11.4 里设备组件那一节是同一个道理。 清单只能告诉你「这条路存在」,能不能走要另判。
三、三种用法,代价完全不同
硬件加速不是「开了就快」,要看你把哪一段交给显卡:
用法 参数形态 代价
只解不编 -hwaccel dxva2 解码快,编码还在 CPU 只编不解 -c:v h264_nvenc 编码快,解码还在 CPU 全硬 两边都指定 最快,画质与兼容性受限
第三行的代价要说清楚:硬件编码器为了速度会牺牲压缩效率。 同样码率下画质通常不如 x264 的 slow preset,参数可调的范围也小得多。
第一行反而是最划算的一种:解码白拿速度,画质一点不损。
所以「只想快点看」这件事,加 -hwaccel 比换编码器合适得多。
四、这一节的结论只有一句
ffmpeg -hwaccels 给出的是这份构建支持的方案列表,
而 -h decoder=h264 里那一段才是「这个解码器具体能接哪些」。
命令 回答什么
ffmpeg -hwaccels 这份构建支持哪几种方案 ffmpeg -h decoder=h264 h264 能接哪几种、哪种可用
两个都要查,少查一个就会写出「参数不认」的命令。 只查前一个,会写出「方案存在但这个解码器不接」; 只查后一个,会写出「解码器接但这份构建没编那个方案」。
这句话可以推广成一条排查习惯:任何跟硬件相关的参数,都以本机实测为准。 别人的命令、教程里的参数,只能当方向,不能当依据。
五、动手 Demo:h264 的五种硬件配置,逐条读
读一个具体解码器声明的硬件配置:每条有设备类型号、像素格式、以及「这份构建判定可用吗」。 注意「在表里」和「可用」是两个不同的字段,别混着看。
import av
DEV = {4: u"dxva2", 0: u"d3d11va", 7: u"d3d11", 12: u"d3d12", 2: u"cuda"}
c = av.codec.Codec(u"h264", u"r")
cfg = c.hardware_configs or []
print(u"h264 的硬件配置数 %d" % len(cfg))
ok = 0
for h in cfg:
dt = int(h.device_type)
name = DEV.get(dt, u"类型%d" % dt)
print(u"%-10s %-12s 可用=%s" % (name, h.format.name, h.is_supported))
if h.is_supported:
ok += 1
print(u"其中可用 %d 条" % ok)
实跑输出:
--------------------------------------------------------------------
3.11.8 -hwaccels——硬件加速有哪几种
--------------------------------------------------------------------
**① 硬件加速不是一种东西,是一族互不兼容的方案**
方案 平台 典型名字
----------------------------------------------------------
DXVA2 Windows(老) dxva2
D3D11VA Windows 8 以上 d3d11va
NVDEC/NVENC NVIDIA 显卡 cuda/cuvid/nvenc
VAAPI Linux 核显 vaapi
VideoToolbox macOS videotoolbox
**这五种之间不能互换:在 Windows 上写的 vaapi 参数,移到 Mac 上一定不认。**
**所以「硬件加速能不能用」这个问题,必须先问「在哪台机器上」。**
**② 本机 h264 解码器的五种硬件配置,逐个列出来**
序号 设备类型 像素格式 本机支持
--------------------------------------------------
4 dxva2 dxva2_vld 是
0 d3d11va d3d11va_vld 否
7 d3d11 d3d11 是
12 d3d12 d3d12 是
2 cuda cuda 是
**本机 h264 有 4 种硬件配置可用:dxva2、d3d11、d3d12、cuda。**
**注意有一项标了「否」——它在表里,但这份构建判定不可用。**
**「在表里」和「能用」是两个状态,跟 3.11.4 里设备组件那一节是同一个道理。**
**③ 硬件加速的三种用法,代价完全不同**
用法 参数形态 代价
---------------------------------------------------------------
只解不编 -hwaccel dxva2 解码快,编码还在 CPU
只编不解 -c:v h264_nvenc 编码快,解码还在 CPU
全硬 两边都指定 最快,但画质与兼容性都受限
**第三行的代价要说清楚:硬件编码器为了速度会牺牲压缩效率,**
**同样码率下画质通常不如 x264 的 slow preset,而且参数可调的范围小得多。**
**④ 这一节的结论只有一句**
**硬件加速能不能用、用哪一条,只能「在这台机器上查」,不能「按经验写」。**
**`ffmpeg -hwaccels` 给出的是这份构建支持的方案列表,**
**而 `-h decoder=h264` 里那一段才是「这个解码器具体能接哪些」。**
**两个都要查,少查一个就会写出「参数不认」的命令。**
五行里有一条是「可用=False」,那一条就是「在表里但走不通」的典型。 如果只看配置数量(5 条)就断定「这台机器有五种硬解」,那就错了。
device_type 是个数字,不是名字。
数字与名字的对应关系在 SDL/FFmpeg 的头文件里,代码里这张 DEV 表是照那份定义填的。
写脚本时别自己猜数字,用常量名去比。
这一段只能证明「解码器接受这些硬件方案」,不能证明「真的跑起来了」。 真跑要真 exe 加真显卡,沙箱两样都没有,所以文案只能写到这一层。
30 秒实验
- 列方案:
ffmpeg -hwaccels,看这份构建支持哪几种。 - 看解码器能接哪些:
ffmpeg -h decoder=h264,往下找 hardware 那一段。 - 只解不编:
ffmpeg -hwaccel dxva2 -i 片子.mp4 -c:v libx264 出.mp4,只给解码提速。
常见误区
- 以为硬件加速是「一种开关」。它是一族互不兼容的方案,换平台就得换参数。
- 看到配置数就当成可用数。表里有的条目可能标着「不可用」,要逐条看。
- 全硬编码就为了快。硬件编码器压缩效率低、参数少,画质通常不如 x264。
自测三问(点开对答案)
1. 为什么 Windows 上写的 vaapi 参数换到 Mac 必然不认? —— 因为硬件加速方案按平台分,vaapi 是 Linux 的接口,Mac 用的是 VideoToolbox。 2. 「硬件配置数 5」能直接说成「支持 5 种硬解」吗? —— 不能。其中可能有条目标着 `is_supported=False`,那是「在表里但这份构建判定不可用」。 3. 只想让播放变快又不想掉画质,该加什么? —— 只加解码侧的 `-hwaccel`,编码仍用 libx264,这样画质不受影响。- ☐ (本节完,下一节 3.11.9 -layouts)