Firefox和Chrome中MediaRecorder支持的所有MIME类型?

67

我在哪里可以找到Firefox或Chrome支持的所有MIME类型的列表?到目前为止,我所看到的所有示例只是使用 video/webm


我也没有找到这个问题的答案。对于其他有兴趣的人,我开了一个caniuse功能建议来收集数据。在问题列表中的优先级基于GitHub问题上的+1。 - Kevinoid
https://developer.mozilla.org/en-US/docs/Web/Media/Formats/codecs_parameter#webm - Shimon Doodkin
9个回答

58

我还没有看到过关于Firefox的全面列表,但是我已经找到了一些相关信息(通过Google网页更新部分上关于MediaRecorder API的帖子),它链接到这个测试集,似乎对事情有所启示。

基本上,在撰写本文时,以下是Chrome中被接受的视频/音频MIME类型:

  • 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

(编辑于2019年02月10日:更新以包含brianchirls'链接查找)


13
真的吗?没有 audio/wav 格式,所以录音会有数据丢失?在需求阶段有人严重疏忽了... - John Weisz
1
@JohnWeisz,我相信你可以使用ScriptProcessorNodeAudioWorklet来记录原始数据而不会丢失数据。(但是,这样你仍然需要手动拼接生成的文件,所以我认为这仍然是一个疏忽。) - Venryx
1
我整理了一个库列表,可以让你录制到其他格式(其中一些是无损的):https://dev59.com/UFYN5IYBdhLWcg3whIXz#57837816 - Venryx
2
源代码在这里:https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/modules/mediarecorder/media_recorder_handler.cc;l=170-174;drc=1aa1254f5b527b89b190837892d5928c8d0f7bfc - sexyslippers69
显示剩余3条评论

44

我在我的utils.js中编写了这个小函数,用于获取最佳支持的编解码器,并支持多种可能的命名变体(例如:firefox支持video/webm;codecs:vp9但不支持video/webm;codecs=vp9)。

您可以根据自己的需要按优先级重新排序videoTypesaudioTypescodecs数组,以便始终使用下一个受支持的类型。

编辑:添加音频支持,修复mimetype重复问题

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)


1
这个(以及下面的答案)也适用于MediaSource,尽管结果有点令人沮丧......你只能得到大约5个选择..... - TJBlackman
1
同样的问题也出现在 video/webm;codecs:should-not-be-supported 中,请注意检查支持情况。问题出在 := 的区别上。 - Nekron SN
我感到相当震惊,这是否算作 Chrome 的 bug/问题... 已更新答案,仅使用 = 而不是 : 进行检查... 感谢您的通知。 - Fennec

14

对于Firefox来说,可接受的MIME类型可以在MediaRecorder.cpp中找到,并可以使用MediaRecorder.isTypeSupported(...)进行确认。

示例:

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

我可以确认,视频/webm;codecs=vp9在火狐浏览器中不受支持。 - James Hancock
不确定为什么 audio/webm 在你的浏览器中返回 false。在我的浏览器中,它返回 true。 - smac89
Chrome在iOS上的组合键是什么?audio/webm;codecs=opus在那里不起作用。 - arjary

