v4l2loopback

来自 ArchWiki

来自项目 仓库

v4l2loopback - 一个用于创建 V4L2 回环设备的内核模块
此模块允许您创建“虚拟视频设备”。普通 (v4l2) 应用程序将读取这些设备,就好像它们是普通的视频设备一样,但是视频将不会从例如采集卡读取,而是由另一个应用程序生成。

安装

安装 v4l2loopback-dkms 软件包目标内核/内核的头文件(参见 动态内核模块支持#安装)。例如,对于默认的 linux 内核,这将是 linux-headers。其他内核有各自的头文件软件包。

命令行实用程序由 v4l2loopback-utilsv4l-utils 提供。

本文中的许多用例示例也使用了 ffmpeg

加载内核模块

v4l2loopback 内核模块 可以通过 动态内核模块支持 加载

# modprobe v4l2loopback

v4l2-ctl 可用于列出所有视频设备,新的 v4l2loopback 设备应出现在其中

$ v4l2-ctl --list-devices

v4l2loopback 可以加载各种设备创建选项

# modprobe v4l2loopback video_nr=9 card_label=Video-Loopback exclusive_caps=1

这应该创建 /dev/video9 作为回环设备。exclusive_caps=1 对于某些基于 Chromium/WebRTC 的应用程序是必要的,例如 jitsi-meet-desktop-binAURzoomAUR。这将启用 exclusive_caps 模式,该模式仅排他性地报告 CAPTURE/OUTPUT 功能。新创建的设备将仅声明 OUTPUT 功能(因此普通网络摄像头应用程序(包括 Chrome)将看不到它)。一旦您将生产者连接到设备,它将开始仅声明 CAPTURE 功能(因此拒绝打开除捕获功能以外的其他功能的设备的应用程序也可以打开它)。更多选项可以在 官方文档 中找到。

如果模块已加载,则上述命令可能无效。模块必须先卸载,然后再重新加载

# modprobe -r v4l2loopback

有关更多详细信息,请参见 内核模块#手动模块处理

提示: 也可以使用 v4l2loopback-ctl 动态管理设备,而无需重新加载内核模块,如 官方文档 中所述。

可以通过使用 devices 参数创建多个回环设备。每个设备的选项通过逗号指定。以下命令创建三个回环设备,/dev/video8/dev/video9 和第一个可用的 /dev/videoX,所有设备都启用了 exclusive_caps

# modprobe v4l2loopback devices=3 video_nr=8,9 exclusive_caps=1,1,1 card_label="Loopback-1,Loopback-2,Loopback-3"

重启系统将卸载模块,但是可以在启动时自动加载模块以及自定义设备选项,如果一个回环设备用于内部网络摄像头,这将非常有用。有关详细信息,请参见 内核模块#自动模块加载官方文档

查看 v4l2loopback 视频源

注意: 只有在将流管道传输到 v4l2loopback 视频设备时,它才会输出视频,就像 #用例 中的示例一样。否则,许多应用程序甚至不会检测到视频设备。

位于 /dev/video0 的回环视频设备可以使用以下任何一种方式进行测试查看:ffplayffmpeg 的一部分),mpvgst-launchgstreamer 的一部分)

$ ffplay /dev/video0
$ mpv av://v4l2:/dev/video0
$ gst-launch-1.0 -v v4l2src device=/dev/video0 ! glimagesink

#加载内核模块 中所述,当使用 exclusive_caps=1 时,Chromium 和诸如 jitsi-meet-desktop-binAURzoomAUR 的应用程序应该能够使用回环设备作为虚拟网络摄像头,同时将视频流管道传输到其中。在浏览器中,可以在 webcamtests.com 上测试虚拟网络摄像头。

另请参见 网络摄像头设置#应用程序

提示: 如果您将视频流管道传输到视频设备,但您的应用程序未检测到它,请尝试使用和不使用 exclusive_caps=1
注意
  • 已报告了 Firefox 的各种其他问题。
  • 据报告,skypeforlinux-binAUR 检测到虚拟视频设备,但输出空白屏幕。

用例

注意: 由于 v4l2loopback 设备可以作为 v4l2 设备处理,因此许多应用程序可以与它们交互。有关 v4l2 设备 的更多信息,请参见 网络摄像头设置 文章。

通常,FFmpeg 与 v4l2loopback 结合使用非常方便,因为它可以将各种输入流转码为广泛支持的 yuv420p 像素格式,并使用 ffmpeg 参数 -vf format=yuv420p -f v4l2 将输出管道传输到 v4l2loopback 设备。请参阅本文中的以下示例。

FFmpeg 也可以使用 v4l2loopback 设备作为输入流。请参阅 FFmpeg#录制网络摄像头

GStreamer 也可以使用 v4l2loopback 设备作为 接收器

更多示例可以在 官方 v4l2loopback wiki 中找到。

提示: PipeWire 是一个即将推出的新的底层多媒体框架,它也可以完成 v4l2loopback 用于完成的一些事情。

屏幕投射

以下是如何通过将屏幕流式传输到 v4l2 回环设备来实现屏幕共享的示例,该设备可以用作虚拟网络摄像头。

使用 FFmpeg 投射 X11

注意: 这需要使用 exclusive_caps=1 #加载内核模块,并假定创建的视频设备为 /dev/video0

FFmpeg 可用于选择 X11 显示器上的区域,然后将其流式传输到 v4l2 回环设备

$ ffmpeg -f x11grab -select_region 1 -show_region 1 -framerate 25 -i $DISPLAY -vf format=yuv420p -f v4l2 /dev/video0

