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

设备是一种特殊的 demuxer:没有扩展名,必须用 -f 指定。 这份 Windows 构建里有 dshow、gdigrab、vfwcap 三个,Mac 与 Linux 的一个都没有。

📝 本节和前面几节的关系

3.11.3 讲的是「读文件」,这一节讲「读设备」。 设备这一类的坑不在参数,在「有组件」和「有设备」分不清。

一、为什么设备必须用 -f 指定

普通文件能靠扩展名猜,设备没有扩展名,所以只能显式说:

-f dshow 这句不是「选一个设备」,是「告诉 ffmpeg 接下来的输入归 dshow 管」。 具体用哪个摄像头,要在 -i 里再写 video=名字。

写法 意思 漏了会怎样


-f dshow 接下来的输入按 dshow 解 当成文件打开,报找不到 -list_devices true 只列设备,不打开 不知道设备名,无法填 -i -f gdigrab 抓屏幕 当文件打开,必然失败

这就是 1.2 里「装完先试 -list_devices true」的原因: 先看有哪些设备,再拿名字去填 -i,而不是先写命令再猜名字。

二、本机三个组件,逐个试

把常见的八个设备组件逐个探测,看这份构建里编进了哪些:

组件 管什么 本机有吗 方向


dshow Windows 摄像头与声卡 有 读 gdigrab 抓屏幕 有 读 vfwcap 老的 VfW 摄像头 有 读 avfoundation macOS 采集 没有 — x11grab Linux 抓屏幕 没有 — alsa Linux 声卡 没有 — pulse Linux 声音服务 没有 — decklink 专业采集卡 没有 —

本机正好有 dshow、gdigrab、vfwcap 三个,就是 Windows 那一套。 Mac 与 Linux 的那几个全没有,因为这是一份 Windows 构建。

这个结果本身就是一条可用的信息: 在这台机器上能写的采集命令,换到服务器上跑,第一句 -f x11grab 就会报错。 原因不是权限,是那份构建根本没编这个组件。

三、有组件不等于有设备

这是本节最要紧的一句话,要分三层看:

层次 查什么 查不到说明


组件层 -devices 换一份构建 设备层 -list_devices true 插设备、查权限 参数层 -h demuxer=dshow 查参数名

dshow 组件在,只代表「这份库会调 DirectShow 接口」。 机器上到底有没有摄像头、能不能被访问,得走第二层才知道。

沙箱里没有摄像头,所以这一节只能验到组件层。 第二层要真设备、第三层要真 exe——两层都超出这里的能力范围,不假装测过。

四、动手 Demo:八个设备组件,逐个探

Python 这一层没有「列出设备组件」的接口,只能拿名字逐个去试。 试的办法是「按这个名字打开一个输入容器」,成功就说明组件在。 注意这一步验的是「组件在不在」,不是「设备有没有」。

import av

DEV = [(u"dshow", u"Windows 摄像头与声卡"),
       (u"gdigrab", u"抓屏幕"),
       (u"vfwcap", u"老的 VfW 摄像头"),
       (u"avfoundation", u"macOS 采集"),
       (u"x11grab", u"Linux 抓屏幕"),
       (u"alsa", u"Linux 声卡"),
       (u"pulse", u"Linux 声音服务"),
       (u"decklink", u"专业采集卡")]

for name, use in DEV:
    try:
        av.format.ContainerFormat(name)
        print(u"有  %-14s %s" % (name, use))
    except Exception:
        print(u"没有 %-14s %s" % (name, use))

实跑输出:

--------------------------------------------------------------------
3.11.4 -devices——输入设备这一类特殊 demuxer
--------------------------------------------------------------------

**① 设备是 demuxer 的一种,但必须用 -f 指定**

**普通文件能靠扩展名猜,设备没有扩展名,所以必须 `-f dshow` 这样说。**
**这也是 1.2 里「装完要先试 `-list_devices true`」的原因——先看有哪些设备。**

**② 本机这份构建里的设备组件,逐个试**

  组件             管什么                   本机有吗     方向
  ---------------------------------------------------------------
  dshow            Windows 摄像头与声卡     有           读
  gdigrab          抓屏幕                   有           读
  vfwcap           老的 VfW 摄像头          有           读
  avfoundation     macOS 采集               没有         —
  x11grab          Linux 抓屏幕             没有         —
  alsa             Linux 声卡               没有         —
  pulse            Linux 声音服务           没有         —
  decklink         专业采集卡               没有         —

**本机有 3 个:dshow、gdigrab、vfwcap——正好是 Windows 那三个。**
**Mac 与 Linux 的那几个全没有,因为这是一份 Windows 构建。**

**③ 有组件不等于有设备**

**这句话要分开看:`dshow` 组件在,只代表「这份库会调 DirectShow 接口」;**
**机器上到底有没有摄像头、能不能被访问,要 `-list_devices true` 才知道。**

  层次       查什么                 查不到说明
  ----------------------------------------------------
  组件层     -devices               换一份构建
  设备层     -list_devices true     插设备、查权限
  参数层     -h demuxer=dshow       查参数名

**沙箱里没有摄像头,所以这一节只能验到组件层。**
**第二层要真设备,第三层要真 exe——两层都超出这里的能力范围,文案里不假装测过。**

打出来的「有」只有三行:dshow、gdigrab、vfwcap。 这三行合起来就是 Windows 上的全部采集途径:摄像头、屏幕、老式摄像头。

这一步能证明的是「组件注册了」,不能证明「设备可用」。 组件只是「会调那个系统接口」,设备要另外查——中间差着一层权限和驱动。

所以千万别把「组件在」当成「能录」:真的写采集命令时,先跑 -list_devices true。 这一步在沙箱里做不了,因为确实没有摄像头;强行写出来就成了编造。

30 秒实验

  1. 列组件:ffmpeg -devices,看是 D 开头还是 E 开头,设备的 D 表示能读。
  2. 列设备:ffmpeg -f dshow -list_devices true -i dummy,看真实设备名。
  3. 录屏幕:ffmpeg -f gdigrab -i desktop -t 5 出.mp4,Windows 上可用,别处不行。

常见误区

  1. 以为 -devices 里有名字就代表能录。组件只说明「会调那个接口」,设备要另外查。
  2. 在 Linux 服务器上跑 -f gdigrab。那是 Windows 专用组件,那份构建里根本没有。
  3. 采集时不写 -f。设备没有扩展名可猜,必然被当成文件打开,然后报找不到。
自测三问(点开对答案) 1. 为什么采集设备必须显式写 `-f`? —— 因为设备没有扩展名,ffmpeg 无法靠后缀猜格式,只能由 `-f` 指定用哪个设备组件。 2. `-devices` 里有 dshow,是否说明这台机器能录摄像头? —— 不能。组件只表示这份构建会调 DirectShow 接口,有没有设备要 `-list_devices true` 才知道。 3. 为什么沙箱里只能验到组件层? —— 因为没有真实采集设备和 ffmpeg 可执行文件,设备层与参数层都没法验,只能老实标注。

相关笔记