在页面上显示设备标签

时间:2018-11-12 18:44:40

标签: javascript webrtc getusermedia

我正在编写一个Web应用程序,用户可以在其中使用他的相机(并选择要使用的相机)。问题是我希望用户可以在启用相机之前选择它。在当前代码中,当用户打开页面时,他看到一个空的摄像机列表,并且在启用摄像机流时,下拉列表中会填充摄像机名称。我希望他打开该网页时填充下拉列表。

P.S。当我stop()相机时,它会禁用相机并仅显示黑屏。为什么是黑色而不是背景色?

CameraStreamView.cshtml

@using Api.Models
@{
    ViewBag.Title = "Smart Vision";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="~/Content/Contact-Form-Clean.css">
</head>

<body onpageshow="Init()">
<div id="container">
    <video id="video" style="display: block; margin: 0 auto; margin-top: 30px;" width="300" height="400" autoplay></video>
    <button id="enableStream" style="display: block; margin: 0 auto; margin-top: 20px; height: 70px; width: 200px" onclick="start()">Enable camera</button>
    <button id="disableStream" style="display: block; margin: 0 auto; margin-top: 20px; height: 70px; width: 200px" onclick="stop()">Disable camera</button>
    <label for="videoSource">Video source: </label><select id="videoSource"></select>
</div>

<script src="~/Scripts/GetCameraFeed.js"></script>
</body>
</html>

GetCameraFeed.js

const videoSelect = document.querySelector('select#videoSource');
const selectors = [videoSelect];

function gotDevices(deviceInfos) {
    // Handles being called several times to update labels. Preserve values.
    const values = selectors.map(select => select.value);
    selectors.forEach(select => {
        while (select.firstChild) {
            select.removeChild(select.firstChild);
        }
    });
    for (let i = 0; i !== deviceInfos.length; ++i) {
        const deviceInfo = deviceInfos[i];
        const option = document.createElement('option');
        option.value = deviceInfo.deviceId;
        if (deviceInfo.kind === 'videoinput') {
            option.text = deviceInfo.label;
            videoSelect.appendChild(option);
        }
    }
    selectors.forEach((select, selectorIndex) => {
        if (Array.prototype.slice.call(select.childNodes).some(n => n.value === values[selectorIndex])) {
            select.value = values[selectorIndex];
        }
    });
}

function Init() {
    navigator.mediaDevices.enumerateDevices().then(gotDevices).catch(handleError);
}


function gotStream(stream) {
    window.stream = stream; // make stream available to console
    video.srcObject = stream;
    // Refresh button list in case labels have become available
    return navigator.mediaDevices.enumerateDevices();
}

function handleError(error) {
    console.log('navigator.getUserMedia error: ', error);
}

function start() {
    const videoSource = videoSelect.value;
    const constraints = {
        video: { deviceId: videoSource ? { exact: videoSource } : undefined }
    };
    navigator.mediaDevices.getUserMedia(constraints).then(gotStream).then(gotDevices).catch(handleError);
}

function stop() {
    video.pause();
    video.src = "";
    stream.getTracks().forEach(track => track.stop());
    console.log("Stopping stream");
}

1 个答案:

答案 0 :(得分:0)

由于explicitly disallowed的问题,您想要的是fingerprinting。有关用户设置的详细信息,使网站可以在Web上唯一地标识它们,这是隐私问题。

一旦用户使用其摄像头和麦克风信任您的网站,该信息就被认为与共享有关。

由于以下几个原因,工作组认为这是一个合理的折衷方案:

  1. 大多数台式机用户只有一个摄像头或一个摄像头。
  2. 大多数电话用户有两个,但是您可以使用facingMode约束来选择。
  3. 鉴于1和2,对于大多数人来说,预先选择可以说是次等的用户体验。

我会考虑更改您的代码以首次请求默认相机,并让用户可以选择是否需要更改默认相机。大多数WebRTC网站都是这样做的。

请注意,这仅是用户首次访问您的网站时出现的问题。如果他们过去仅授予过一次摄像头或麦克风,那么您至少应该在Chrome中能够看到标签。

与Chrome不同,Firefox不会隐式保留权限,因此您需要做更多的工作才能在重复访问时获得页面加载标签:

enumerateDevices为每个设备返回一个deviceId,只要用户至少(或将在此会话中授予)摄像头或麦克风一次,该设备就会在您的站点上保留。您可以使用Cookie或本地存储将deviceId与设备标签相关联。这也可以使人们在Chrome中手动撤消权限而幸免。