代码之家  ›  专栏  ›  技术社区  ›  Alok

MediaStream Recording API对canvas元素的视频捕获不起作用

  •  0
  • Alok  · 技术社区  · 3 年前

    我正在尝试录制和下载以下视频 canvas 元素使用官 MediaStream Recording API

    <!DOCTYPE html>
    <html>
    
    <body>
        <h1>Lets test mediaRecorder</h1>
    
        <canvas id="myCanvas" width="200" height="100" style="border:1px solid #d3d3d3;">
            Your browser does not support the HTML canvas tag.
        </canvas>
    
        <script>
            var c = document.getElementById("myCanvas");
            var ctx = c.getContext("2d");
            ctx.font = "30px Arial";
            ctx.fillText("Hello World", 10, 50);
    
            const stream = c.captureStream(25);
            var recordedChunks = [];
            console.log(stream);
            var options = { mimeType: "video/webm; codecs=vp9" };
            mediaRecorder = new MediaRecorder(stream, options);
    
            mediaRecorder.ondataavailable = handleDataAvailable;
            mediaRecorder.start();
    
            function handleDataAvailable(event) {
                console.log("data-available");
                if (event.data.size > 0) {
                    recordedChunks.push(event.data);
                    console.log(recordedChunks);
                    download();
                } else {
                    // ...
                }
            }
    
            function download() {
                var blob = new Blob(recordedChunks, {
                    type: "video/webm"
                });
                var url = URL.createObjectURL(blob);
                var a = document.createElement("a");
                document.body.appendChild(a);
                a.style = "display: none";
                a.href = url;
                a.download = "test.webm";
                a.click();
                window.URL.revokeObjectURL(url);
            }
    
            // demo: to download after 10 sec
            setTimeout(event => {
                console.log("stopping");
                mediaRecorder.stop();
            }, 10000);
        </script>
    
    </body>
    
    </html>
    

    代码正在运行,我可以下载 test.webm 但我想它没有任何数据,因为我在VLC Media Player中播放此文件时没有看到任何内容

    我缺少什么让它工作?

    0 回复  |  直到 3 年前
        1
  •  2
  •   Kaiido NickSlash    3 年前

    你在这里遇到了一些bug。

    第一个有点可以原谅, Chrome doesn't generate seekable webm files. 这是因为媒体文件是如何构建的,以及MediaRecorder API是如何工作的。为了使他们能够添加这些信息,他们必须将元数据所在的块保留在记录完成时添加这些信息。

    我不太确定Firefox在这里有什么不同,但VLC更喜欢他们的文件。

    另一个Chrome错误,更不可原谅的是,在我们再次在源画布上绘制之前,它们不会将新帧传递给MediaRecorder。
    因此,由于在您的情况下,启动MediaRecorder后您没有绘制任何内容,因此输出中不会有任何内容。。。

    为了解决这个问题,在我们停止记录器之前画一个框架就足够了,除了没有什么能让我们确切地知道浏览器何时会将该框架推送到记录器。。。

    因此,这里唯一可行的解决方法是在记录的同时在画布上连续绘制。好消息是,它不需要绘制任何新内容:我们可以通过绘制一个透明的矩形来欺骗浏览器,使其认为新内容是绘制的。

    最后一点,虽然Chrome确实支持导出具有透明度的画布,但并非所有浏览器都可以,即使在支持的情况下,大多数玩家也有默认的黑色背景。所以,在录制时,一定要给自己画一个其他颜色的背景。

    尽管如此,这里有一个固定的演示:

    var c = document.getElementById("myCanvas");
    var ctx = c.getContext("2d");
    // draw a white background
    ctx.fillStyle = "white";
    ctx.fillRect(0, 0, c.width, c.height);
    ctx.fillStyle = "black";
    ctx.font = "30px Arial";
    ctx.fillText("Hello World", 10, 50);
    
    const stream = c.captureStream(25);
    var recordedChunks = [];
    var options = {};
    mediaRecorder = new MediaRecorder(stream, options);
    
    mediaRecorder.ondataavailable = handleDataAvailable;
    mediaRecorder.start();
    // Chrome requires we draw on the canvas while recording
    mediaRecorder.onstart = animationLoop;
    
    function animationLoop() {
      // draw nothing, but still draw
      ctx.globalAlpha = 0;
      ctx.fillRect(0, 0, 1, 1);
      // while we're recording
      if (mediaRecorder.state !== "inactive") {
        requestAnimationFrame(animationLoop);
      }
    }
    // wait for the stop event to export the final video
    // the dataavailable can fire before
    mediaRecorder.onstop = (evt) => download();
    
    function handleDataAvailable(event) {
      recordedChunks.push(event.data);
    }
    
    function download() {
      var blob = new Blob(recordedChunks, {
        type: "video/webm"
      });
      var url = URL.createObjectURL(blob);
      // exporting to a video element for that demo
      // the downloaded video will still not work in some programs
      // For this one would need to fix the markers using something like ffmpeg.
      var video = document.getElementById('video');
      video.src = url;
      // hack to make the video seekable in the browser
      // see https://stackoverflow.com/questions/38443084/
      video.onloadedmetadata = (evt) => {
        video.currentTime = 10e6;
        video.addEventListener("seeked", () => video.currentTime = 0, {
          once: true
        })
      }
    }
    
    setTimeout(() => {
      console.clear();
      mediaRecorder.stop();
    }, 10000);
    console.log("please wait while recording (10s)");
    <h1>Lets test mediaRecorder</h1>
    
    <canvas id="myCanvas" width="200" height="100" style="border:1px solid #d3d3d3;">
      Your browser does not support the HTML canvas tag.
    </canvas>
    <video controls id="video"></video>