MediaSource
注意:此功能在 专用 Web Workers 中可用。
MediaSource 接口是 Media Source Extensions API 的一部分,它代表了 HTMLMediaElement 对象的媒体数据源。MediaSource 对象可以附加到 HTMLMediaElement 以在用户代理中播放。
构造函数
MediaSource()-
构造并返回一个新的
MediaSource对象,不关联任何源缓冲区(source buffers)。
实例属性
MediaSource.activeSourceBuffers只读-
返回一个
SourceBufferList对象,其中包含MediaSource.sourceBuffers中的SourceBuffer对象的一个子集 — 该列表提供了选定的视频轨道、启用的音频轨道以及显示/隐藏的文本轨道。 MediaSource.duration-
获取并设置当前正在呈现的媒体的时长。
MediaSource.handle只读-
在专用工作线程(dedicated worker)中,返回一个
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实例已由媒体元素打开,并且可以开始向SourceBuffer对象(位于sourceBuffers中)追加数据时触发。
示例
完整的基本示例
以下简单示例使用 XMLHttpRequest 加载视频,并在可以播放时立即播放。此示例由 Nick Desaulniers 编写,可在此处 查看实时演示(您也可以 下载源代码 进行进一步研究)。函数 getMediaSource()(此处未定义)返回一个 MediaSource。
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 属性,然后通过 postMessage() 调用将生成的 MediaSourceHandle 对象传输回创建工作线程的线程(在此例中为主线程)。
// 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 事件处理器接收句柄,通过其 HTMLMediaElement.srcObject 属性将其附加到 <video> 元素,然后 play 视频。
worker.addEventListener("message", (msg) => {
let mediaSourceHandle = msg.data.arg;
video.srcObject = mediaSourceHandle;
video.play();
});
注意: MediaSourceHandle 无法成功传输到共享工作线程或服务工作线程中,或通过它们进行传输。
规范
| 规范 |
|---|
| Media Source Extensions™ # mediasource |
浏览器兼容性
加载中…