设备是一种特殊的 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 秒实验
- 列组件:
ffmpeg -devices,看是D开头还是E开头,设备的D表示能读。 - 列设备:
ffmpeg -f dshow -list_devices true -i dummy,看真实设备名。 - 录屏幕:
ffmpeg -f gdigrab -i desktop -t 5 出.mp4,Windows 上可用,别处不行。
常见误区
- 以为
-devices里有名字就代表能录。组件只说明「会调那个接口」,设备要另外查。 - 在 Linux 服务器上跑
-f gdigrab。那是 Windows 专用组件,那份构建里根本没有。 - 采集时不写
-f。设备没有扩展名可猜,必然被当成文件打开,然后报找不到。
自测三问(点开对答案)
1. 为什么采集设备必须显式写 `-f`? —— 因为设备没有扩展名,ffmpeg 无法靠后缀猜格式,只能由 `-f` 指定用哪个设备组件。 2. `-devices` 里有 dshow,是否说明这台机器能录摄像头? —— 不能。组件只表示这份构建会调 DirectShow 接口,有没有设备要 `-list_devices true` 才知道。 3. 为什么沙箱里只能验到组件层? —— 因为没有真实采集设备和 ffmpeg 可执行文件,设备层与参数层都没法验,只能老实标注。- ☐ (本节完,下一节 3.11.5 -encoders)