如何避免SecurityError:操作不安全。在Firefox上使用.mozCaptureStream和MediaRecorder时?

时间:2017-09-18 05:14:37

标签: javascript firefox mediastream web-mediarecorder

给出代码

<!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 URL Blob事件dataavailable处生成MediaRecorder {1}}实例。

在当前实施.mozCaptureStream()的Firefox浏览器中,recorder.start()调用SecurityError: The operation is insecure.recorder.stop()调用InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable时会抛出错误。

错误显然是Security ConsiderationsMedia Capture from DOM Elements造成的。

我们如何避免上述错误并获得Chromium和Chrome浏览器在Firefox浏览器中实现的相同结果?

1 个答案:

答案 0 :(得分:0)

您可以使用XMLHttpRequest()fetch()获取媒体资源的Blob代表,使用Blob URLBlob创建URL.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>

或者,我们可以通过将MediaSource()媒体资源的.src表示附加到HTMLMediaElement,将ArrayBuffer的媒体播放设置为SourceBuffer MediaSource <!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>实例

X     Y
0.99 0.56  //line 1
0.32 -0.23  //line 2

我们还可以使用辅助函数在每个Chromium,Chrome浏览器和Firefox浏览器中使用相同的代码,例如,请参阅Answer上的captureStream() on dynamically created video element