在 pageshow 上获取设备标签

Get device labels onpageshow

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

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

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");
}

你要的是explicitly disallowed, due to fingerprinting关注。有关用户设置的详细信息让网站可以在网络上唯一地识别他们,这是一个隐私问题。

一旦用户使用他们的相机和微信信任您的网站phone,此信息就被认为与分享有关。

工作组认为这是一个合理的权衡,原因如下:

  1. 大多数桌面用户只有一个摄像头或 none。
  2. 大多数 phone 用户有两个,但您可以使用 facingMode 约束来选择。
  3. 给定 1 和 2,对于大多数人来说,预先选择可以说是较差的用户体验。

我会考虑更改您的代码以在第一次请求默认摄像头,并让用户可以选择在事后更改它,如果他们需要的话。这是大多数 WebRTC 网站所做的。

请注意,这应该只是用户第一次访问您的网站时出现的问题。如果他们过去只授予过一次相机或微型 phone,您应该能够看到标签,至少在 Chrome.

中是这样

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

enumerateDevices returns 每个设备一个 deviceId,如果用户已授予(或将在此会话中授予)摄像头或微型[=41,则为您的网站保留=] 至少一次。您可以使用 cookie 或本地存储将 deviceId 与设备标签相关联。这也使人们在 Chrome.

中手动撤销权限后仍然存在