Start · Sprachen · JavaScript · Referenz · MediaSource.readyState

MediaSource.readyState

Eigenschaft

Schreibgeschützte Eigenschaft, die den aktuellen Zustand einer <code>MediaSource</code> als Zeichenkette liefert: <code>"closed"</code>, <code>"open"</code> oder <code>"ended"</code>.

seit JavaScript Baseline: alle modernen Browser (iOS Safari erst a Kategorie: webapi

Signatur

MediaSource.readyState

Beschreibung

MediaSource.readyState gibt an, in welchem Zustand sich eine MediaSource gerade befindet. Die Media Source Extensions (MSE) nutzt man, um Mediendaten wie HLS-/DASH-Segmente oder selbst erzeugte Streams per JavaScript an ein <video>- oder <audio>-Element zu übergeben. Viele Operationen sind nur in einem bestimmten Zustand erlaubt, deshalb prüft man readyState vorher.

  • "closed": Die Quelle ist an kein Medienelement angehängt. Das gilt direkt nach new MediaSource() und nach dem Lösen vom Element.
  • "open": Die Quelle ist angehängt und kann Daten annehmen. Nur in diesem Zustand funktionieren addSourceBuffer(), das Setzen von duration und endOfStream().
  • "ended": Die Quelle ist angehängt, aber endOfStream() wurde aufgerufen. Hängt man danach neue Daten an oder ruft appendBuffer() auf, springt der Zustand wieder auf "open".

Jeder Zustandswechsel löst ein Ereignis aus: sourceopen, sourceended oder sourceclose. Statt readyState regelmäßig abzufragen, reagiert man am besten auf diese Ereignisse. Ein typisches Beispiel ist, Puffer erst im sourceopen-Handler anzulegen.

Rückgabewert

Typ
"closed" | "open" | "ended"
Beschreibung
Eine Zeichenkette mit dem aktuellen Zustand der MediaSource.

Beispiele

Zustand vor und nach dem Anhängen an ein Video

const video = document.querySelector('video');
const mediaSource = new MediaSource();

console.log(mediaSource.readyState); // noch nicht angehängt

video.src = URL.createObjectURL(mediaSource);

mediaSource.addEventListener('sourceopen', () => {
  console.log(mediaSource.readyState);
}, { once: true });
closed open

Segmente laden und den Stream sauber beenden

const video = document.querySelector('video');
const mime = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
const mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);

const appendSegment = (sb, data) => new Promise((resolve, reject) => {
  sb.addEventListener('updateend', resolve, { once: true });
  sb.addEventListener('error', reject, { once: true });
  sb.appendBuffer(data);
});

mediaSource.addEventListener('sourceopen', async () => {
  URL.revokeObjectURL(video.src);
  const sb = mediaSource.addSourceBuffer(mime);

  for (const url of ['/media/init.mp4', '/media/seg1.m4s', '/media/seg2.m4s']) {
    const data = await (await fetch(url)).arrayBuffer();
    // Wurde die Quelle inzwischen geschlossen (z. B. neue src)? Dann abbrechen.
    if (mediaSource.readyState !== 'open') return;
    await appendSegment(sb, data);
  }

  if (mediaSource.readyState === 'open' && !sb.updating) {
    mediaSource.endOfStream();
  }
  console.log(mediaSource.readyState);
}, { once: true });
ended

Hilfsfunktion: sicheres endOfStream()

const safeEndOfStream = (ms, error) => {
  const busy = [...ms.sourceBuffers].some((sb) => sb.updating);
  if (ms.readyState !== 'open' || busy) {
    console.warn(`endOfStream übersprungen (readyState: ${ms.readyState})`);
    return false;
  }
  error ? ms.endOfStream(error) : ms.endOfStream();
  return true;
};

const ms = new MediaSource();
safeEndOfStream(ms);
endOfStream übersprungen (readyState: closed)

// Wichtig · Fallstricke

  • InvalidStateError: Wird addSourceBuffer(), endOfStream() oder der duration-Setter aufgerufen, während readyState nicht "open" ist, wirft der Browser eine DOMException. Bei endOfStream() und duration passiert das auch, solange ein SourceBuffer noch updating === true hat.
  • Direkt nach dem Setzen von video.src ist der Zustand noch "closed". Die Quelle öffnet sich asynchron, deshalb auf sourceopen warten.
  • Bei "ended" setzt ein erneutes appendBuffer() den Zustand automatisch zurück auf "open". Das ist praktisch für Live-Streams, kann aber unerwartet sein.
  • Die Eigenschaft ist schreibgeschützt. Eine Zuweisung wird ignoriert (im Strict Mode gibt es einen TypeError).
  • Kompatibilität: MSE wird von allen Desktop-Browsern unterstützt. iPhone-Safari bietet erst ab iOS 17.1 ManagedMediaSource an, das ebenfalls readyState hat. Vorab mit 'MediaSource' in window bzw. MediaSource.isTypeSupported() prüfen. In Dedicated Workern steht MediaSource in Chrome ab Version 108 zur Verfügung.