I am using this code to generate small stand alone videos from a MediaRecorder:
var mediaRecorder;
var chunks;
// call this function to start the process
function startRecording(stream) {
chunks = [];
mediaRecorder = new MediaRecorder(stream, { mimeType: "video/webm; codecs=vp8" });
mediaRecorder.ondataavailable = function (e) {
chunks.push(e.data);
};
mediaRecorder.onstop = function () {
actualChunks = chunks.splice(0, chunks.length);
const blob = new Blob(actualChunks, { type: "video/webm; codecs=vp8" });
uploadVideoPart(blob); // Upload to server
};
recordVideoChunk(stream);
};
function recordVideoChunk(stream) {
mediaRecorder.start();
setTimeout(function() {
mediaRecorder.stop();
recordVideoChunk(stream);
}, 10000); // 10 seconds videos
}
The problem is that some of the files generated are considered corrupted by ffmpeg:
ffmpeg -v error -i 03_video_part_1638535340218.webm -f null -
Error while decoding stream #0:0: Invalid data found when processing input
More info about the file:
> ffprobe 03_video_part_1638535340218.webm
ffprobe version 4.4.1 Copyright (c) 2007-2021 the FFmpeg developers
built with Apple clang version 12.0.0 (clang-1200.0.32.29)
configuration: --prefix=/usr/local/Cellar/ffmpeg/4.4.1_3 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-avresample --enable-videotoolbox
libavutil 56. 70.100 / 56. 70.100
libavcodec 58.134.100 / 58.134.100
libavformat 58. 76.100 / 58. 76.100
libavdevice 58. 13.100 / 58. 13.100
libavfilter 7.110.100 / 7.110.100
libavresample 4. 0. 0 / 4. 0. 0
libswscale 5. 9.100 / 5. 9.100
libswresample 3. 9.100 / 3. 9.100
libpostproc 55. 9.100 / 55. 9.100
Input #0, matroska,webm, from '03_video_part_1638535340218.webm':
Metadata:
encoder : Chrome
Duration: N/A, start: 0.000000, bitrate: N/A
Stream #0:0(eng): Video: vp8, yuv420p(progressive), 1280x1236, SAR 1:1 DAR 320:309, 60 tbr, 1k tbn, 1k tbc (default)
Metadata:
alpha_mode : 1
Stream #0:1(eng): Audio: opus, 48000 Hz, stereo, fltp (default)
The error doesn't happen always and not in all stand alone videos.
I was not able to reproduce the error using Firefox
I have tracked the error to the browser itself, creating links in the same page that I download and check through ffmpeg. So possible causes in the upload mechanism are eliminated. The file is corrupted from origin.
Looks like the error never happens in the first file.
Using other codecs:
I moved the creation of the MediaRecorder
instance to the recurrent function and now it is working properly:
var mediaRecorder;
var chunks;
// call this function to start the process
function startRecording(stream) {
chunks = [];
recordVideoChunk(stream);
};
function recordVideoChunk(stream) {
mediaRecorder = new MediaRecorder(stream, { mimeType: "video/webm; codecs=vp8" });
mediaRecorder.ondataavailable = function (e) {
chunks.push(e.data);
};
mediaRecorder.onstop = function () {
actualChunks = chunks.splice(0, chunks.length);
const blob = new Blob(actualChunks, { type: "video/webm; codecs=vp8" });
uploadVideoPart(blob); // Upload to server
};
mediaRecorder.start();
setTimeout(function() {
mediaRecorder.stop();
recordVideoChunk(stream);
}, 10000); // 10 seconds videos
}
I think there was some kind of race condition that made the event listeners (ondataavailable
and onstop
) to not be called in the proper order, or to have multiple calls... to be honest I don't know what is the real problem and if there is a better version of the code I can create that also works.