docs.rodeo

MDN Web Docs mirror

MediaSource

{{APIRef("Media Source Extensions")}} {{AvailableInWorkers("window_and_dedicated")}} 

The MediaSource interface of the {{domxref("Media Source Extensions API", "Media Source Extensions API", "", "nocode")}}  represents a source of media data for an {{domxref("HTMLMediaElement")}}  object. A MediaSource object can be attached to a {{domxref("HTMLMediaElement")}}  to be played in the user agent.

{{InheritanceDiagram}} 

Constructor

Instance properties

Static properties

Instance methods

Inherits methods from its parent interface, {{domxref("EventTarget")}} .

Static methods

Events

Examples

Complete basic example

The following simple example loads a video with {{domxref("XMLHttpRequest")}} , playing it as soon as it can. This example was written by Nick Desaulniers and can be viewed live here (you can also download the source for further investigation). The function getMediaSource(), which is not defined here, returns a 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();
}

Constructing a MediaSource in a dedicated worker and passing it to the main thread

The {{domxref("MediaSource.handle", "handle")}}  property can be accessed inside a dedicated worker and the resulting {{domxref("MediaSourceHandle")}}  object is then transferred over to the thread that created the worker (in this case the main thread) via a {{domxref("DedicatedWorkerGlobalScope.postMessage()", "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 {{domxref("Worker.message_event", "message")}}  event handler, attach it to a {{htmlelement("video")}}  via its {{domxref("HTMLMediaElement.srcObject")}}  property, and {{domxref("HTMLMediaElement.play()", "play")}}  the video:

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

Note: {{domxref("MediaSourceHandle")}} s cannot be successfully transferred into or via a shared worker or service worker.

Specifications

{{Specifications}} 

Browser compatibility

{{Compat}} 

See also

In this article

View on MDN