如果您在 Linux 上使用多个摄像头通过 OBS 进行直播,您可能会注意到摄像头是在启动时检测到时加载的。 通常情况下,您可能不会对此进行过多考虑,但是如果您有一个使用复杂 OBS 模板的永久直播设置,则需要知道物理世界中的哪个摄像头将显示在虚拟世界中的哪个屏幕上。 换句话说,您不希望今天将一个设备分配为摄像头 A,而明天却最终成为摄像头 B。
为了标准化复杂的摄像头设置,您可以对摄像头如何在 Linux 文件系统中分配位置施加一些特殊规则。
udev 子系统
Linux 上处理硬件外围设备的系统称为 udev。 它检测并管理您插入计算机的所有设备。 您可能没有意识到它,因为它没有引起太多注意,尽管当您插入 USB 拇指驱动器以在桌面上打开或连接打印机时,您肯定与之交互过。
硬件检测
假设您有两个 USB 摄像头:一个在您计算机的左侧,另一个在右侧。 左侧摄像头拍摄特写镜头,右侧摄像头拍摄远景镜头,并且您在直播期间在两者之间切换。 在 OBS 中,您将每个摄像头添加到“来源”面板,并直观地将一个称为“camLEFT”,另一个称为“camRIGHT”。
假设最坏的情况,假设您有两个相同的摄像头:它们是相同的品牌和相同的型号。 这是最坏的情况,因为当两个硬件部件相同时,它们几乎没有唯一的 ID,供您的计算机将它们彼此区分开。
不过,这个难题有一个解决方案,它只需要使用一些简单的终端命令进行一些调查。
1. 获取供应商和产品 ID
首先,将一个摄像头插入您要分配给它的 USB 端口。 然后发出此命令
$ lsusb
Bus 006 Device 002: ID 0951:1666 Kingston Technology DataTraveler G4
Bus 005 Device 003: ID 03f0:3817 Hewlett-Packard LaserJet P2015 series
Bus 003 Device 006: ID 045e:0779 Microsoft Corp. LifeCam HD-3000
Bus 003 Device 002: ID 8087:0025 Intel Corp.
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 046d:c216 Logitech, Inc. Dual Action Gamepad
Bus 001 Device 002: ID 048d:5702 Integrated Technology Express, Inc.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
[...]
您通常可以专门搜索字符串“cam”来缩小结果范围,因为大多数(但不是全部)摄像头都报告为摄像头。
$ lsusb | grep -i cam
Bus 003 Device 006: ID 045e:0779 Microsoft Corp. LifeCam HD-3000
这里有很多信息。 ID 列为 045e:0779
。 第一个数字是供应商 ID,第二个是产品 ID。 将它们写下来,因为您稍后会需要它们。
2. 获取 USB 标识符
您还获得了摄像头的设备路径:总线 3,设备 6。 Linux 中有一句谚语“一切皆文件”,实际上,USB 设备在 udev 中被描述为以 /dev/bus/usb/
开头并以总线(在本例中为 003)和设备(在本例中为 006)结尾的文件路径。 查看 lsusb
输出中的总线和设备编号。 它们告诉您此摄像头位于 /dev/bus/usb/003/006
。
您可以使用 udevadm
命令来获取内核为此 USB 设备的指示符
$ sudo udevadm info \
--attribute-walk \
/dev/bus/usb/003/006 | grep "KERNEL="
KERNEL=="3-6.2.1"
在此示例中,内核 USB 标识符为 3-6.2.1
。 写下您系统的标识符,因为您稍后也需要它。
3. 为每个摄像头重复
将另一个摄像头(或多个摄像头,如果您有两个以上)连接到您要分配给它的 USB 端口。 这与您用于另一个摄像头的 USB 端口不同!
重复该过程,获取供应商和产品 ID(如果摄像头是相同的制造商和型号,则这些 ID 应与第一个相同)以及内核 USB 标识符。
$ lsusb | grep -i cam
Bus 001 Device 004: ID 045e:0779 Microsoft Corp. LifeCam HD-3000
$ sudo udevadm info \
--attribute-walk \
/dev/bus/usb/001/004 | grep "KERNEL="
KERNEL=="1-6"
在此示例中,我已经确定我的摄像头连接到 1-6 和 3-6.2.1(第一个是我机器上的 USB 端口,另一个是插入插入我机器的监视器的集线器,这就是为什么一个比另一个更复杂)。
编写 udev 规则
您拥有所需的一切,因此现在您可以编写一个规则,告诉 udev 在特定 USB 端口找到摄像头时,为每个摄像头提供一致的标识符。
创建并打开一个名为 /etc/udev/rules.d/50-camera.conf
的文件,并输入以下两个规则,使用适合您自己系统的供应商和产品 ID 以及内核标识符
SUBSYSTEM=="usb", KERNEL=="1-6", ATTR{idVendor}=="045e", ATTR{idProduct}=="0779", SYMLINK+="video100"
SUBSYSTEM=="usb", KERNEL=="3-6.2.1", ATTR{idVendor}=="045e", ATTR{idProduct}=="0779", SYMLINK+="video101"
这些规则告诉 udev,当它在这些特定的 USB 位置找到与特定供应商和产品 ID 匹配的设备时,创建名为 video100
和 video101
的符号链接(有时也称为“别名”)。 符号链接在很大程度上是任意的。 我给它们较高的数字,以便它们易于发现,并且因为该数字不得与现有设备冲突。 如果您实际上在计算机上连接了 101 个以上的摄像头,请使用 video200
和 video201
以确保安全(并保持联系!我很想了解更多关于那个项目的信息)。
重启
重启您的计算机。 您现在可以保持摄像头连接,但这实际上并不重要。 一旦 udev 加载了规则,它就会遵循这些规则,无论设备是在启动期间连接还是稍后插入。
许多人说 Linux 永远不需要重启,但是 udev 在启动期间加载其规则,此外,您想证明您的 udev 规则在重启后仍然有效。
一旦您的计算机重新启动并运行,请查看 /dev/video
,摄像头在此处注册
$ ls -1 /dev/video*
/dev/video0
/dev/video1
/dev/video100
/dev/video101
/dev/video2
/dev/video3
如您所见,video100
和 video101
处有条目。 今天,这些是到 /dev/video2
和 /dev/video3
的符号链接,但明天它们可能是到 /dev/video1
和 /dev/video2
的符号链接,或基于 Linux 何时检测到并为其分配文件的任何其他组合。

(图片由 Jeff Siepman 拍摄)
不过,您可以在 OBS 中使用符号链接,这样 camLEFT 始终是 camLEFT,而 camRIGHT 始终是 camRIGHT。
评论已关闭。