-1

给定代码

<!DOCTYPE html>
<html>

<head>
</head>

<body>
  <video width="320" height="280"></video>
  <script>
      const video = document.querySelector("video");
      const src = "https://mirrors.creativecommons.org/movingimages/webm/ScienceCommonsJesseDylan_240p.webm#t=0,10";
      let recorder;
      video.oncanplay = () => {
        video.play(); 
        const mediaStream = video.captureStream();
        recorder = new MediaRecorder(mediaStream);
        recorder.ondataavailable = event => 
          console.log(URL.createObjectURL(event.data));
        
        recorder.start();
      }

      video.onpause = () => recorder && recorder.stop();

      video.src = src;
  </script>
</body>

</html>

Chromium 浏览器使用 捕获<video>元素的回放.captureStream(), 以及实例事件的结果日志MediaRecorder()Blob URLBlobdataavailableMediaRecorder

在当前实现.mozCaptureStream()错误的 Firefox 浏览器中,会抛出recorder.start()callSecurityError: The operation is insecure.和 at recorder.stop()call InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable

这些错误显然是由于来自 DOM Elements的媒体捕获的安全考虑

我们如何才能避免上述错误并达到 Chromium 和 Chrome 浏览器在 Firefox 浏览器上实现的相同结果?

4

1 回答 1

0

您可以使用或XMLHttpRequest()获取fetch()媒体Blob资源的表示,创建一个Blob URL使用BlobURL.createObjectURL()

<!DOCTYPE html>
<html>

<head>
</head>

<body>
  <video width="320" height="280"></video>
  <script>
    (async() => {
      const video = document.querySelector("video");
      const src = "https://mirrors.creativecommons.org/movingimages/webm/ScienceCommonsJesseDylan_240p.webm#t=0,10";
      const url = new URL(src);
      let recorder;
      video.oncanplay = () => {
        // note, audio is not output here
        video.play();
        const mediaStream = video.mozCaptureStream();
        recorder = new MediaRecorder(mediaStream);
        recorder.ondataavailable = event =>
          // audio is output at resulting `Blob URL`         
          console.log(URL.createObjectURL(event.data));

        recorder.start();
      }

      video.onpause = () => recorder && recorder.stop();

      const blob = await fetch(url).then(response => response.blob());
      video.src = URL.createObjectURL(blob) + url.hash;

    })();
  </script>
</body>

</html>

或者,我们可以通过将媒体资源的表示附加到of实例来记录MediaSource()set as .srcof的媒体播放HTMLMediaElementArrayBufferSourceBufferMediaSource

<!DOCTYPE html>
<html>

<head>
</head>

<body>
  <video width="320" height="280"></video>
  <script>
  (async() => {
  // SecurityError: The operation is insecure.
  //  InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable
  const video = document.querySelector("video");
  const src = "https://mirrors.creativecommons.org/movingimages/webm/ScienceCommonsJesseDylan_240p.webm#t=0,10";
  const url = new URL(src);
  const mediaSource = new MediaSource();
  const mimeCodec = "video/webm;codecs=opus";
  video.src = URL.createObjectURL(mediaSource);
  mediaSource.onsourceopen = async() => {
    const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
    const mediaBuffer = await fetch(url).then(response => response.arrayBuffer());
    sourceBuffer.appendBuffer(mediaBuffer);
  }
  let recorder;
  video.oncanplay = () => {
    // note, audio is not output here
    video.play(); 
    const mediaStream = video.mozCaptureStream();
    recorder = new MediaRecorder(mediaStream);
    recorder.ondataavailable = event => 
      // audio is output at resulting `Blob URL` 
      console.log(URL.createObjectURL(event.data)); 
      
    recorder.start();
  }

  video.ontimeupdate = () => {
    if (Math.floor(video.currentTime) === Number(url.hash.split(",").pop())) {
      video.ontimeupdate = null;
      video.pause();
      mediaSource.endOfStream();
    }
  }

  video.onpause = () => recorder && recorder.stop();

})();

</script>

</body>
</html>

我们还可以使用辅助函数在每个 Chromium、Chrome 浏览器和 Firefox 浏览器上使用相同的代码,例如,请参阅动态创建的视频元素的captureStream() 中的答案

于 2017-09-18T05:14:37.120 回答