提示💡

  • 媒体串流能够通过 JavaScript 创建,并且能通过使用 <audio> 和 <video> 元素进行播放 。
  • js对视频加载的过程完全能进行干预。

媒体源扩展 API(MSE) 提供了实现无插件且基于 Web 的流媒体的功能。使用 MSE,媒体串流能够通过 JavaScript 创建,并且能通过使用 <audio> 和 <video> 元素进行播放。

该规范允许通过 JavaScript 为 <audio> <video> 动态构造媒体源,它定义了 MediaSource 对象,作为 HTML 5 中 HTMLMediaElement 的媒体数据源。MediaSource 对象可以有一个或多个 SourceBuffer 对象。应用程序可以向 SourceBuffer 对象动态添加数据片段,并可以根据系统性能及其他因素自适应调整所添加媒体数据的数据质量。来自 SourceBuffer 对象的数据可以解码为音频、视频或文本数据,并由浏览器或播放器处理。与媒体源扩展一同使用的,还是包括媒体原扩展字节流格式注册表及一组预定义的字节流格式规范。

什么是 MSE?

MSE 全称为 Media Source Extensions。

此规范扩展了 HTML Media Element [HTML] 允许 JavaScript 生成媒体流以进行播放。允许 JavaScript 生成流支持各种用例,如自适应流和时间转移直播流。

此规范允许 JavaScript 为 audio 和 video 动态构造媒体流。它定义了一个 MediaSource 对象,该对象可以作为 HtmlMedia 元素的媒体数据源。MediaSource 对象具有一个或多个 SourceBuffer 对象。应用程序将数据段附加到 SourceBuffer 对象,并可以根据系统性能和其他因素调整附加数据的质量。来自 SourceBuffer 对象的数据作为解码和播放的音频、视频和文本数据的曲目缓冲区进行管理。与这些扩展一起使用的字节流规范可在字节流格式注册表 [MSE-registry] 中找到。

背景

MSE 大大地扩展了浏览器的媒体播放功能,提供允许 JavaScript  生成媒体流。这可以用于自适应流(adaptive streaming)及随时间变化的视频直播(live streaming)等应用场景。

在这之前,浏览器提供的媒体播放功能(音频、视频)都是相当简陋的,一个 video 或者 audio 标签再加上相对应的数据 url 就搞定了。

<video src="/xxxx.mp4"></video>

但这缺少了诸如视频分段加载、视频码率切换部分加载等等现代播放器应该有的功能,所以绝大部分的浏览器视频播放器过去都是基于 Flash 开发的,这也是为什么直到现在2017年中旬,Flash 这个老古董依然在各大视频网站上活着的原因。

MediaSource 的简单使用

var supportMediaSource = 'MediaSource' in window // 判断是否支持 MediaSource
if (supportMediaSource) {
  // 新建一个 MediaSource 对象,并且把 mediaSource 作为 objectURL 附加到 video 标签上
  var mediaSource = new MediaSource()
  var video = document.querySelector('video')
  video.src = URL.createObjectURL(mediaSource)
  
  // 监听 mediaSource 上的 sourceOpen 事件
  mediaSource.addEventListener('sourceopen', sourceOpen);
  function sourceOpen {
    // todo...
  }
}

SourceBuffer

SourceBuffer 对象提供了一系列接口,可以 动态地向 MediaSource 中添加视频/音频片段(对于一个 MediaSource,可以同时存在多个 SourceBuffer)。

function sourceOpen () {
    var mime = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
    // 新建一个 sourceBuffer
    var sourceBuffer = mediaSource.addSourceBuffer(mime);
 
    // 加载一段 chunk,然后 append 到 sourceBuffer 中
    fetchBuffer('/xxxx.mp4', buffer => {
        sourceBuffer.appendBuffer(buffer)
    })
}
 
// 以二进制格式请求某个url
function fetchBuffer (url, callback) {
    var xhr = new XMLHttpRequest;
    xhr.open('get', url);
    xhr.responseType = 'arraybuffer';
    xhr.onload = function () {
        callback(xhr.response);
    };
    xhr.send();
}

浏览器兼容性

参考文档