2

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.

Mitya
  • 33,629
  • 9
  • 60
  • 107
  • Have you tried downloading a video and playing it in a dedicated player? It might give some errors or warnings if the file is malformed in any way, which could be a hint. Chrome might be more lenient when it comes to file validity. –  Sep 11 '18 at 19:21
  • Chrome certainly does seem to be more lenient. I think the answer below is the reason I'm failing. Thanks. – Mitya Sep 12 '18 at 08:25
  • Please include the `recorder` declaration, the `recorder.chunks` declaration, the `ondataavailable` handler if any, and the call to `recorder.stop()`. Also, for how long did you actually record your stream? From experience, below 1s won't get recorded... And if you can confirm `recorder.chunks` is indeed an Array containing at least one Blob with non 0 `.size`. – Kaiido Sep 12 '18 at 08:45
  • @Kaiido thanks, see edit 2. – Mitya Sep 12 '18 at 08:55
  • Weird... you did remove all options from MediaRecorder constructor right? (I see it's still there in your edit 2). i.e `recorder = new MediaRecorder(master_stream);`. – Kaiido Sep 12 '18 at 08:58
  • @Kaiido yes I tried that too, ie no mime specification in either the MediaRecorder or Blob constructors. Could it be anything to do with using multiple streams and merging them into a master stream? I wouldn't have thought so, though, since there's only one recorder and blob. – Mitya Sep 12 '18 at 13:05
  • At this stage, I'm afraid it could come from anywhere... And without an [MCVE], hard to tell more than "probably a browser bug". Can you confirm that [the demo in this Answer](https://stackoverflow.com/questions/39302814/mediastream-capture-canvas-and-audio-simultaneously/39302994#39302994) does work? You say `master_stream` is actually composed of multiple MediaStreams, where do they come from, and how did you merged these? – Kaiido Sep 12 '18 at 13:49
  • Hmm, that *does* work. Let me see about putting together an MCVE. I'll be back. – Mitya Sep 13 '18 at 09:16
  • Ah, something I've neglected to explain thus far... my videos are being *generated* in Chrome (I'm building an extension) - it's just they won't *play* in Firefox. – Mitya Sep 13 '18 at 09:50

1 Answers1

4

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!

  • Really helpful, thanks. Looking at my code, I'm not currently specifying media type at the point of instantiating `MediaRecorder`, so that's new for me. I'll give it a go. – Mitya Sep 12 '18 at 08:24
  • Edited question... still no joy. Firefox shows same error. – Mitya Sep 12 '18 at 08:43