将MediaDevices.enumerateDevices()的值分配给JavaScript中的全局变量

时间:2016-04-06 14:16:15

标签: javascript html5 mobile camera webrtc

我对JavaScript的顺序有疑问。我先告诉你我的代码:

这是我的HTML:

<video id="video" width="320" height="320" autoplay></video><br>
<button id="snap">Snap Photo</button><br>
<canvas id="canvas" width="320" height="320"></canvas>
<p id="pngHolder"></p>

这是我的JavaScript:

<script>
var Id;
//List cameras and microphones.
if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
    console.log("enumerateDevices() not supported.");
}
navigator.mediaDevices.enumerateDevices()
.then(function (devices) {
    devices.forEach(function (device) {
        if (device.kind == "videoinput" && device.label.indexOf('back') >= 0) {
            Id = device.deviceId;
            alert("ID 1 : " + Id);
        }
    });
})
.catch(function (err) {
    console.log(err.name + ": " + err.message);
});

// Put event listeners into place
window.addEventListener("DOMContentLoaded", function () {
    // Grab elements, create settings, etc.
    alert("ID 2 : "+ Id);
    var canvas = document.getElementById("canvas"),
        videoObj = {
            video: {
                optional: [{ deviceId: Id }]
            }
        },
        context = canvas.getContext("2d"),
        video = document.getElementById("video"),
        errBack = function (error) {
            console.log("Video capture error: ", error.code);
        };

    // Trigger photo take
    document.getElementById("snap").addEventListener("click", function () {
        context.drawImage(video, 0, 0, 640, 480);
        // Get the image
        var image = convertCanvasToImage(canvas);
        // Actions
        document.getElementById("pngHolder").appendChild(image);
        // Converts canvas to an image
        function convertCanvasToImage(canvas) {
            var image = new Image();
            image.src = canvas.toDataURL("image/png");
            return image;
        }
    });

    //alert("ID 2 : " + Id);
    // Put video listeners into place
    if (navigator.getUserMedia) { // Standard
        navigator.getUserMedia(videoObj, function (stream) {
            video.src = stream;
            video.play();
        }, errBack);
    } else if (navigator.webkitGetUserMedia) { // WebKit-prefixed
        navigator.webkitGetUserMedia(videoObj, function (stream) {
            video.src = window.webkitURL.createObjectURL(stream);
            video.play();
        }, errBack);
    } else if (navigator.mozGetUserMedia) { // Firefox-prefixed
        navigator.mozGetUserMedia(videoObj, function (stream) {
            video.src = window.URL.createObjectURL(stream);
            video.play();
        }, errBack);
    }
}, false);

我想将device.deviceId的值插入到我在JavaScript行的第一行中定义的变量Id中。它仍然是成功的(由alert("ID 1 : " + Id);显示)。但是,当我尝试将其放入optional: [{ deviceId: Id }]时,Id没有任何价值。

而且,当我尝试使用浏览器运行它时,我发现首先显示alert("ID 2 : " + Id);而不是alert("ID 1 : " + Id);。事实上,我已经将alert("ID 1 : " + Id);放在首位。我认为这就是变量仍为空的原因。

我的问题是如何将device.deviceId值插入optional: [{ deviceId: Id }]

2 个答案:

答案 0 :(得分:5)

navigator.mediaDevices.enumerateDevicesDOMContentLoaded正在竞争,而后者正在获胜,因此您需要在Id之前使用haveId

要解决此问题,请使用临时var haveId = navigator.mediaDevices.enumerateDevices() .then(devices => devices.find(d => d.kind == "videoinput" && d.label.indexOf("back") >= 0)); // Put event listeners into place window.addEventListener("DOMContentLoaded", function () { haveId.then(id => { // Grab elements, create settings, etc. alert("ID 2 : "+ id); var canvas = document.getElementById("canvas"), videoObj = { video: { deviceId: id } }, // <-- adapter.js constraints 承诺:

getUserMedia

Promise-chains创建依赖关系,这样sourceId代码就不会继续发生。

第二个问题是你正在混合新的outdated Chrome-specific constraints。使用adapter.js直到Chrome赶上,或者在紧要关头使用仅限Chrome的id parent_id name ----------------------------- 1 0 John 10 1 Anna 11 1 Doe 2 0 Brian 101 10 Chris (但在其他浏览器中无法使用)。

答案 1 :(得分:1)

navigator.mediaDevices.enumerateDevices()是异步的。它返回一个承诺(想想回调,但更高兴)。

您应该从那里触发对getUserMedia的调用,或者等待DOMContentLoaded和enumerateDevices,然后执行getUserMedia。