9

我正在尝试使用 MediaRecorder API 构建屏幕录制。

作为暗示性媒体记录方法

var chunks = [];
var recorder = new MediaRecorder(stream);

recorder.streams = [stream];

recorder.ondataavailable = function(e) {
    chunks.push(e.data);
};

recorder.onstop = function(){
      var blob = new Blob(chunks, {type: "video/webm"});
      chunks = [];

      var mimeType = 'video/webm';
      var fileExtension = 'webm';

      var file = new File([blob ? blob : ''], getFileName(fileExtension), {
          type: mimeType
      });
};

使用这种方法录制工作正常,但录制的视频搜索不起作用。

关于这个问题,我在网上做了一些搜索,发现视频标题不包含持续时间。

在控制台上打印file对象时,它包含以下属性,

lastModified : 1527592713006
lastModifiedDate : Tue May 29 2018 16:48:33 GMT+0530 (India Standard Time) 
name : "Recording-May,29 2018 4:48:33 PM.webm"
size : 1971220
type : "video/webm"
webkitRelativePath : ""

可以看到文件对象不包含持续时间属性。

任何人都可以建议任何可用的 JavaScript 库,它只能在准备视频文件时在客户端修复视频头?

4

3 回答 3

6

这是Chrome中一个众所周知的错误。基本上,录制媒体的持续时间不会添加到最终文件的标题中。

遗憾的是,这个错误目前WontFix被 Chromium 团队标记为。但是,有几个解决方法:

  • 在后端,使用 ffmpeg 修复标头: ffmpeg -i old.webm output.webm

  • 在前端,此答案的解决方法或使用包ts-ebml

于 2019-03-07T23:15:24.783 回答
5

在https://recordrtc.org/上查看 getSeekableBlob

这是代码:

function getSeekableBlob(inputBlob, callback) {
    // EBML.js copyrights goes to: https://github.com/legokichi/ts-ebml
    if (typeof EBML === 'undefined') {
        throw new Error('Please link: https://cdn.webrtc-experiment.com/EBML.js');
    }
    var reader = new EBML.Reader();
    var decoder = new EBML.Decoder();
    var tools = EBML.tools;
    var fileReader = new FileReader();
    fileReader.onload = function(e) {
        var ebmlElms = decoder.decode(this.result);
        ebmlElms.forEach(function(element) {
            reader.read(element);
        });
        reader.stop();
        var refinedMetadataBuf = tools.makeMetadataSeekable(reader.metadatas, reader.duration, reader.cues);
        var body = this.result.slice(reader.metadataSize);
        var newBlob = new Blob([refinedMetadataBuf, body], {
            type: 'video/webm'
        });
        callback(newBlob);
    };
    fileReader.readAsArrayBuffer(inputBlob);
}
于 2021-06-03T14:56:23.187 回答
0

几年过去了,仍然没有官方的解决方案。到目前为止,我尝试过的最佳解决方案是webm-duration-fix为那些需要它的人准备的。它支持修复大于 2GB 的录音文件,修复时内存占用低。

import fixWebmDuration from 'webm-duration-fix';

const mimeType = 'video/webm\;codecs=vp9';
const blobSlice: BlobPart[] = [];

mediaRecorder = new MediaRecorder(stream, {
  mimeType
});

mediaRecorder.ondataavailable = (event: BlobEvent) => {
  blobSlice.push(event.data);
}

mediaRecorder.onstop = async () => {  
    // fix blob, support fix webm file larger than 2GB
    const fixBlob = await fixWebmDuration(new Blob([...blobSlice], { type: mimeType }));
    // to write locally, it is recommended to use fs.createWriteStream to reduce memory usage
    const fileWriteStream = fs.createWriteStream(inputPath);
    const blobReadstream = fixBlob.stream();
    const blobReader = blobReadstream.getReader();
  
    while (true) {
      let { done, value } = await blobReader.read();
      if (done) {
        console.log('write done.');
        fileWriteStream.close();
        break;
      }
      fileWriteStream.write(value);
      value = null;
    }
    blobSlice = [];
};
于 2022-01-17T09:51:34.187 回答