Web Video MimeCodec 究竟代表什么意思?

大家才开始学习 MediaSource 的时候,我们都会好奇,其中指定 mimeCodec 的行为:

var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';

if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) {  
  var mediaSource = new MediaSource();
  //console.log(mediaSource.readyState); // closed
  video.src = URL.createObjectURL(mediaSource);
  mediaSource.addEventListener('sourceopen', sourceOpen);
} else {
  console.error('Unsupported MIME type or codec: ', mimeCodec);
}

很多人不太理解这个 mimeCodec 代表着什么意思。

HTML5 在提供对视频的支持的时候,支持了一个方法,叫 canPlayType 。它主要用于测试当前浏览器是否可以支持播放给出的视频的 MIME type。

你可以在这里看到 codecs_parameter目前绝大多数支持的视频格式类型。

我们拆开看

video/mp4; codecs="avc1.42E01E, mp4a.40.2"
video/mp4;
avc1.42E01E
mp4a.40.2

video/mp4

可能大家都很熟悉,我们在 HTTP 返回的 Header 里也经常看到,类似我们经常还看见一些类似 text/plain, image/png 等。而对于音视频而言常见的类型也就那么几种:

video/webm
video/mp4
video/quicktime
audio/ogg
audio/mpeg

而这些仅仅是代表当前资源的格式。通过格式我们可以初步看出是否对 Web 友好。

那么接下来我们看的可能大家有点懵逼了。

后面这一部分 cdoec=?其实主要是用于视频用上面编码的,比如是 H.264 还是 H.265 还是早期的 MPEG-4(终于理解初中 火影忍者DVD 上的意思) 等。

我们 再看 avc1.42E01E 表示什么意思。

参考 RFC6381 中定义:

codecs      := cod-simple / cod-fancy

所以其中 avc1 代表的编码采样数据,这里可以是 avc1,avc2, 又或者是 mp4a, mp4v。总之你看到 AVC的话,表示基于 H.264 来进行编解码的。看到 vp9 就表示基于 VP9 来进行编解码的。看到 hevc 的话表示视频是基于 H.265 编码的。

而 cod-fancy 是由一个 16进制字符串组成的。而 AVC 编码下组有三个部分组成

avc1.PPCCLL

PP = profile_idc
CC = constraint_set flags
LL = level_idc

其中 profile_idc 中表示 H.264 编解码中编码器的特性概述,不同的值,需要的编码性能不一样,在官方定义的常见有下面这些:

enum eAVEncH264VProfile {
  eAVEncH264VProfile_unknown                    = 0,
  eAVEncH264VProfile_Simple                     = 66,
  eAVEncH264VProfile_Base                       = 66,
  eAVEncH264VProfile_Main                       = 77,
  eAVEncH264VProfile_High                       = 100,
  eAVEncH264VProfile_422                        = 122,
  eAVEncH264VProfile_High10                     = 110,
  eAVEncH264VProfile_444                        = 144,
  eAVEncH264VProfile_Extended                   = 88,
  eAVEncH264VProfile_ScalableBase               = 83,
  eAVEncH264VProfile_ScalableHigh               = 86,
  eAVEncH264VProfile_MultiviewHigh              = 118,
  eAVEncH264VProfile_StereoHigh                 = 128,
  eAVEncH264VProfile_ConstrainedBase            = 256,
  eAVEncH264VProfile_UCConstrainedHigh          = 257,
  eAVEncH264VProfile_UCScalableConstrainedBase  = 258,
  eAVEncH264VProfile_UCScalableConstrainedHigh  = 259
};

所以 0x42 也就是上面的 eAVEncH264VProfile_Base;

其中 constraint_set flags 则表示编码级别的约束条件,常见的有下面的几种

constraint_set0_flag  
constraint_set1_flag  
constraint_set2_flag  
constraint_set3_flag
constraint_set4_flag
constraint_set5_flag

他们分别针对不同的 profie 而制定。 而其中 0xE0 转换成二进制 11100000 也就是表示constraint_set2_flag

其中 level_idc 表示视频编码本身的视频参数,比如分辨率,码率,帧率等。Level 越高视频质量就相对越好。

而参考 eAVEncH264VLevel Enumeration Level常见的定义级别

enum eAVEncH264VLevel {
  eAVEncH264VLevel1    = 10,
  eAVEncH264VLevel1_b  = 11,
  eAVEncH264VLevel1_1  = 11,
  eAVEncH264VLevel1_2  = 12,
  eAVEncH264VLevel1_3  = 13,
  eAVEncH264VLevel2    = 20,
  eAVEncH264VLevel2_1  = 21,
  eAVEncH264VLevel2_2  = 22,
  eAVEncH264VLevel3    = 30,
  eAVEncH264VLevel3_1  = 31,
  eAVEncH264VLevel3_2  = 32,
  eAVEncH264VLevel4    = 40,
  eAVEncH264VLevel4_1  = 41,
  eAVEncH264VLevel4_2  = 42,
  eAVEncH264VLevel5    = 50,
  eAVEncH264VLevel5_1  = 51,
  eAVEncH264VLevel5_2  = 51
}

那么 0x1E 则表示 eAVEncH264VLevel3

这样大家是不是了解这些值具体的含义,不同 编码同样 code-fancy 也不一样,比如我们看到的 vp9,

 var mime = 'video/webm; codecs="opus, vp09.00.10.08"';

这个需要去不同的编码定义里去寻找具体含义。

当然,开发不用太关心怎么去设置,这个是转码需要关心的,你可以阅读 使用 JS 获取视频 Codec 使用工具或者代码来获取这些值。

扩展阅读