Поиск не работает в записанном видео с 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 = [];
};