MediaSource
Limited availability
This feature is not Baseline because it does not work in some of the most widely-used browsers.
Want more support for this feature? Tell us why.
Note: This feature is available in Dedicated Web Workers.
The MediaSource interface of the Media Source Extensions API represents a source of media data for an HTMLMediaElement object. A MediaSource object can be attached to a HTMLMediaElement to be played in the user agent.
Constructor
MediaSource()-
Constructs and returns a new
MediaSourceobject with no associated source buffers.
Instance properties
MediaSource.activeSourceBuffersRead only-
Returns a
SourceBufferListobject containing a subset of theSourceBufferobjects contained withinMediaSource.sourceBuffers— the list of objects providing the selected video track, enabled audio tracks, and shown/hidden text tracks. MediaSource.duration-
Gets and sets the duration of the current media being presented.
MediaSource.handleRead only-
Inside a dedicated worker, returns a
MediaSourceHandleobject, a proxy for theMediaSourcethat can be transferred from the worker back to the main thread and attached to a media element via itsHTMLMediaElement.srcObjectproperty. MediaSource.readyStateRead only-
Returns an enum representing the state of the current
MediaSource, whether it is not currently attached to a media element (closed), attached and ready to receiveSourceBufferobjects (open), or attached but the stream has been ended viaMediaSource.endOfStream()(ended.) MediaSource.sourceBuffersRead only-
Returns a
SourceBufferListobject containing the list ofSourceBufferobjects associated with thisMediaSource.
Static properties
MediaSource.canConstructInDedicatedWorkerRead only-
A boolean; returns
trueifMediaSourceworker support is implemented, providing a low-latency feature detection mechanism.
Instance methods
Inherits methods from its parent interface, EventTarget.
MediaSource.addSourceBuffer()-
Creates a new
SourceBufferof the given MIME type and adds it to theMediaSource.sourceBufferslist. MediaSource.clearLiveSeekableRange()-
Clears a seekable range previously set with a call to
setLiveSeekableRange(). MediaSource.endOfStream()-
Signals the end of the stream.
MediaSource.removeSourceBuffer()-
Removes the given
SourceBufferfrom theMediaSource.sourceBufferslist. MediaSource.setLiveSeekableRange()-
Sets the range that the user can seek to in the media element.
Static methods
MediaSource.isTypeSupported()-
Returns a boolean value indicating whether the current user agent supports the given MIME type — this is, if it can successfully create
SourceBufferobjects for that MIME type.
Events
sourceclose-
Fired when the
MediaSourceinstance is not attached to a media element anymore. sourceended-
Fired when the
MediaSourceinstance is still attached to a media element, butendOfStream()has been called. sourceopen-
Fired when a media element has opened the
MediaSourceinstance and it is ready for data to be appended to theSourceBufferobjects insourceBuffers.
Examples
>Complete basic example
The following basic example loads a video using XMLHttpRequest and plays it as soon as it can. This example can be viewed live here (you can also download the source for further investigation).
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 = 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);
}
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();
}
Constructing a MediaSource in a dedicated worker and passing it to the main thread
The handle property can be accessed inside a dedicated worker, and the resulting MediaSourceHandle object is then transferred over to the thread that created the worker (in this case, the main thread) via a postMessage() call:
// 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"
});
Over in the main thread, we receive the handle via a message event handler, attach it to a <video> via its HTMLMediaElement.srcObject property, and play the video:
worker.addEventListener("message", (msg) => {
let mediaSourceHandle = msg.data.arg;
video.srcObject = mediaSourceHandle;
video.play();
});
Note:
MediaSourceHandles cannot be successfully transferred into or via a shared worker or service worker.
Specifications
| Specification |
|---|
| Media Source Extensions™> # mediasource> |