有关所有参数的说明,请参见 x11grab 文档

使用 wf-recorder 投射 Wayland

注意

安装 wf-recorder(或 wf-recorder-gitAUR)。要使用 wf-recorder 开始录制屏幕并将其流式传输到 v4l2 回环设备,请使用

$ wf-recorder --muxer=v4l2 --codec=rawvideo --file=/dev/video0 -x yuv420p

如果您遇到 Unknown V4L2 pixel format equivalent for rgb0,请使用 --force-yuv-t 运行 wf-recorder,以强制将数据转换为 yuv 格式,然后再将其发送到 GPU。 [1]

仅投射屏幕的特定区域
警告: 此方法不涉及单独应用程序共享的正确实现,因为在调整任何窗口大小后,共享区域不会更改。

如上所述,wf-recorder 能够仅通过首先使用 slurp 选择区域来记录屏幕的一部分。要使用此功能通过虚拟视频设备共享特定区域/应用程序窗口,请使用以下修改后的命令开始录制屏幕

$ wf-recorder -g "$(slurp)" --muxer=v4l2 --codec=rawvideo --file=/dev/video0 -x yuv420p

使用照片相机作为网络摄像头与 gPhoto

注意: 这需要使用 exclusive_caps=1 #加载内核模块,并假定创建的视频设备为 /dev/video0

如果安装了 gPhoto 并且可以与您的相机一起使用,则可以使用 gphoto2FFmpeg 将相机的实时取景流管道传输到 v4l2 回环设备

$ gphoto2 --stdout --capture-movie | ffmpeg -i - -vf format=yuv420p -f v4l2 /dev/video0

有关故障排除,请参阅 gPhoto#故障排除。这应适用于 官方 gPhoto 网站 上列出具有实时取景功能的所有相机。

使用网络流作为网络摄像头

注意: 这需要使用 exclusive_caps=1 #加载内核模块,并假定创建的视频设备为 /dev/video0

FFmpeg 可用于捕获网络流并将其管道传输到 v4l2 回环设备

$ ffmpeg -i http://ip_address:port/video -vf format=yuv420p -f v4l2 /dev/video0

使用 Android 设备作为网络摄像头

在 Android 上,可以使用 IP Webcam 广播网络视频流。然后,可以使用上面的命令将其管道传输到 v4l2 回环设备,并像网络摄像头一样使用它。IP Webcam 默认为端口 8080。

根据网络连接,通过 Wi-Fi 的网络流可能具有很大的延迟并且可能会断断续续。如果您已使用计算机和 Android 设备配置了 Android 调试桥,则可以使用 adb forward 通过 USB 电缆隧道传输流,这提供了更稳定的连接

$ adb wait-for-usb-device && adb forward tcp:8080 tcp:8080 && ffmpeg -i http://127.0.0.1:8080/video -vf format=yuv420p -f v4l2 /dev/video0

另一种更简单的方法是使用 scrcpy

$ scrcpy --video-source=camera --camera-id=0 --camera-size=1920x1080 --video-bit-rate=20M --v4l2-sink=/dev/video0 --no-playback
提示: 另一个选择是 Iriuniriunwebcam-binAUR

在视频会议中使用背景图像

有很多不同的选项可以在 Microsoft Teams 和 Zoom 等视频会议软件中隐藏/替换背景。

OBS

OBS 被流媒体用作实时视频管理系统,用于在视频源之间切换。它可以设置多个“场景”(例如,每个场景具有不同的背景图像),然后可以通过单击按钮来切换它们。它还可以提供其他视频滤镜,具有用于新滤镜的插件系统,可以同时显示多个视频源等等。它可以将其输出发送到 v4l2loopback 设备,该设备可与任何支持 V4L2 相机的应用程序一起使用。

要进行设置:

  1. 安装 主要的 obs-studio 软件包和 obs-backgroundremovalAUR 插件。
  2. 加载 obs 并将真实相机添加为场景的输入源。
  3. 右键单击源并编辑滤镜,然后添加背景移除滤镜。您现在应该看到背景被擦除,仅显示黑色。(您也可以选择模糊背景而不是移除它,在高级选项中。)
  4. 添加另一个类型为“图像”的输入源,然后选择您喜欢的背景图像。源类型也可以是视频文件或另一个网络摄像头,但先从图像开始,直到一切正常为止。
  5. 在源列表中拖动图像条目,使其低于视频源的条目,以便图像出现在视频后面而不是前面。
  6. 移动/调整背景图像的大小,使其占据场景的大部分。
  7. 启用虚拟输出,虚拟网络摄像头即可使用。

必须保持 obs 运行并启用虚拟输出,虚拟网络摄像头才能被视频会议软件使用。

如果您获得损坏或空白的图像(在更改输出分辨率后很常见),则可能需要删除并重新创建 V4L2 回环设备(或卸载并重新加载 v4l2loopback 模块)。

有关故障排除,请参阅上面的 #查看 v4l2loopback 视频源 - 如果这些程序可以正常播放源,则问题出在使用视频的应用程序。如果这些实用程序也无法正确看到视频,则问题出在回环设置上。

故障排除

Firefox

如果 Firefox 无法读取视频流并打印类似 AbortError: Starting video failed 的消息,请尝试预加载 v4l2compat.so

$ LD_PRELOAD=/usr/lib/v4l1compat.so firefox

ioctl(VIDIOC_G_FMT)

如果您在使用 ffmpeg 尝试使用视频设备时遇到 ioctl(VIDIOC_G_FMT) 错误,请尝试卸载并重新加载内核模块。 [2]

参见