All MIME types supported by MediaRecorder in Firefox and Chrome?
Asked Answered
M

9

78

Where can I find a list of all MIME types that are supported by Firefox or Chrome? All examples I've seen so far using video/webm only.

Mekong answered 19/1, 2017 at 10:45 Comment(2)
I haven't found an answer to this question either. For anyone else interested, I opened a caniuse feature suggestion to collect the data. Priority in the list is based on +1s on the GitHub issue.Appendectomy
developer.mozilla.org/en-US/docs/Web/Media/Formats/…Four
K
62

I've not seen any sort of comprehensive list yet for Firefox but I have managed to find something (via a post on the MediaRecorder API from Google's web updates section) that links to this test set that seems to shed some light on things.

Essentially, it looks like the following are (at time of writing) accepted MIME types for video/audio in Chrome:

  • video/webm
  • video/webm;codecs=vp8
  • video/webm;codecs=vp9
  • video/webm;codecs=vp8.0
  • video/webm;codecs=vp9.0
  • video/webm;codecs=h264
  • video/webm;codecs=H264
  • video/webm;codecs=avc1
  • video/webm;codecs=vp8,opus
  • video/WEBM;codecs=VP8,OPUS
  • video/webm;codecs=vp9,opus
  • video/webm;codecs=vp8,vp9,opus
  • video/webm;codecs=h264,opus
  • video/webm;codecs=h264,vp9,opus
  • video/x-matroska;codecs=avc1

  • audio/webm

  • audio/webm;codecs=opus