12
只需执行以下代码片段(基于@MillenniumFennec答案 + audio + 去重 + 其他一些改进 + 来自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'))


10

媒体记录器支持常见的音频编解码器:

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在最初的实现中使用Vorbis进行音频录制,但后来转向了Opus。

所以现在是用OPUS!


这可能会引起兴趣:


Chrome在iOS上的组合键是什么?audio/webm;codecs=opus在那里不起作用。 - arjary
有时需要写“:”而不是“=”,可能是为了测试MediaRecorder.isTypeSupported。 - Shimon Doodkin

4

抱歉,无法添加评论;但认为有必要指出: 通过ScriptProcessor或audioWorklet记录原始采样的实施存在许多缺陷,其中一个 - 主要是因为它将您连接到输出节点,并且在您看到数据之前发生时钟“修正”。

因此,缺少音频/wav或其他原始格式确实很致命。

但也许......在Chrome中支持“audio/webm;codecs=pcm”。


1
哇,研究了好几个小时才找到一种使用MediaRecorder录制无损音频的方法,除了webm/opus之外没有其他编解码器被正式记录在案,更糟糕的是Chrome将比特率限制在128k。但你说得对,在Chrome中完全可以使用"audio/webm;codecs=pcm"!如果通过Blob管道将其导入文件并通过createObjectURL创建它,它会生成一个看起来像是无损/无压缩的.mka文件(audio/x-matroska)。因此,这似乎是一种奇怪/错误的实现,因为这不是webm,如果我尝试给输出文件一个.webm扩展名,MediaInfo会标记它为FileExtension_Invalid。 - keymap
Chrome在iOS上的组合键是什么?PCM在Chrome-iOS上能用吗? - arjary

1

ISTYPESUPPORTED

在之前的答案基础上(感谢 @Fennec),我创建了一个 jsfiddle 来列出所有支持的类型:https://jsfiddle.net/luiru72/rfhLcu26/5/。我还添加了一个不存在的编解码器("notatall")。

在这个脚本的结果中,如果你从Firefox调用它,你会发现:

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

请注意,您将找不到"video/webm;codecs=vp9.0",也不会找到"video/webm;codecs=notatall"

这是因为Firefox的isTypeSupported能够理解请求"video/webm;codecs=vp9.0"或"video/webm;codecs=notatall"并回应不支持;但它无法理解请求"video/webm;codecs:vp9.0"或"video/webm;codecs:notatall",所以Firefox的isTypeSupported(截至版本92.0,2021-09-14)回应支持。

MEDIARECORDER

我创建了另一个jsfiddle来尝试MediaRecorder:https://jsfiddle.net/luiru72/b9q4nsdv/42/

如果您尝试使用错误的语法“video/webm;codecs:vp9,opus”或“video/webm;codecs:notatall,opus”在Firefox上创建MediaRecorder,您不会收到错误消息,而是会得到一个VP8和Opus编码的视频。如果您使用MediaInfo之类的工具打开文件https://sourceforge.net/projects/mediainfo/,则会发现它是以VP8,Opus编码的。
如果您指定“video/webm;codecs=vp8”,则会出现错误,因为vp8无法编码音频。您需要同时指定:“video/webm;codecs=vp8,opus”,或者只需依赖默认值,仅指定容器格式“video/webm”。通过这种方式,您现在可以得到以VP8、Opus编码的文件,但实际的视频和音频编码器默认值可能随时间而改变,因此如果您想确保使用VP8和Opus,则需要指定它们。
关键要点:
  1. 您应该使用语法:video/webm;codecs=vp8,而不是video/webm;codecs:vp8

  2. 创建MediaRecorder时,您应该格外小心:例如,在Firefox上,支持video/webm;codecs=vp8,但创建MediaRecorder时应使用“video/webm”或“video/webm;codecs=vp8,opus

  3. 如果您指定了错误的语法,例如在Firefox中使用video/webm;codecs:vp9,opus,则不会出现错误,您只会得到一个以VP8、opus编码的文件。只有当您使用MediaInfo等程序打开它时,才能意识到它与预期的格式不同,并且能够显示所使用的编解码器。


1
我正在使用的工具来检测支持的格式是:
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)

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

所有基于Chrome和Blink的浏览器,如Edge和Vivaldi,都支持与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"]

0
今天我找到了一个解决方案,它涉及使用以下代码来区分Chrome(和Opera)和Firefox: var canRecordVp9 = MediaRecorder.isTypeSupported('video/webm;codecs=vp9'); 然后根据情况构建MediaRecorder: if (canRecordVp9) { mediaRecorder = new MediaRecorder(stream, {mimeType : 'video/webm;codecs=vp9'}); } else { mediaRecorder = new MediaRecorder(stream); } 最后,在获取blob时: if (canRecordVp9) { blob = new Blob([myArrayBuffer], { "type" : "video/webm;codecs=vp9" }); } else { blob = new Blob([myArrayBuffer], { "type" : "video/webm" }); } 最终,使用FileReader将blob作为dataUrl获取即可:
var reader = new FileReader();
reader.onload = function(event)
{
    var blobDataUrl = event.target.result;
}
reader.readAsDataURL(blob);`

然后我将blobDataUrl保存为webm文件,Chrome中录制的视频在Firefox中可以正常工作,反之亦然。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接