Javascript DOMException:关联的 Track 处于无效状态

we_*_*mor 5 javascript domexception mediadevices

我正在尝试在 nodeJS 服务器上创建照片捕获 Web 应用程序,并且我正在使用下面的javascript代码。

const btn = document.querySelector('#btn');

btn.addEventListener('click', (event) => {
 navigator.mediaDevices.getUserMedia({video: true})
  .then(gotMedia)
  .catch(error => console.error('getUserMedia() error:', error));

  event.preventDefault()
})
Run Code Online (Sandbox Code Playgroud)

而gotMedia函数是这样的:

function gotMedia(mediaStream) {
    const mediaStreamTrack = mediaStream.getVideoTracks()[0];
    const imageCapture = new ImageCapture(mediaStreamTrack);
    console.log(imageCapture);

    const canvas = document.querySelector('canvas');
    // ...
    imageCapture.grabFrame()
    .then(imageBitmap => {
        canvas.width = imageBitmap.width;
        canvas.height = imageBitmap.height;
        canvas.getContext('2d').drawImage(imageBitmap, 0, 0);
    })
    .catch(error => console.error('grabFrame() error:', error));
}
Run Code Online (Sandbox Code Playgroud)

一切正常,图像捕捉正常,但是当我一张又一张地快速拍摄照片时,出现错误,提示:

grabFrame() 错误:DOMException:关联的 Track 处于无效状态。

当我拍摄太多照片时(例如快速单击约 20 秒以上),通常会发生这种情况,但前五张快照也会发生这种情况。有谁知道发生了什么事以及我应该改变什么才能解决这个问题?感谢您的时间。

小智 6

根据规范,此类错误可能是由于不可接受的状态造成的。在铬源中我发现了这种方法

我已经使用这样的代码克服了错误:

  const promise = getPrevImagePromise();

  if (!promise && !(imageCapture.track.readyState != 'live' || !imageCapture.track.enabled || imageCapture.track.muted)) {
    const imagePromise = imageCapture.grabFrame()
      .then((image) => {
        // do work with image
      })
      .then(() => {
        deletePrevImagePromise()
      })
      .catch((error) => {
        // 
      });

    setPrevImagePromise(imagePromise);
  }
Run Code Online (Sandbox Code Playgroud)


hun*_*tis 2

我遇到了同样的问题,无法让前沿grabFrame功能可靠地工作。

相反,您可以从中间视频源进行绘制。在你的函数中,它看起来像这样(未经测试):

function gotMedia(mediaStream) {
    const mediaStreamTrack = mediaStream.getVideoTracks()[0];
    const canvas = document.querySelector('canvas');
    const video = document.createElement('video');

    video.autoplay = true;
    video.srcObject = mediaStream;
    video.onplay = () => {
         canvas.width = video.videoWidth;
         canvas.height = video.videoHeight;
         canvas.getContext('2d').drawImage(video, 0, 0);
    };
}
Run Code Online (Sandbox Code Playgroud)

当然,如果您要捕获大量帧,最好在流旁边创建一个视频并每次都从中捕获。