(EDITED 2019-02-10: Updated to include brianchirls' link find)

Katharyn answered 17/2, 2017 at 21:44 Comment(9)
Looks like the code for those tests has moved: cs.chromium.org/chromium/src/third_party/blink/web_tests/fast/…Gypsy
Really? No audio/wav so no recording without data loss? Someone was seriously slacking during requirements...Jayme
@JohnWeisz You can record the raw data without data loss by using a ScriptProcessorNode or AudioWorklet, I believe. (However, then you have to manually piece together the resulting file, so I suppose it is still an oversight.)Ea
I've put together a list of libraries that let you record to alternate formats (some of which are lossless): https://mcmap.net/q/266169/-record-as-ogg-using-mediarecorder-in-chromeEa
@Ea You are correct, but it just feels weird to have a native solution for audio recording, but without support for the most basic use case. It's indeed straightforward to implement it using an AudioWorklet, you can even build the wav file contents in a separate dedicated worker thread on the fly, but it just doesn't make sense IMO.Jayme
The source code is over here: source.chromium.org/chromium/chromium/src/+/master:third_party/…Telson
"audio/webm;codecs=pcm" works for lossless audio recording in Chrome as of at least 2020Barrelchested
audio/webm;codecs=pcm still working for lossless audio recording on a 2023 chrome (115.0.5790.102)Viewpoint
WebM does not work on iOS Safari though.Chandrachandragupta
S
51

I made this small function in my utils.js to get the best supported codec, with support for multiple possible naming variations (example : firefox support video/webm;codecs:vp9 but not video/webm;codecs=vp9)

You can reorder videoTypes, audioTypes and codecs arrays by priority, depending on your needs, so you'll always fall on the next supported type.

EDIT: Add support for audio, fixed mimetype duplicates

function getSupportedMimeTypes(media, types, codecs) {
  const isSupported = MediaRecorder.isTypeSupported;
  const supported = [];
  types.forEach((type) => {
    const mimeType = `${media}/${type}`;
    codecs.forEach((codec) => [
        `${mimeType};codecs=${codec}`,
        `${mimeType};codecs=${codec.toUpperCase()}`,
        // /!\ false positive /!\
        // `${mimeType};codecs:${codec}`,
        // `${mimeType};codecs:${codec.toUpperCase()}` 
      ].forEach(variation => {
        if(isSupported(variation)) 
            supported.push(variation);
    }));
    if (isSupported(mimeType))
      supported.push(mimeType);
  });
  return supported;
};

// Usage ------------------

const videoTypes = ["webm", "ogg", "mp4", "x-matroska"];
const audioTypes = ["webm", "ogg", "mp3", "x-matroska"];
const codecs = ["should-not-be-supported","vp9", "vp9.0", "vp8", "vp8.0", "avc1", "av1", "h265", "h.265", "h264", "h.264", "opus", "pcm", "aac", "mpeg", "mp4a"];

const supportedVideos = getSupportedMimeTypes("video", videoTypes, codecs);
const supportedAudios = getSupportedMimeTypes("audio", audioTypes, codecs);

console.log('-- Top supported Video : ', supportedVideos[0])
console.log('-- Top supported Audio : ', supportedAudios[0])
console.log('-- All supported Videos : ', supportedVideos)
console.log('-- All supported Audios : ', supportedAudios)
Sparke answered 3/11, 2020 at 3:5 Comment(3)
This (and answers below) also work for MediaSource although the results are a little upsetting... You get ~5 choices.....Denis
And so does with video/webm;codecs:should-not-be-supported, be careful when checking for support. The issue lies with the : instead of =Sleekit
I'm pretty shocked, does this qualify as a chrome bug/issue ... Updated the answer to only check with = and not : ... Thanks for the notification.Sparke
P
22

Just execute the below snippet (Based on @MillenniumFennec's answer + audio + removing duplicates + some other improvements + full list from MDN):

function getAllSupportedMimeTypes(...mediaTypes) {
  if (!mediaTypes.length) mediaTypes.push('video', 'audio')
  const CONTAINERS = ['webm', 'ogg', 'mp3', 'mp4', 'x-matroska', '3gpp', '3gpp2', '3gp2', 'quicktime', 'mpeg', 'aac', 'flac', 'x-flac', 'wave', 'wav', 'x-wav', 'x-pn-wav', 'not-supported']
  const CODECS = ['vp9', 'vp9.0', 'vp8', 'vp8.0', 'avc1', 'av1', 'h265', 'h.265', 'h264', 'h.264', 'opus', 'vorbis', 'pcm', 'aac', 'mpeg', 'mp4a', 'rtx', 'red', 'ulpfec', 'g722', 'pcmu', 'pcma', 'cn', 'telephone-event', 'not-supported']
  
  return [...new Set(
    CONTAINERS.flatMap(ext =>
        mediaTypes.flatMap(mediaType => [
          `${mediaType}/${ext}`,
        ]),
    ),
  ), ...new Set(
    CONTAINERS.flatMap(ext =>
      CODECS.flatMap(codec =>
        mediaTypes.flatMap(mediaType => [
          // NOTE: 'codecs:' will always be true (false positive)
          `${mediaType}/${ext};codecs=${codec}`,
        ]),
      ),
    ),
  ), ...new Set(
    CONTAINERS.flatMap(ext =>
      CODECS.flatMap(codec1 =>
      CODECS.flatMap(codec2 =>
        mediaTypes.flatMap(mediaType => [
          `${mediaType}/${ext};codecs="${codec1}, ${codec2}"`,
        ]),
      ),
      ),
    ),
  )].filter(variation => MediaRecorder.isTypeSupported(variation))
}

// To get all mime types, use: getAllSupportedMimeTypes()

console.log('Video mime types:')
console.log(getAllSupportedMimeTypes('video'))

console.log('Audio mime types:')
console.log(getAllSupportedMimeTypes('audio'))
Participial answered 3/7, 2021 at 13:4 Comment(1)
Amazing! But browsers today offer no access to raw PCM data??Exoenzyme
E
16

For Firefox, the accepted mimetypes can be found in MediaRecorder.cpp and confirmed using MediaRecorder.isTypeSupported(...)

Example:

21:31:27.189 MediaRecorder.isTypeSupported('video/webm;codecs=vp8')
21:31:27.135 true
21:31:41.598 MediaRecorder.isTypeSupported('video/webm;codecs=vp8.0')
21:31:41.544 true
21:32:10.477 MediaRecorder.isTypeSupported('video/webm;codecs=vp9')
21:32:10.431 false
21:31:50.534 MediaRecorder.isTypeSupported('audio/ogg;codecs=opus')
21:31:50.479 true
21:31:59.198 MediaRecorder.isTypeSupported('audio/webm')
21:31:59.143 false
Endopeptidase answered 15/6, 2018 at 19:35 Comment(3)
I can confirm that video/webm;codecs=vp9 is NOT supported by firefox.Handfast
Not sure why audio/webm returned false for you. In my browser, it returns trueSabin
What is the combination for Chrome on iOS? audio/webm;codecs=opus does not work there.Heathenize
S
10

MediaRecorder support for common audio codecs:

MediaRecorder.isTypeSupported('audio/webm;codecs=opus'); // true on chrome, true on firefox => SO OPUS IT IS!
MediaRecorder.isTypeSupported('audio/ogg;codecs=opus'); // false on chrome, true on firefox
MediaRecorder.isTypeSupported('audio/webm;codecs=vorbis'); // false on chrome, false on firefox
MediaRecorder.isTypeSupported('audio/ogg;codecs=vorbis'); // false on chrome, false on firefox

Firefox used Vorbis for audio recording in the 1st implementations but it moved to Opus since.

So OPUS it is!


This may prove of interest:

Strobotron answered 25/8, 2020 at 17:58 Comment(2)
What is the combination for Chrome on iOS? audio/webm;codecs=opus does not work there.Heathenize
sometimes need to write ":" not "=", maybe to test MediaRecorder.isTypeSupportedFour
D
6

What I'm using to detect supported formats:

const containers = ['webm', 'ogg', 'mp4', 'x-matroska', '3gpp', '3gpp2', 
                    '3gp2', 'quicktime', 'mpeg', 'aac', 'flac', 'wav']
const codecs = ['vp9', 'vp8', 'avc1', 'av1', 'h265', 'h.265', 'h264',             
                'h.264', 'opus', 'pcm', 'aac', 'mpeg', 'mp4a'];

const supportedAudios = containers.map(format => `audio/${format}`)
  .filter(mimeType => MediaRecorder.isTypeSupported(mimeType))
const supportedAudioCodecs = supportedAudios.flatMap(audio => 
  codecs.map(codec => `${audio};codecs=${codec}`))
      .filter(mimeType => MediaRecorder.isTypeSupported(mimeType))

console.log('Supported Audio formats:', supportedAudios)
console.log('Supported Audio codecs:', supportedAudioCodecs)

const supportedVideos = containers.map(format => `video/${format}`)
  .filter(mimeType => MediaRecorder.isTypeSupported(mimeType))
const supportedVideoCodecs = supportedVideos.flatMap(video => 
  codecs.map(codec => `${video};codecs=${codec}`))
      .filter(mimeType => MediaRecorder.isTypeSupported(mimeType))

console.log('Supported Video formats:', supportedVideos)
console.log('Supported Video codecs:', supportedVideoCodecs)

Results in 2023:

macOS

Safari 16.6:

Supported Audio formats: – ["audio/mp4"]
Supported Audio codecs: – ["audio/mp4;codecs=avc1", "audio/mp4;codecs=mp4a"]

Supported Video formats: – ["video/mp4"]
Supported Video codecs: – ["video/mp4;codecs=avc1", "video/mp4;codecs=mp4a"]

Chrome 116:

Supported Audio formats: ['audio/webm']
Supported Audio codecs: ['audio/webm;codecs=opus', 'audio/webm;codecs=pcm']

Supported Video formats: ['video/webm', 'video/x-matroska']
Supported Video codecs: ['video/webm;codecs=vp9', 'video/webm;codecs=vp8', 
'video/webm;codecs=avc1', 'video/webm;codecs=av1', 'video/webm;codecs=h264', 
'video/webm;codecs=opus', 'video/webm;codecs=pcm', 'video/x-matroska;codecs=vp9', 
'video/x-matroska;codecs=vp8', 'video/x-matroska;codecs=avc1', 
'video/x-matroska;codecs=av1', 'video/x-matroska;codecs=h264', 
'video/x-matroska;codecs=opus', 'video/x-matroska;codecs=pcm']

Windows

All Chrome and Blink based browsers like Edge and Vivaldi support the same as Chrome macOS.

Firefox 117:

Supported Audio formats: ["audio/webm", "audio/ogg"]
Supported Audio codecs: ["audio/webm;codecs=opus", "audio/ogg;codecs=opus"]

Supported Video formats: ["video/webm"]
Supported Video codecs: ["video/webm;codecs=vp8", "video/webm;codecs=opus"]
Dillman answered 12/9, 2023 at 3:23 Comment(0)
S
4

Sorry, can't add comments; but thought it important to note: Implementation of recording raw samples via ScriptProcessor or audioWorklet is flawed for a number of reasons, one here - mainly because it connects you to an output node, and clock 'correction' happens before you see the data.

So lack of audio/wav or other raw format really kills.

But just maybe.... seems 'audio/webm;codecs=pcm' is supported in chrome.

Stopping answered 22/10, 2019 at 14:54 Comment(2)
Whoah, researching for hours to find a way to record uncompressed audio with MediaRecorder, with no codec other than webm/opus officially documented anywhere, and even worse Chrome clamps the bitrate to 128k. But you're right, "audio/webm;codecs=pcm" totally works in Chrome! If you pipe it into a file via Blob and createObjectURL it produces what appears to be a lossless/uncompressed .mka file (audio/x-matroska). So it appears to be a weird/misnamed implementation as this is not webm, and if I try to give the output file a .webm extension MediaInfo flags it as FileExtension_Invalid.Barrelchested
What is the combination for Chrome on iOS? does pcm work on Chrome-iOS ?Heathenize
F
2

ISTYPESUPPORTED

Building on the previous answers (thanks @Fennec), I have created a jsfiddle to list all the supported types: https://jsfiddle.net/luiru72/rfhLcu26/5/. I also added a non-existent codec ("notatall").

Among the results of this script, if you call it from Firefox, you will find:

video/webm;codecs:vp9.0
video/webm;codecs=vp8
video/webm;codecs:vp8
video/webm;codecs:notatall

Note that you will not find "video/webm;codecs=vp9.0", and you will not find "video/webm;codecs=notatall" either.

This is because isTypeSupported on Firefox is able to understand the request "video/webm;codecs=vp9.0" or "video/webm;codecs=notatall" and it responds that it is not supported; but it is not able to understand the request "video/webm;codecs:vp9.0" or "video/webm;codecs:notatall", so isTypeSupported on Firefox (as of version 92.0, 2021-09-14) responds that it is supported.

MEDIARECORDER

I have created another jsfiddle to experiment with MediaRecorder: https://jsfiddle.net/luiru72/b9q4nsdv/42/

If you try to create a MediaRecorder on Firefox using the wrong syntax "video/webm;codecs:vp9,opus" or "video/webm;codecs:notatall,opus", you do not get an error, you just get a video encoded in VP8 and Opus. If you open the file using a tool like MediaInfo https://sourceforge.net/projects/mediainfo/, you realize that it is encoded in VP8,Opus.

If you specify "video/webm;codecs=vp8", you get an error because vp8 cannot encode audio. You need to specify both: "video/webm;codecs=vp8,opus", or you can just rely on defaults, specifying only the container format "video/webm". In this way, you now get the file encoded in VP8,Opus, but the actual video and audio encoder defaults could change over time, so if you want to be sure that VP8 and Opus are used, you need to specify them.

Key take away points:

  1. you should use the syntax: video/webm;codecs=vp8, not video/webm;codecs:vp8

  2. when creating a MediaRecorder, you should take extra-care: for example, on Firefox, video/webm;codecs=vp8 is supported, but when creating a MediaRecorder you should use "video/webm" or "video/webm;codecs=vp8,opus

  3. if you specify an incorrect syntax, for example video/webm;codecs:vp9,opus in Firefox, you do not get an error, you just get a file that is encoded in VP8,opus. You only realize that it is in a different format from the one intended if you open it with a program like MediaInfo that is able to show you the codecs that have been used

Fere answered 14/9, 2021 at 10:35 Comment(0)
C
0

I found a solution today which involves using var canRecordVp9 = MediaRecorder.isTypeSupported('video/webm;codecs=vp9');

to differentiate between Chrome(and Opera) and Firefox, and then do if (canRecordVp9) { mediaRecorder = new MediaRecorder(stream, {mimeType : 'video/webm;codecs=vp9'}); } else { mediaRecorder = new MediaRecorder(stream); }

to construct the MediaRecorder accordingly.

Then, when grabbing the blob: if (canRecordVp9) { blob = new Blob([myArrayBuffer], { "type" : "video/webm;codecs=vp9" }); } else { blob = new Blob([myArrayBuffer], { "type" : "video/webm" }); }

and finally, use the FileReader to get the blob as a dataUrl: `

var reader = new FileReader();
reader.onload = function(event)
{
    var blobDataUrl = event.target.result;
}
reader.readAsDataURL(blob);`

I then save the blobDataUrl as a webm file, and videos recorded in Chrome work fine in Firefox, and vice-versa.

Complexion answered 29/7, 2019 at 3:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.