如何修改Chrome MediaRecorder捕获的.webm Blob

Bob*_*bby 5 javascript google-chrome canvas webm

在Chrome中.我正在使用MediaRecordercanvas.captureStream ()来创建画布的webm文件.

let recorder = new MediaRecorder(document.querySelector('canvas').captureStream(), {mimeType: 'video/webm'});
let chunks = [];
let blob;

recorder.ondataavailable = function(event) {
  if (event.data.size > 0) {
    chunks.push(event.data);
  }
};
recorder.onstop = function() {
  blob = new Blob(chunks, {type: 'video/webm'});
  let url = URL.createObjectURL(blob);
  let a = document.createElement('a');
  document.body.appendChild(a);
  a.href = url;
  a.download = Date.now()+'.webm';
  a.click();
  window.URL.revokeObjectURL(url);
  a.parentNode.removeChild(a);
}
recorder.onstart = function() {
  chunks = [];
}
Run Code Online (Sandbox Code Playgroud)

这是基本的录制和下载代码,以及recorder.start()开始录制和recorder.stop()结束的呼叫.

输出webm文件很好,我遇到的问题是由于计算机/开销很大,我不能总是快速绘制画布使其达到完整的60 fps.在画布本身,我不介意较低的帧速率,但绘制到画布的滞后被转换为webm,我留下了x0.9速度的视频.

我尝试通过canvas.captureStream(0)一次只捕获一个帧并将其与每个画布渲染相匹配来解决这个问题.但这失败了,因为我无法指定每个帧应该持续的持续时间,并且文件大小变得很大,因为每个帧都具有所有头信息.

我可以在我的blob数组中看到前131个blob是常量,blob 132有非常大量的数据.在那之后,通常有~7个间隔blob,每个1字节,然后是一个包含更多数据量的blob.我知道前132个blob是标题信息+我的第一帧.我想每个帧都有大量数据的blob.我还假设1字节间隔斑点与帧持续时间或暂停一段时间有关.

我想要做的是能够修改那些spacer blob以指定帧的确切持续时间.我试图通过在2帧之间复制7个间隔斑点来手动完成此操作,我知道帧率是理想的,然后移除所有其他间隔物并在每个帧之间粘贴这些理想的间隔斑点,但输出文件没有播放.

我误解了blob数据吗?有没有办法通过修改blob数据来手动指定帧持续的持续时间,还是我可以使用绘制到画布的任何帧速率?

Bob*_*bby 5

通过暂停并在超时时恢复记录器,并在再次暂停之​​前请求一个帧,我能够定义一个与画布刷新率不同的帧率:

let recorder = new MediaRecorder(canvas.captureStream(), {mimeType: 'video/webm'});
recorder.start();
recorder.pause();

function draw() {
  context.drawImage(...);
  recorder.resume();
  setTimeout(function() {
    recorder.requestData();
    recorder.pause();

    //update progress bars or any laggy overhead stuff at this point

    requestAnimationFrame(draw);
  }, 1000/fps);
}
requestAnimationFrame(draw);
Run Code Online (Sandbox Code Playgroud)

这样,实际的画布图形或更新进度条等中的任何延迟都不会影响记录器的帧收集。recorder.requestData()似乎没有必要,但似乎也没有任何缺点。为了清楚起见,此处将其包括在内。

我没有详细检查,但是一开始可能会有一个双帧,具体取决于是否recorder.start()收集了初始帧,并且您的画布不是空白。