Linux 录屏用 x11grab,输入写 :0.0,但 -video_size 必须自己给。 这跟 gdigrab 正好相反——那边能自己问系统桌面多大。
9.6.1 是 Windows 录屏,这一节是 Linux。 顺带把三平台的录屏写法摆在一起,也把「录屏加小窗」接回第七章。
一、一条命令录全屏
同样是录屏,Linux 这边的输入串不一样。
ffmpeg -f x11grab -video_size 1920x1080 -framerate 25 \
-i :0.0 -c:v libx264 -preset veryfast -crf 23 out.mp4
参数 作用
-f x11grab X11 桌面抓取接口 -i :0.0 屏幕号点显示号,第一块屏 -video_size WxH 必写,不给就报错 -framerate 25 抓多少帧 -draw_mouse 0 不要光标就写 0
:0.0 的意思是「第 0 号 X 服务器上的第 0 号屏幕」。
单屏机器上写 :0.0 或 :0 都行,多屏要写 :0.1。
-video_size 在 x11grab 上是必写项,这一点跟 gdigrab 不一样。
gdigrab 能自己问系统「桌面多大」,x11grab 不会——
不给就是抓 0×0,等于什么都没抓到。
二、实测:本机三条 Linux 通路一条都没有
x11grab、kmsgrab、v4l2 三个全在这里试一遍。
接口 参数 结果
x11grab :0.0 ValueError kmsgrab (空) ValueError v4l2 /dev/video0 ValueError
三条全是同一个错:no container format。
同一个错、同一个原因——这些接口在 Windows 版 FFmpeg 里没编进去。
所以这一节跟 9.5.1 一样,演示只到「证明没有」为止。 真正的录屏命令在 Linux 机器上照抄就能跑。
三、三平台录屏对照
录屏没有跨平台的统一写法,只有「接口名 + 输入串」不同。
平台 接口 输入怎么写
Windows gdigrab -i desktop 或 title=名字
Linux x11grab -i :0.0,必须给 -video_size
Linux 新路 kmsgrab -i -,要 root 与 DRM
macOS avfoundation -i "1:none"
这张表最有用的是最后一列:三种输入的写法差别很大, 一个写「desktop」、一个写「:0.0」、一个写「1:none」。 而后面那串编码参数,三个平台完全通用。
kmsgrab 是新路,绕过 X11 直接读显卡帧缓冲,
所以它能抓「没有桌面环境」的机器(比如纯控制台)。
代价是要 root 权限,而且要自己处理 DMA-BUF 到普通帧的转换,
用起来比 x11grab 麻烦不少。
四、录屏加摄像头小窗
这一条把两章接起来:采集是第九章,合成是第七章。
ffmpeg -f x11grab -video_size 1920x1080 -framerate 25 -i :0.0 \
-f v4l2 -video_size 640x480 -i /dev/video0 \
-filter_complex "[1:v]scale=320:180[p];[0:v][p]overlay=W-w-16:H-h-16" \
-c:v libx264 -preset veryfast out.mp4
[1:v] 是第二路输入(摄像头),先 scale 缩到 320×180,
再 overlay 贴到第一路(桌面)的右下角,W-w-16 就是「右边留 16 像素」。
注意这个坐标会算成奇数,而第七章量过:
overlay 会把奇数向下抹成偶数——所以实际落点会再往左或往上偏一像素。
写的时候不用管,看效果就行。
想做「屏幕加摄像头」的网课录制,这一条命令就够了, 不用装任何第三方录屏软件。
五、动手 Demo:确认三条 Linux 通路都没有,再看三平台对照
下面这段对 x11grab、kmsgrab、v4l2 各试一次。
再看一眼三平台录屏的输入串差在哪。
import av
def probe(fmt, arg):
c = None
try:
c = av.open(arg, format=fmt)
st = c.streams[0]
return u"打开成功 %dx%d" % (st.codec_context.width,
st.codec_context.height)
except Exception as e:
return u"%s: %s" % (type(e).__name__, str(e)[:36])
finally:
if c is not None:
c.close()
for fmt, arg in (("x11grab", ":0.0"),
("kmsgrab", ""),
("v4l2", "/dev/video0")):
print(u"%-9s %-14s -> %s" % (fmt, arg, probe(fmt, arg)))
print(u"本机 formats 里有 x11grab 吗:%s"
% ("x11grab" in av.formats_available))
实跑输出:
--------------------------------------------------------------------
9.6.2 Linux 系统中 FFmpeg 录屏
--------------------------------------------------------------------
**① 一条命令录全屏**
`ffmpeg -f x11grab -video_size 1920x1080 -framerate 25 \`
` -i :0.0 -c:v libx264 -preset veryfast -crf 23 out.mp4`
参数 作用
----------------------------------------------------------
-f x11grab X11 桌面抓取接口
-i :0.0 屏幕号 . 显示号,`:0.0` 是第一块屏
-video_size WxH **必写**,不给就抓不到
-framerate 25 抓多少帧
-draw_mouse 0 不要光标就写 0
**`-video_size` 在 x11grab 上是必写项,这跟 gdigrab 不一样——**
**gdigrab 能自己问系统桌面多大,x11grab 不会,不给就是报错。**
**② 实测:本机三条 Linux 通路,一条都没有**
接口 参数 结果 宽高
---------------------------------------------------
x11grab :0.0 ValueError —
kmsgrab ValueError —
v4l2 /dev/video0 ValueError —
**三条全是 `ValueError: no container format`——**
**同一个错,同一个原因:这些接口在 Windows 版 FFmpeg 里就没编进去。**
**③ 三平台录屏命令对照**
平台 接口 输入怎么写
---------------------------------------------------------------------
Windows gdigrab `-i desktop` 或 `-i title=窗口名`
Linux x11grab `-i :0.0`,且必须给 `-video_size`
Linux 新路 kmsgrab `-i -`,需要 root 与 DRM
macOS avfoundation `-i "1:none"`,1 是屏幕序号
**录屏这件事没有跨平台的统一写法,只有「接口名 + 输入串」不同。**
**编码参数那一半完全通用,所以换平台时只改前三个参数就够。**
**④ 录屏 + 摄像头画中画:把第七章拼回来**
`ffmpeg -f x11grab -video_size 1920x1080 -framerate 25 -i :0.0 \`
` -f v4l2 -video_size 640x480 -i /dev/video0 \`
` -filter_complex "[1:v]scale=320:180[p];[0:v][p]overlay=W-w-16:H-h-16" \`
` -c:v libx264 -preset veryfast out.mp4`
**这一条把两章接起来了:`x11grab` 是采集(第九章),**
**`scale` 加 `overlay` 是合成(第七章)。**
**所以「录屏带小窗」不用装第三方软件,一条命令就够。**
**注意 `overlay` 的坐标 `W-w-16` 与 `H-h-16` 会算成奇数,**
**而第七章量过:crop 与 overlay 都会把奇数向下抹成偶数,**
**所以实际落点是 `W-w-16` 再减一——写的时候不用管,看效果就行。**
**⑤ 录屏到底该不该用 FFmpeg**
场景 合适吗 为什么
--------------------------------------------------------
简单录一段存档 合适 一条命令,不用装软件
要剪辑、要标注 不合适 它只管录,不管编辑
要录带小窗 合适 overlay 一条命令搞定
要推直播 合适 录完直接换输出地址就行
**它的长处是「可编程」:所有参数都在命令行里,**
**能写进脚本、能被别的程序调用,这是图形界面录屏软件做不到的。**
三条全是 ValueError: no container format,连宽高都没读到。
"x11grab" in av.formats_available 也是 False——
这是最省事的一次判断:不用试开,查一下清单就知道有没有。
30 秒实验
- 把
x11grab换成gdigrab再跑一次:它会打开成功,差别一眼看出。 - 查一下
formats_available里有哪些grab:体会「接口按平台编」这件事。 - 在 Linux 上把
-video_size去掉:看它报的错跟沙箱里的错哪个更早出现。
常见误区
- x11grab 不写
-video_size。它不会自己问桌面多大,抓出来是 0×0。 - 多屏机器上还写
:0.0。第二块屏要写:0.1。 - 以为
kmsgrab跟x11grab一样简单。它要 root,还要自己做格式转换。
自测三问(点开对答案)
1. `x11grab` 跟 `gdigrab` 最大的差别是什么? —— x11grab 必须自己给 `-video_size`,gdigrab 能自己问系统桌面多大。 2. `:0.0` 这两个数字分别是什么? —— 第 0 号 X 服务器、第 0 号屏幕;多屏时第二个数字会变。 3. 录屏加小窗用了哪两章的技能? —— 采集用第九章的 x11grab 与 v4l2,合成用第七章的 scale 与 overlay。- ☐ 9.6.2 完,第九章收官——下一章 10.1 FFmpeg 在 Linux 系统中的安装