【问题标题】:How to detect when `canvas.captureStream()` is not supported?如何检测何时不支持“canvas.captureStream()”?
【发布时间】:2021-01-04 12:21:56
【问题描述】:

It is known that iOS Safari does not support canvas.captureStream() 用于(例如)将其内容通过管道传输到视频元素中,请参阅this demo not working in iOS Safari。

然而,canvas.captureStream() 在 iOS Safari 中是一个有效的函数,并且正确地返回了一个 CanvasCaptureMediaStreamTrack,它只是没有按预期运行。为了检测不支持canvas.captureStream的浏览器,做一个测试typeof canvas.captureStream === 'function'本来很容易,但至少对于iOS Safari,我们不能依赖它。我们也不能依赖返回值的类型。

如何编写检测当前浏览器是否有效支持canvas.captureStream()的JavaScript?

【问题讨论】:

    标签: javascript ios canvas mobile-safari


    【解决方案1】:

    这里没有 iOS 来测试它,但根据您链接到的问题的 cmets,captureStream() 确实有效,HTMLVideoElement 对此 MediaStream 的读取无效。所以这才是你真正想要测试的。

    根据那里的消息,视频甚至未能加载视频(即元数据已正确设置,我不希望像error 这样的事件触发,但如果确实如此,那么测试就很简单了:检查视频是否能够播放这样的 MediaStream。

    function testReadingOfCanvasCapturedStream() {
      // first check the DOM API is available
      if( !testSupportOfCanvasCapureStream() ) {
        return Promise.resolve(false);
      }
      // create a test canvas
      const canvas = document.createElement("canvas");
      // we need to init a context on the canvas
      const ctx = canvas.getContext("2d");
      const stream = canvas.captureStream();
      const vid = document.createElement("video");
      vid.muted = true;
      vid.playsInline = true;
      vid.srcObject = stream;
      let supports = false;
    
      // Safari needs we draw on the canvas
      // asynchronously after we requested the MediaStream
      setTimeout(() => ctx.fillRect(0,0,5,5));
    
      // if it failed, .play() would be enough
      // but according to the comments on the issue, it isn't
      return vid.play()
        .then(() => supports = true)
        .finally(() => {
          // clean
          stream.getTracks().forEach(track => track.stop());
          return supports;
        });
    }
    function testSupportOfCanvasCapureStream() {
      return "function" === typeof HTMLCanvasElement.prototype.captureStream;
    }
    testReadingOfCanvasCapturedStream()
      .then(supports => console.log(supports));

    但如果视频可以播放,但没有绘制图像,那么我们必须更深入地检查视频上绘制的内容。为此,我们将在画布上绘制一些颜色,等待视频加载完毕并将其重新绘制到画布上,然后再检查画布上帧的颜色:

    async function testReadingOfCanvasCapturedStream() {
      // first check the DOM API is available
      if( !testSupportOfCanvasCapureStream() ) {
        return false;
      }
      // create a test canvas
      const canvas = document.createElement("canvas");
      // we need to init a context on the canvas
      const ctx = canvas.getContext("2d");
      const stream = canvas.captureStream();
      const clean = () => stream.getTracks().forEach(track => track.stop());
      const vid = document.createElement("video");
      vid.muted = true;
      vid.srcObject = stream;
    
      // Safari needs we draw on the canvas
      // asynchronously after we requested the MediaStream
      setTimeout(() => {
        // we draw in a well knwown color
        ctx.fillStyle = "#FF0000";
        ctx.fillRect(0,0,300,150);
      });
    
      try {
        await vid.play();
      }
      catch(e) {
        // failed to load, no need to go deeper
        // it's not supported
        clean();
        return false; 
      }
      // here we should have our canvas painted on the video
      // let's keep this image on the video
      await vid.pause();
    
      // now draw it back on the canvas
      ctx.clearRect(0,0,300,150);
      ctx.drawImage(vid,0,0);
      const pixel_data = ctx.getImageData(5,5,1,1).data;
      const red_channel = pixel_data[0];
    
      clean();
    
      return red_channel > 0; // it has red
    }
    function testSupportOfCanvasCapureStream() {
      return "function" === typeof HTMLCanvasElement.prototype.captureStream;
    }
    
    testReadingOfCanvasCapturedStream()
      .then(supports => console.log(supports));

    【讨论】:

    • 在 iOS 上测试并确认它记录“假”。感谢您的洞察力回答!
    • @AndréStaltz 它适用于 sn-ps 还是仅适用于第二个?
    • 只有第二个,第一个不记录任何东西
    • 有趣,我最初打开这个问题时考虑到了 iOS Safari,但现在我意识到 Safari 14 (macOS) 有问题,它不会为第二个 sn-p 记录任何内容!
    • @AndréStaltz 感谢您的提醒。确实可以与以前的版本一起使用。显然他们不再喜欢在画布上绘制流停止的视频了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-12
    • 1970-01-01
    • 2019-03-22
    • 1970-01-01
    • 2017-04-21
    • 1970-01-01
    • 2021-08-05
    相关资源
    最近更新 更多