Поиск не работает в записанном видео с MediaRecorder API

Я пытаюсь создать запись экрана с помощью 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 : ""

Видно, что объект file не содержит свойства duration.

Кто-нибудь может предложить любую доступную библиотеку JavaScript, которая может восстанавливать заголовок видео на стороне клиента только при подготовке видео файла?

3 ответа

взгляните на getSeekableBlob на https://recordrtc.org/

это код:

      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);
}

Это хорошо известная ошибка в Chrome. Как правило, длительность записанного носителя не добавляется в заголовки окончательного файла.

К сожалению, эта ошибка в настоящее время помечена как WontFix командой Chromium. Однако есть несколько обходных путей:

  • На сервере, используя ffmpeg для исправления заголовков: ffmpeg -i old.webm output.webm

  • На внешнем интерфейсе, обход этого ответа или использование пакета ts-ebml

Прошло несколько лет, а официального решения до сих пор нет. Лучшее решение, которое я пробовал до сих пор, это webm-duration-fixдля тех, кому это нужно. Он поддерживает исправление файлов записи размером более 2 ГБ и имеет небольшой объем памяти при исправлении.

      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 = [];
};
Другие вопросы по тегам