getUserMedia()的回调事件

时间:2017-01-25 15:28:24

标签: javascript getusermedia

我正在尝试使用navigator.mediaDevices.getUserMedia()canvas.getContext('2d').drawImage()功能从我的网络摄像头拍摄快照。

当我这样做时,它完美地运作:

function init(){
  myVideo = document.getElementById("myVideo") 
  myCanvas = document.getElementById("myCanvas");
  videoWidth = myCanvas.width;
  videoHeight = myCanvas.height;
    
  startVideoStream();
}

function startVideoStream(){
  navigator.mediaDevices.getUserMedia({audio: false, video: { width: videoWidth, height: videoHeight }}).then(function(stream) {
    myVideo.src = URL.createObjectURL(stream);
  }).catch(function(err) {
      console.log("Unable to get video stream: " + err);
  });
}

function snapshot(){
  myCanvas.getContext('2d').drawImage(myVideo, 0, 0, videoWidth, videoHeight);
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="debug.js"></script>
</head>
<body onload="init()">
    <div id="mainContainer">
        <video id="myVideo" width="640" height="480" autoplay style="display: inline;"></video>
        <canvas id="myCanvas" width="640" height="480" style="display: inline;"></canvas>
        <input type="button" id="snapshotButton" value="Snapshot" onclick="snapshot()"/>
    </div>
</body>
</html>

问题是,我不想使用按钮单击来拍摄快照,而是在加载相机流后立即拍摄快照。 我尝试在设置视频源后直接调用snapshot()函数:

function init(){
  myVideo = document.getElementById("myVideo") 
  myCanvas = document.getElementById("myCanvas");
  videoWidth = myCanvas.width;
  videoHeight = myCanvas.height;
    
  startVideoStream();
}

function startVideoStream(){
  navigator.mediaDevices.getUserMedia({audio: false, video: { width: videoWidth, height: videoHeight }}).then(function(stream) {
    myVideo.src = URL.createObjectURL(stream);
    snapshot();
  }).catch(function(err) {
      console.log("Unable to get video stream: " + err);
  });
}

function snapshot(){
  myCanvas.getContext('2d').drawImage(myVideo, 0, 0, videoWidth, videoHeight);
}

但它不起作用。我的画布保持白色。我想这是因为此时相机流没有完全加载。

是否还有其他事件被触发,我可以在加载相机Feed后立即绘制快照?还是我完全走错了路?

提前致谢!

1 个答案:

答案 0 :(得分:4)

等待loadedmetadata事件:

navigator.mediaDevices.getUserMedia({video: true})
  .then(stream => {
    video.srcObject = stream;
    return new Promise(resolve => video.onloadedmetadata = resolve);
  })
  .then(() => canvas.getContext('2d').drawImage(video, 0, 0, 160, 120))
  .catch(e => console.log(e));
<video id="video" width="160" height="120" autoplay></video>
<canvas id="canvas" width="160" height="120"></canvas>

以上内容适用于所有浏览器(使用WebRTC)。

在Chrome中,您也可以执行this - 但play()尚未在任何其他浏览器中返回承诺。

另请注意,URL.createObjectURL(stream)已弃用。使用srcObject

更新:感谢@KyleMcDonald在评论中指出了同步注册loadedmetadata侦听器与设置srcObject! - 代码更新的重要性。