Start · Sprachen · JavaScript · Referenz · MediaSourceHandle

MediaSourceHandle

Schnittstelle

Übertragbarer Stellvertreter für ein in einem dedizierten Worker erzeugtes <code>MediaSource</code>, der im Haupt-Thread per <code>srcObject</code> an ein Medienelement gebunden wird.

seit JavaScript Chrome/Edge 108+; nicht in allen Browsern verfügba Kategorie: webapi

Signatur

interface MediaSourceHandle

Beschreibung

Das Interface MediaSourceHandle gehört zu den Media Source Extensions (MSE). Es ermöglicht, ein MediaSource-Objekt in einem dedizierten Worker zu erzeugen und zu befüllen, die Wiedergabe aber im Haupt-Thread über ein <video>- oder <audio>-Element laufen zu lassen. So lassen sich aufwendige Arbeiten wie das Laden von Segmenten, Demuxen, Transmuxen oder Entschlüsseln aus dem Haupt-Thread herausnehmen. Die Oberfläche bleibt dadurch flüssig, und die Wiedergabe stockt nicht, wenn der Haupt-Thread gerade beschäftigt ist.

Man erzeugt ein Handle nicht selbst, es gibt keinen Konstruktor. Stattdessen liest man im Worker die Eigenschaft MediaSource.prototype.handle aus. Dieses Objekt ist übertragbar (transferable): Man schickt es mit postMessage(handle, [handle]) an den Haupt-Thread und weist es dort HTMLMediaElement.srcObject zu. Die eigentliche Datenversorgung über SourceBuffer.appendBuffer() läuft weiter im Worker.

Das Interface hat keine eigenen Eigenschaften oder Methoden. Es ist nur ein undurchsichtiger Verweis auf das zugehörige MediaSource. Ob ein Browser MSE in Workern unterstützt, prüft man mit der statischen Eigenschaft MediaSource.canConstructInDedicatedWorker.

Rückgabewert

Typ
MediaSourceHandle
Beschreibung
Wird über MediaSource.prototype.handle in einem dedizierten Worker abgerufen. Für jede MediaSource gibt es genau ein Handle, jeder Zugriff liefert dasselbe Objekt.

Beispiele

Worker: MediaSource erzeugen und Handle übertragen

// media-worker.js
const mediaSource = new MediaSource();
const handle = mediaSource.handle;

// Handle als übertragbares Objekt an den Haupt-Thread senden
postMessage({ type: 'handle', handle }, [handle]);

mediaSource.addEventListener('sourceopen', async () => {
  const mime = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
  const sourceBuffer = mediaSource.addSourceBuffer(mime);

  const response = await fetch('/media/video-fragmentiert.mp4');
  const data = await response.arrayBuffer();

  sourceBuffer.addEventListener('updateend', () => {
    if (mediaSource.readyState === 'open') {
      mediaSource.endOfStream();
    }
  }, { once: true });

  sourceBuffer.appendBuffer(data);
  console.log('Segment wird im Worker angehängt');
});
Segment wird im Worker angehängt

Haupt-Thread: Handle an ein Video-Element binden

const video = document.querySelector('video');
const worker = new Worker('media-worker.js');

worker.addEventListener('message', ({ data }) => {
  if (data.type === 'handle') {
    console.log(data.handle instanceof MediaSourceHandle);
    // Wichtig: srcObject verwenden, nicht src/createObjectURL
    video.srcObject = data.handle;
    video.play().catch((err) => console.warn('Autoplay blockiert:', err));
  }
});
true

Feature-Erkennung mit Rückfall auf den Haupt-Thread

const supportsWorkerMse = () =>
  'MediaSource' in window &&
  MediaSource.canConstructInDedicatedWorker === true &&
  'MediaSourceHandle' in window;

const video = document.querySelector('video');

if (supportsWorkerMse()) {
  const worker = new Worker('media-worker.js');
  worker.onmessage = ({ data }) => {
    if (data.type === 'handle') video.srcObject = data.handle;
  };
  console.log('MSE läuft im Worker');
} else {
  // Rückfall: klassisches MSE im Haupt-Thread
  const mediaSource = new MediaSource();
  video.src = URL.createObjectURL(mediaSource);
  console.log('MSE läuft im Haupt-Thread');
}
MSE läuft im Worker

// Wichtig · Fallstricke

  • Browser-Unterstützung: Chromium-Browser ab Version 108 unterstützen die Schnittstelle. In anderen Browsern fehlt sie teilweise oder ganz. Deshalb vorher immer MediaSource.canConstructInDedicatedWorker prüfen und einen Rückfall auf den Haupt-Thread vorsehen.
  • Nur dedizierte Worker: In Shared Workern und Service Workern kann man MediaSource nicht erzeugen.
  • Übertragen statt kopieren: Das Handle muss in der Transfer-Liste von postMessage() stehen. Ohne diese Liste wirft der Aufruf einen DataCloneError. Ein Handle lässt sich nur einmal übertragen. Nach der Übertragung ist es im Worker nicht mehr nutzbar, und eine zweite Übertragung schlägt fehl.
  • srcObject statt src: Im Worker erzeugt URL.createObjectURL() keine Wiedergabe-URL für eine MediaSource. Im Haupt-Thread muss man das Handle video.srcObject zuweisen.
  • Das Handle lässt sich nur an ein einziges Medienelement binden. Die MediaSource selbst und ihre SourceBuffer-Objekte bleiben im Worker. Man steuert sie also dort, zum Beispiel für appendBuffer(), endOfStream() oder duration.
  • Ereignisse des Medienelements wie seeking oder timeupdate kommen im Haupt-Thread an. Wenn der Worker darauf reagieren soll, muss man sie ihm selbst per postMessage() weiterleiten.