🎬 第三章 FFmpeg三大常用工具及应用选项详解
📄 一句话概括

硬件加速不是一个东西,是一族互不兼容的方案。 能不能用、用哪一条,只能在这台机器上查,不能按经验写。

📝 本节和前面几节的关系

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 秒实验

  1. 列方案:ffmpeg -hwaccels,看这份构建支持哪几种。
  2. 看解码器能接哪些:ffmpeg -h decoder=h264,往下找 hardware 那一段。
  3. 只解不编:ffmpeg -hwaccel dxva2 -i 片子.mp4 -c:v libx264 出.mp4,只给解码提速。

常见误区

  1. 以为硬件加速是「一种开关」。它是一族互不兼容的方案,换平台就得换参数。
  2. 看到配置数就当成可用数。表里有的条目可能标着「不可用」,要逐条看。
  3. 全硬编码就为了快。硬件编码器压缩效率低、参数少,画质通常不如 x264。
自测三问(点开对答案) 1. 为什么 Windows 上写的 vaapi 参数换到 Mac 必然不认? —— 因为硬件加速方案按平台分,vaapi 是 Linux 的接口,Mac 用的是 VideoToolbox。 2. 「硬件配置数 5」能直接说成「支持 5 种硬解」吗? —— 不能。其中可能有条目标着 `is_supported=False`,那是「在表里但这份构建判定不可用」。 3. 只想让播放变快又不想掉画质,该加什么? —— 只加解码侧的 `-hwaccel`,编码仍用 libx264,这样画质不受影响。

相关笔记