0

MediaRecorder.isTypeSupported() returns true for 'video/webm', 'video/webm;codecs=avc1', and 'video/webm;codecs=vp9'.

However, only mimeType='video/webm;codecs=vp9' results in a valid webm file ('video/webm;codecs=vp9,opus').

Setting mimeType to either 'video/webm' and 'video/webm;codecs=avc1' results in 'video/x-matroska;codecs=avc1,opus' file, which is not a valid webm video.

Is this a MediaRecorder bug, Chrome bug or am I missing something?\

Software: Chrome 85, MacOS 10.15. I have not tried this on Windows or Linux.

2 Answers2

0

However, only mimeType='video/webm;codecs=vp9' results in a valid webm file.
Is this a MediaRecorder bug, Chrome bug or am I missing something?

WebM is the correct a/v media container for the VP8 and VP9 video codecs.

AVC1 video codec belongs into an MPEG container (.mp4, .m4v).
This video codec can also be contained inside an MKV media file (Matroska .mkv).

VC.One
  • 12,230
  • 4
  • 21
  • 51
  • If that is so, the behavior described above is a Chrome bug, correct? – Tigran Mirzoev Oct 06 '20 at 23:54
  • It's not a bug, it is correct because those things are supported by Chrome... Google are the creators of VP8 and VP9, so it gives `MediaRecorder.isTypeSupported() = true;` when you query for `codecs=avc1` or `video/webm` but as you can see you cannot put MPEG's AVC1 codec inside competing Google's WebM container and expect to have a valid working file. My answer tells you what codec to use for which container to avoid corrupt files, – VC.One Oct 07 '20 at 14:46
  • I believe this is a Chrome bug, because setting mimeType to 'video/webm' (codecs not specified) results in 'video/x-matroska;codecs=avc1,opus' file, which is not a valid webm video. – Tigran Mirzoev Oct 07 '20 at 22:45
  • You must **always specify codecs** for a container. I think H264 is Chrome's default assumed codec (see: _Line 24_ at Chrome's [source code](https://source.chromium.org/chromium/chromium/src/+/master:media/base/video_codecs.h;l=24) ). – VC.One Oct 08 '20 at 13:09
  • What exact problem in your code/app are you trying to solve? Is there anything stopping your app working correctly? There is no bug if things (codecs and containers) are used correctly. Check if a container is supported (MP4, MKV, WebM), then use correct codec(s) for that container (VP8/VP9 is webM, H264 is MKV or MP4). – VC.One Oct 08 '20 at 13:12
  • "You must always specify codecs" The codecs are not specified in the example on https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/isTypeSupported – Tigran Mirzoev Oct 09 '20 at 03:02
  • I had issues because I followed the example on developer.mozilla.org. things worked, but they didn't work well and didn't work cross-platform. I worked around the issues by being more specific in mimeTypes. The major issue was the one outlined above. Thank you for comments on this. – Tigran Mirzoev Oct 09 '20 at 03:09
0

Reproduction:

const wantMimeType = 'video/webm;codecs=h264,opus';
if (MediaRecorder.isTypeSupported(wantMimeType)) {
  let mediaRecorder = new MediaRecorder(stream, {
    mimeType: wantMimeType,
  });
  // ...drive the recorder
  mediaRecorder.onstop = (event) => {
    try {
      // returns 'video/x-matroska;codecs=avc1,opus' in Chrome,
      // and the binary file content also says Matroska instead of WebM
      let mimetype = mediaRecorder.mimeType;
      if (!mimeType.startsWith('video/webm')) {
        throw new Error(`We requested "${wantMimeType},
          but the browser gave us "${mediaRecorder.mimeType}"`);
      }
      let blob = new Blob(chunks, { type: mimeType });
      // ...convert to data: URL
      // ...play it in <video src="data:..."> // won't work, if Matroska
    } catch (ex) {
      alert(ex);
    }
  };
}

Observations:

  1. Chrome responds true to isTypeSupported('video/webm;codecs=h264,opus'), but Chrome actually does not support this combination, i.e. the response is factually incorrect and defeats the entire purpose of isTypeSupported().

  2. Chrome ignores the mimetype that we pass in the MediaRecorder constructor, and instead returns video/x-matroska;codecs=avc1,opus. Which then doesn't work, because <video> won't play the Matroska mimetype.

2 solutions:

  • Hacky: After recording, just change the mimetype back to video/webm;codecs=h264,opus. The file content will still say "Matroska", but <video> on Chrome will play it. It's a bad solution, because we're passing in the wrong mimetype, it doesn't match the content. Other software - or Chrome in later versions - might break over it.
  • Proper: Don't use H.264, but VP9 or VP8. Chrome supports both, and Firefox supports VP8, and they work properly. As a bonus, they are open, while H.264 is riddled with software patents. Depending on the hardware encoder implementation, VP8/9 also may give better image quality results.
Ben Bucksch
  • 116
  • 6