【问题标题】:How can I get a unique ID for multiple USB devices (cameras) for WebRTC (javascript)?如何为 WebRTC (javascript) 获取多个 USB 设备(相机)的唯一 ID?
【发布时间】:2017-05-26 11:24:25
【问题描述】:

我正在 Windows 机器上开发,但目标平台是使用 Chromium 的 Raspberry Pi(这是可选的,任何浏览器都可以)。我将多个相机(比如十几个)连接到 Pi,显然甚至必须使用 USB 集线器。在下面的代码中,每次插入相机甚至是新的浏览器会话时,我似乎都会获得不同的设备 ID。我需要能够从特定的摄像头进行录制、录制视频或图像、打开/关闭摄像头等,但我无法做到这一点,除非我能为每个摄像头获取某种唯一标识符。

我也可以使用视频源标识符来识别摄像机(例如 /dev/video0、/dev/video1、... /dev/videon),但不确定如何在浏览器中执行此操作。

html:

<div id="container">
   <h1>Test  Page</h1>
   <div id="List"></div>
   <div class="select">
      <p><label for="videoSource">Video source: </label><select id="videoSource"></select></p>
      <p><label for="audioOutput">audioOutput source: </label><select id="audioOutput"></select></p>
      <p><label for="audioInput">audioInput source: </label><select id="audioInput"></select></p>
   </div>
   <video muted autoplay></video>
</div>

javascript:

<script>
    var DeviceInfo = "";
    var videoSelect = document.getElementById("videoSource");
    var audioOutputSelect = document.getElementById("audioOutput");
    var audioInputSelect = document.getElementById("audioInput");
    navigator.mediaDevices.enumerateDevices()
      .then(gotDevices)
      .catch(errorCallback);
    function gotDevices(deviceInfos) {
        alert("deviceInfos.length: " + deviceInfos.length);
        for (var i = 0; i !== deviceInfos.length; ++i) {
            var deviceInfo = deviceInfos[i];
            DeviceInfo += "<br>=================";
            for (var key in deviceInfo) {
                DeviceInfo += "<br>" + key + " => " + deviceInfo[key];
            }
            var option = document.createElement('option');
            option.value = deviceInfo.deviceId;
            if (deviceInfo.kind === 'audioinput') {
                option.text = deviceInfo.label ||
                'Microphone ' + (audioInputSelect.length + 1);
                audioInputSelect.appendChild(option);
            } else if (deviceInfo.kind === 'audiooutput') {
                option.text = deviceInfo.label || 'Speaker ' +
                (audioOutputSelect.length + 1);
                audioOutputSelect.appendChild(option);
            } else if (deviceInfo.kind === 'videoinput') {
                option.text = deviceInfo.label || 'Camera ' +
                (videoSelect.length + 1);
                videoSelect.appendChild(option);
            }
        }
        document.getElementById("List").innerHTML = DeviceInfo;
    }
    function errorCallback(err) {
        alert(err.name + ": " + err.message);
    }
</script>

样本输出:

=================
toJSON => function toJSON() { [native code] }
deviceId => 68KeeWjqTyTiECj/vjwuwWSMNXraaUu/sz5CDSnbNg0=
kind => videoinput
label =>
groupId =>
=================
toJSON => function toJSON() { [native code] }
deviceId => wuJ0e0dyB7bUyO3L6MHV6CD8v+FQRRZ0V9oSS/IMebg=
kind => videoinput
label =>
groupId =>
=================
toJSON => function toJSON() { [native code] }
deviceId => BdtXeGDVhh2g68rfu4cOg9yZoS7WdgTNr8nXOThLfPU=
kind => videoinput
label =>
groupId =>
=================
toJSON => function toJSON() { [native code] }
deviceId => mAc/SogzkQKpq8O3Zto64+SlOwsg1kKdXJLxua5t328=
kind => audioinput
label =>
groupId =>
=================
toJSON => function toJSON() { [native code] }
deviceId => n1or62DRNYW0zC4yQVox75nQhBZb0BYR9C/VWB1GLkM=
kind => audioinput
label =>
groupId =>
=================
toJSON => function toJSON() { [native code] }
deviceId => 74K5qAhhroD8esqAYW+9P8jxs4yvdWnPQ1Ia8OYJZqc=
kind => audioinput
label =>
groupId =>
=================
toJSON => function toJSON() { [native code] }
deviceId => rHIqRAFL4ZcfTqJc214llo5XxeDLm+pTG/DoicpOryM=
kind => audioinput
label =>
groupId =>

