如何正确地记录从帆布流?

问题描述 投票:3回答:1

局势:

我需要做到以下几点:

  • <video>获取视频和<canvas>里面玩
  • 从画布作为BLOB录制的视频流

而已。第一部分是好的。对于第二部分,我设法记录的Blob,问题是,斑点是空的。

风景:

<video id="video" controls="true" src="http://upload.wikimedia.org/wikipedia/commons/7/79/Big_Buck_Bunny_small.ogv"></video>
<canvas id="myCanvas" width="532" height="300"></canvas>

编码:

// Init
console.log(MediaRecorder.isTypeSupported('video/webm')) // true
const canvas = document.querySelector("canvas")
const ctx = canvas.getContext("2d")
const video = document.querySelector("video")

// Start the video in the player
video.play()

// On play event - draw the video in the canvas
video.addEventListener('play', () => {
  function step() {
    ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
    requestAnimationFrame(step)
  }
  requestAnimationFrame(step);

  // Init stream and recorder
  const stream = canvas.captureStream()
  const recorder = new MediaRecorder(stream, {
    mimeType: 'video/webm',
  });

  // Get the blob data when is available
  let allChunks = [];
  recorder.ondataavailable = function(e) {
    console.log({e}) // img1
    allChunks.push(e.data);
  }

  // Start to record
  recorder.start()

  // Stop the recorder after 5s and check the result
  setTimeout(() => {
    recorder.stop()
    const fullBlob = new Blob(allChunks, { 'type' : 'video/webm' });
    const downloadUrl = window.URL.createObjectURL(fullBlob)
    console.log({fullBlob}) // img2
  }, 5000);
})

结果:

console.log事件的这个ondataavailable

enter image description here

这是块的console.log

enter image description here

小提琴:

这里是的jsfiddle。您可以检查在控制台的结果:

https://jsfiddle.net/1b7v2pen/

BROWSERS行为:

这种行为(BLOB数据大小:0),它发生在Chrome和Opera。 在Firefox上它的表现略有不同。它记录了一个非常小的视频斑点(725个字节)。视频长度为5秒,因为它应该的,但它只是一个黑屏。

问题:

什么是记录的正确方法从画布流? 这是一个错误的代码? 你知道为什么一滴出来是空的?

谢谢!

javascript html html5 vue.js html5-canvas
1个回答
2
投票

MediaRecorder.stop()是一种异步方法的。

在停止算法,也就是一个的RequestData电话,这本身将队列的任务时触发事件dataavailable与自上次事件等当前可用的数据。

这意味着,在同步你叫MediaRecorder#停止()抢下不会是你allChunks阵列的一部分,但最后的数据。他们将成为后(通常在同一事件循环)没有那么长。

所以,当您要保存所有来自MediaRecorder制作的视频,一定要始终建立从MediaRecorder's onstop事件的最后一滴,这将标志着该MediaRecorder实际上是结束,没有触发其最后dataavailable事件,而这一切都是好的。

还有一两件事,我错过了第一个,是你请求跨域视频。这样做,没有正确的跨域请求,会令你的画布(与MediaElement的)污染,所以你MediaStream将静音。

既然你正试图要求该视频来自维基,你可以简单地要求它作为一个跨源资源,但对于其他的资源,你必须确保服务器被配置为允许这些请求。

const canvas = document.querySelector("canvas")
const ctx = canvas.getContext("2d")
const video = document.querySelector("video")

// Start the video in the player
video.play()

// On play event - draw the video in the canvas
video.addEventListener('play', () => {
  function step() {
    ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
    requestAnimationFrame(step)
  }
  requestAnimationFrame(step);
  
  // Init stream and recorder
  const stream = canvas.captureStream()
  const recorder = new MediaRecorder(stream, {
    mimeType: 'video/webm',
  });

  // Get the blob data when is available
  let allChunks = [];
  recorder.ondataavailable = function(e) {
    allChunks.push(e.data);
  }
  recorder.onstop = (e) => {
    const fullBlob = new Blob(allChunks, { 'type' : 'video/webm' });
    const downloadUrl = window.URL.createObjectURL(fullBlob)
    console.log({fullBlob})
    console.log({downloadUrl})
  }

  // Start to record
  recorder.start()

  // Stop the recorder after 5s and check the result
  setTimeout(() => {
    recorder.stop()
  }, 5000);
})
<!--add the 'crossorigin' attribute to your video -->
<video id="video" controls="true" src="https://upload.wikimedia.org/wikipedia/commons/7/79/Big_Buck_Bunny_small.ogv" crossorigin="anonymous"></video>
<canvas id="myCanvas" width="532" height="300"></canvas>

另外,我无法避免要注意的是,如果你不从你的画布做任何特别的图纸,你可能想直接保存视频源,或者至少,直接记录的<video>的captureStream MediaStream。

© www.soinside.com 2019 - 2024. All rights reserved.