Mitya
Mitya

Reputation: 34556

Why are my JS-generated videos not playing in Firefox?

I have a screen recorder web extension that generates the recorded video as a download. Everything's fine in Chrome, but none of the generated videos are playing in Firefox.

I've tried both .webm (via the VP9 codec) and .mp4 (via H264). The pertinent code is:

recorder.addEventListener('stop', evt => {
    blob = new Blob(recorder.chunks, {'type': 'video/webm; codecs=vp9'});
    blob_url = window.URL.createObjectURL(blob);
    //...

Also tried

{'type': 'video/mp4; codecs=H264'}

In Firefox I just see:

enter image description here

What am I doing wrong?

[EDIT]

Following @epistemex's helpful answer I am now specifying webm at the point of creating the MediaRecorder, and not specifying any codec.

MediaRecorder(master_stream, {mimeType: 'video/webm'});

Then later

blob = new Blob(recorder.chunks); //<-- not setting mime here now

...but still Firefox says it can't play the resultant files, even though

MediaRecorder.isTypeSupported("video/webm") //true

[EDIT 2 - including more code]

    if (rec_prefs.rec_vid == 'screen') listen_for_stop_screen_sharing();
    recorder = new MediaRecorder(master_stream, {mimeType: 'video/webm'});
    recorder.start();
    recorder.chunks = [];
    recorder.addEventListener('dataavailable', evt => {
        recorder.chunks.push(evt.data);
    }, false);
    rec_stopped_dfd = new Promise((resolve) => {
        recorder.addEventListener('stop', evt => {
            blob = new Blob(recorder.chunks);
            blob_url = window.URL.createObjectURL(blob);
            resolve();
        }, false);
    });

Call to recorder.stop() is in a callback in response to a button click:

function stop_recording() {
    master_stream.getTracks().forEach(track => track.stop());
    if (recorder && recorder.state != 'inactive') {
        recorder.stop();

Yes I can confirm the array is not empty. Everything works perfectly in Chrome - no errors, console etc.

Upvotes: 3

Views: 1757

Answers (1)

user1693593
user1693593

Reputation:

Firefox doesn't support audio/webm using the vp9 codec, nor MP4 containers where data is encoded using H.264 (this may be related to licensing/legal aspects).

You can test support using the MediaRecorder.isTypeSupported() to check for support:

console.log("video/webm: ", MediaRecorder.isTypeSupported("video/webm"))
console.log("video/webm; codecs=vp9: ", MediaRecorder.isTypeSupported("video/webm; codecs=vp9"))
console.log("video/mp4; codecs=H264: ", MediaRecorder.isTypeSupported("video/mp4; codecs=H264"))

The other thing you need to be aware of that is that setting the mime-type for the Blob does not affect the data itself in any form - that is just metadata. You have to specify the mime-type in the option object for the MediaRecorder (you don't show this part in the question so you may do this already, but just in case if not):

const mediaRecorder = new MediaRecorder(stream, {
    mimeType: "video/webm"
  });

So what to do: well, if not supported it's really not much you can do, except from using a codec that is supported. You can simply leave out the more specific vp9 requirement and let the browser determine what to use, or use a simplified fallback, for example:

const mime = MediaRecorder.isTypeSupported("video/webm; codecs=vp9") 
             ? "video/webm; codecs=vp9" 
             : "video/webm";  // here: assumed support (todo)

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

Hope this helps!

Upvotes: 4

Related Questions