还要注意标签是空白的(Windows/Firefox),但在 Raspbian/Chromium 中我确实得到了标签。不幸的是它们不是唯一的(例如USB2.0相机(1871:0142))如果我能够以某种方式使用这些标签......这个page说标签“返回一个描述这个设备的标签的DOMString(例如”外部 USB 网络摄像头")。仅在活动 MediaStream 使用期间或已授予持久权限时可用。我不知道什么或如何做“持久权限”。

任何帮助表示赞赏。而且我愿意使用不同的技术,即 fswebcam 以某种方式链接到浏览器(自定义 URL)或 php 或其他任何东西。

【问题讨论】:

    标签: javascript raspberry-pi usb webrtc


    【解决方案1】:

    deviceId 就是那个 ID。出于隐私原因,它对页面的来源是唯一的,但在首次从您的来源向页面授予相机或麦克风权限后,它将像 cookie 一样在浏览会话中持续存在。之后,它应该会一直持续到用户清除他们的 cookie。

    换句话说,如果用户过去曾授予 getUserMedia 访问您的页面的权限,无论是昨天还是一年前,那么您现在获得的 id 将与他们当时在来自您的来源的页面中匹配,前提是用户从那时起没有清除他们的 cookie。

    在您完成此操作之前,label 字段也是空白的,再次出于隐私原因。

    拔出和重新插入设备应该无关紧要。 id 应该仍然可用。

    【讨论】:

    • Thanx @jib 但 id 确实发生了变化,那么它们如何被重用? Pi 可能会重新启动,然后我们必须重新编程所有内容以使用新 ID。
    • @Chiwda 我会隔离问题。 id 应该存储在类似 cookie 的存储中。它是否适用于您的常规桌面浏览器?如果是这样,那么您的树莓派版本中有一个错误。它有存储空间吗?最坏的情况,按照其他人的建议使用标签(正如我所提到的,他们还需要首先获得 gUM 成功)。
    • 它们 (ID) 在 Windows 10 和 Pi 上的工作方式相同。是的,我知道他们需要一个成功的 getUsermedia(),但根据定义,这意味着每次调用时都会重新创建它们。
    • @Chiwda 不,我的意思是:如果用户过去曾授予getUserMedia 访问您的页面的权限,无论是昨天还是一年前,那么您现在获得的 ID 将与当时的 ID 保持一致,在来自您的来源的页面中。用户只能通过清除 cookie 来重置此逻辑。
    • 即使是这样,也无济于事,因为我需要它们在用户之间保持一致。无论谁到达该页面,他们都应该得到正确的摄像机。
    【解决方案2】:

    我知道这是一篇旧帖子,但我遇到了类似的问题。当您启动带有 USB 摄像头的 pi 时,它们会显示为 /dev/video0、video1、video2 等。

    问题在于,在重新启动时,视频 0 的摄像头可能会在它们随机播放时变成视频 2。听起来有点像你的问题。

    我已经想出如何为每个摄像头提供一个地址,该地址仅反映它插入的 USB 孔,而不管它是哪个 videox。适用于所有具有相同序列号的相机。

    当我调用 fswebcam -d $realpath /dev/camUSB1 fred.jpg 时,它总是使用同一个摄像头,无论它被分配了什么 videox。

    如果您已经解决了这个问题(我希望如此),那么我将把它留在那里。如果不是,我将解释如何将相机连接到特定的 USB 插座。

    【讨论】:

    • 我的 USB 摄像头遇到了这个问题,我正在为我的 Jetson Nano 寻找解决方案,但 fswebcam 在那里不起作用。你有什么推荐的?
    【解决方案3】:

    好的 - 到这里 - 我会发布一些代码来完成所有这些,但我不了解网站规则..所以我只会描述它。

    目的是以与 USB 总线地址相对应的标识符结束,而与视频编号无关。将所有内容放入 udev 文件并激活它

    过程..

    反复运行 fswebcam 以收集有效视频号码列表。我发现大多数相机型号都是video0,1,2...但有些是video0,2,4,..

    现在 - 对于每个视频编号 videoX

    发出命令

    udevadm 信息 --attribute-walk --name=/dev/videoX > wwx (或任何视频编号)

    这会在 wwx 中生成一堆东西(或任何你想调用的文件)

    找到/提取(从 wwx)“KERNELS==1-1.3”或类似内容的行 - '==' 后面的位是 video0 的 USB 总线地址 ...

    现在生成一行,上面写着 "KERNEL=="videoX",SUBSYSTEM=="video4linux","KERNELS==1.1.3",SYMLINK+="xx"

    列出这些行。然后在 KERNELS== 字段上对列表进行排序。

    排序后向下列表并将xx替换为CAMUSB1,CAMUSB2,.....

    进程结束

    现在你有了一个 udev 文件(我叫我的 cam.rules) - 把它放在 /etc/udev/rule.d 中,运行 udevadm 触发器,工作就完成了

    这是一个真正的 cam.rules(这些摄像头连接为 video0,2,4,6 ....)

    KERNEL=="video0",SUBSYSTEM="video4linux",KERNELS=="1.1.3:1.0",SYMLINK+="camUSB1" KERNEL=="video2",SUBSYSTEM="video4linux",KERNELS=="1-1.1.1:1.0",SYMLINK+="camUSB2" KERNEL=="video4",SUBSYSTEM="video4linux",KERNELS=="1-1.1.3:1.0",SYMLINK+="camUSB3" KERNEL=="video6",SUBSYSTEM="video4linux",KERNELS=="1-1.1.4:1.0",SYMLINK+="camUSB4"

    现在 fswebcam -d $realpath CAMUSB1 ... 将始终为您提供相同的摄像头,无论它已分配什么 videoX 等等,并且它在重新启动时仍然存在,因为 USB 总线地址在重新启动时仍然存在。当然,您不必将其称为 camUSBx - 使用任何名称。

    我有一个 RPi python 2.7 程序可以完成这一切。我已经运行了几年了。如果我能找到如何传递它,欢迎您使用它。我没有使用 github 的经验 - 抱歉

    【讨论】:

      【解决方案4】:

      浏览器保持相同的 deviceid 可能是安全问题,网站可以通过使用 deviceid 来跟踪用户,例如浏览器 cookie。

      您可以从deviceInfo标签或MediaTrack标签中获取设备供应商名称,如果都来自同一供应商,则戳here。或者挖掘 chromium devices 并构建您的自定义版本。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-07-01
        • 1970-01-01
        • 2019-08-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-15
        • 2017-01-08
        相关资源
        最近更新 更多