MediaSource

有限可用性

此功能不是基线,因为它不适用于某些最常用的浏览器。

MediaSource媒体源扩展 API 的一个接口,它代表了 HTMLMediaElement 对象的媒体数据源。MediaSource 对象可以附加到 HTMLMediaElement 以便在用户代理中播放。

EventTarget MediaSource

构造函数

MediaSource()

构造并返回一个新的 MediaSource 对象,没有关联的源缓冲区。

实例属性

MediaSource.activeSourceBuffers 只读

返回一个 SourceBufferList 对象,它包含 MediaSource.sourceBuffers 中包含的 SourceBuffer 对象的子集 - 提供所选视频轨道的对象列表,已启用的音频轨道以及显示/隐藏的文本轨道。

MediaSource.duration

获取和设置当前呈现的媒体的时长。

MediaSource.handle 只读

在专用工作线程中,返回一个 MediaSourceHandle 对象,它是 MediaSource 的代理,可以从工作线程传输回主线程,并通过其 HTMLMediaElement.srcObject 属性附加到媒体元素。

MediaSource.readyState 只读

返回一个枚举,表示当前 MediaSource 的状态,无论是当前未附加到媒体元素 (closed),附加并准备接收 SourceBuffer 对象 (open),还是附加但流已通过 MediaSource.endOfStream() 结束 (ended.)。

MediaSource.sourceBuffers 只读

返回一个 SourceBufferList 对象,其中包含与该 MediaSource 关联的 SourceBuffer 对象列表。

静态属性

MediaSource.canConstructInDedicatedWorker 只读

布尔值;如果实现了 MediaSource 工作线程支持,则返回 true,提供低延迟的功能检测机制。

实例方法

从其父接口 EventTarget 继承方法。

MediaSource.addSourceBuffer()

创建一个指定 MIME 类型的新的 SourceBuffer,并将它添加到 MediaSource.sourceBuffers 列表中。

MediaSource.clearLiveSeekableRange()

清除之前通过调用 setLiveSeekableRange() 设置的可搜索范围。

MediaSource.endOfStream()

发出流结束的信号。

MediaSource.removeSourceBuffer()

MediaSource.sourceBuffers 列表中移除给定的 SourceBuffer

MediaSource.setLiveSeekableRange()

设置用户可以在媒体元素中搜索到的范围。

静态方法

MediaSource.isTypeSupported()

返回一个布尔值,指示当前用户代理是否支持给定的 MIME 类型 - 也就是说,它是否能够为该 MIME 类型成功创建 SourceBuffer 对象。

事件

sourceclose

MediaSource 实例不再附加到媒体元素时触发。

sourceended

MediaSource 实例仍然附加到媒体元素,但 endOfStream() 已被调用时触发。

sourceopen

MediaSource 实例被媒体元素打开并准备接收数据附加到 sourceBuffers 中的 SourceBuffer 对象时触发。

示例

完整的基本示例

以下简单示例使用 XMLHttpRequest 加载视频,并在视频可用时立即播放它。此示例由 Nick Desaulniers 编写,可以 在此处查看 (您也可以 下载源代码 以供进一步研究)。函数 getMediaSource() 未在此定义,它返回一个 MediaSource

js
const video = document.querySelector("video");

const assetURL = "frag_bunny.mp4";
// Need to be specific for Blink regarding codecs
// ./mp4info frag_bunny.mp4 | grep Codec
const mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
let mediaSource;

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

function sourceOpen() {
  console.log(this.readyState); // open
  const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
  fetchAB(assetURL, (buf) => {
    sourceBuffer.addEventListener("updateend", () => {
      mediaSource.endOfStream();
      video.play();
      console.log(mediaSource.readyState); // ended
    });
    sourceBuffer.appendBuffer(buf);
  });
}

function fetchAB(url, cb) {
  console.log(url);
  const xhr = new XMLHttpRequest();
  xhr.open("get", url);
  xhr.responseType = "arraybuffer";
  xhr.onload = () => {
    cb(xhr.response);
  };
  xhr.send();
}

在专用工作线程中构造 MediaSource 并将其传递给主线程

可以使用专用工作线程中的 handle 属性访问 MediaSourceHandle 对象,然后通过 postMessage() 调用将其传输到创建工作线程的线程(在本例中为主线程)。

js
// Inside dedicated worker
let mediaSource = new MediaSource();
let handle = mediaSource.handle;
// Transfer the handle to the context that created the worker
postMessage({ arg: handle }, [handle]);

mediaSource.addEventListener("sourceopen", () => {
  // Await sourceopen on MediaSource before creating SourceBuffers
  // and populating them with fetched media — MediaSource won't
  // accept creation of SourceBuffers until it is attached to the
  // HTMLMediaElement and its readyState is "open"
});

在主线程中,我们通过 message 事件处理程序接收句柄,将其附加到 <video>HTMLMediaElement.srcObject 属性,并 play 视频。

js
worker.addEventListener("message", (msg) => {
  let mediaSourceHandle = msg.data.arg;
  video.srcObject = mediaSourceHandle;
  video.play();
});

注意: MediaSourceHandle 不能成功传输到共享工作线程或服务工作线程中或通过它们传输。

规范

规范
媒体源扩展™
# mediasource

浏览器兼容性

BCD 表仅在浏览器中加载

参见