javascriptvideowebcammp4web-mediarecorder

Recording video from webcam in MP4 format with MediaRecorder


When I use the JS MediaRecorder to record webcam in MP4 format in a browser supporting MP4 and MediaRecorder (Firefox on Linux), the webcam starts but it does not record.

Recording has worked when the mimeType of the MediaRecorder is set to video/webm but when I set the mimeType to video/mp4 the problem occurs.

I record with the following code:

if (navigator.mediaDevices) {
        var constraints = {audio: true, video: true};
        navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
            mediaRecorder = new MediaRecorder(stream, {mimeType: "video/mp4"});
            mediaRecorder.start();
});
} else {
console.log("media recorder is not supported");
}

I expect the webcam to start recording when the code is executed in a supporting browser, but the console.log is not output and in the console there is the error of :

NotSupportedError: Operation is not supported

I know that my browser supports both mp4 and MediaRecorder:

MP4: https://caniuse.com/#search=mp4 MediaRecorder: https://caniuse.com/#search=mediarecorder

but only webm recording works.


Solution

  • UPDATE (June 24, 2024):

    As of Chrome 126 (Jun 5, 2024), Chrome supports MediaRecorder mp4 format. Here are official examples from the Chrome release notes:

    const recorder = new MediaRecorder(stream, { mimeType: "video/mp4;codecs=avc1,mp4a.40.2" });
    
    const recorder = new MediaRecorder(stream, { mimeType: "video/mp4;codecs=vp9,opus" });
    

    The release notes do not mention any other codecs except vp8 that are not used in the above code samples. It does mention that some OSes may not have proprietary video/audio codecs (avc1 and mp4a.40.2), in which case vp8, vp9, and opus can be used (I'm assuming vp9 is better than vp8).

    So you might like to write something like the following (untested) to fall back based on supported types (please suggest or edit entries for the list):

    const mimeTypeFallbacks = [
      // Chrome/Edge/Safari
      'video/mp4;codecs=avc1,mp4a.40.2',
      'video/mp4;codecs=vp9,opus',
      'video/mp4;codecs=vp8,opus',
      // Firefox/etc (at time of writing)
      'video/webm;codecs=avc1,mp4a.40.2',
      'video/webm;codecs=vp9,opus',
      'video/webm;codecs=vp8,opus',
    ]
    
    let i = 0
    let mimeType = mimeTypeFallbacks[i]
    while (mimeType && !MediaRecorder.isTypeSupported(mimeType)) {
      i++
      mimeType = mimeTypeFallbacks[i]
    }
    
    if (!mimeType) throw new Error('no mime type supported for recording')
    
    const recorder = new MediaRecorder(stream, { mimeType });
    
    // ...
    

    ORIGINAL:

    I found that Chromium doesn't support mp4 recording either, so I decided to do the conversion on the server side after the video was uploaded.

    Since it is GNU/Linux, to speed up the conversion I used:

    ffmpeg -i input.webm -preset superfast output.mp4

    If there are faster approaches I would like to know them.