Start · Sprachen · JavaScript · Referenz · SourceBuffer: updatestart

SourceBuffer: updatestart

Ereignis

Wird ausgelöst, sobald ein <code>SourceBuffer</code> mit einer <code>appendBuffer()</code>- oder <code>remove()</code>-Operation beginnt und <code>updating</code> auf <code>true</code> wechselt.

seit JavaScript Media Source Extensions: Chrome, Edge, Firefox, Sa Kategorie: webapi

Signatur

sourceBuffer.addEventListener("updatestart", handler)

Beschreibung

Das Ereignis updatestart gehört zu den Media Source Extensions (MSE). Ein SourceBuffer löst es aus, sobald eine asynchrone Operation beginnt, also nach einem Aufruf von appendBuffer() oder remove(). Die Eigenschaft SourceBuffer.updating steht dann bereits auf true.

Registrieren kannst du den Handler auf zwei Arten: mit sourceBuffer.addEventListener("updatestart", handler) oder über die Eigenschaft sourceBuffer.onupdatestart = handler. Das Ereignis ist ein einfaches Event. Es steigt nicht auf (bubbling) und lässt sich nicht abbrechen.

Die Ereignisse einer Operation kommen immer in derselben Reihenfolge: updatestart, dann entweder update (Erfolg), error (Fehler) oder abort (Abbruch über abort()), und zum Schluss immer updateend. Typische Einsätze für updatestart sind Ladeanzeigen, Protokollierung, Messung der Anhängedauer oder das Sperren eigener Warteschlangen.

Für die Frage „Darf ich den nächsten Datenblock anhängen?“ ist updateend das richtige Ereignis und nicht updatestart. Solange updating auf true steht, werfen weitere Aufrufe von appendBuffer() oder remove() einen InvalidStateError.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname, immer "updatestart".
$handler Pflicht (event: Event) => void Callback, der ein einfaches Event erhält. event.target ist der auslösende SourceBuffer.
$options boolean | AddEventListenerOptions false Optionen wie once, signal oder capture (siehe addEventListener).

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück. Der Handler erhält ein Event mit bubbles === false und cancelable === false.

Beispiele

updatestart mit addEventListener protokollieren

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

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

  sourceBuffer.addEventListener('updatestart', (event) => {
    console.log('updatestart – updating:', event.target.updating);
  });
  sourceBuffer.addEventListener('updateend', () => {
    console.log('updateend – updating:', sourceBuffer.updating);
  });

  const response = await fetch('/media/init-und-segment1.mp4');
  sourceBuffer.appendBuffer(await response.arrayBuffer());
}, { once: true });
updatestart – updating: true updateend – updating: false

Ladeanzeige über die on-Property steuern und Dauer messen

const spinner = document.querySelector('#buffer-spinner');
const video = document.querySelector('video');
const mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);

mediaSource.onsourceopen = async () => {
  const sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="vp9, opus"');
  let startedAt = 0;

  sourceBuffer.onupdatestart = () => {
    startedAt = performance.now();
    spinner.hidden = false;
  };
  sourceBuffer.onupdateend = () => {
    spinner.hidden = true;
    console.log(`Anhängen dauerte ${(performance.now() - startedAt).toFixed(1)} ms`);
  };

  const data = await (await fetch('/media/clip.webm')).arrayBuffer();
  sourceBuffer.appendBuffer(data);
};
Anhängen dauerte 12.4 ms

Segment-Warteschlange mit Listener, der wieder entfernt wird

const createAppender = (sourceBuffer) => {
  const queue = [];
  let active = 0;

  const onStart = () => { active++; console.log('Operation gestartet, aktiv:', active); };
  const onEnd = () => {
    active--;
    if (queue.length > 0 && !sourceBuffer.updating) {
      sourceBuffer.appendBuffer(queue.shift());
    }
  };

  sourceBuffer.addEventListener('updatestart', onStart);
  sourceBuffer.addEventListener('updateend', onEnd);

  return {
    append(chunk) {
      if (sourceBuffer.updating || queue.length > 0) queue.push(chunk);
      else sourceBuffer.appendBuffer(chunk);
    },
    dispose() {
      // Listener sauber entfernen, z. B. beim Wechsel des Streams
      sourceBuffer.removeEventListener('updatestart', onStart);
      sourceBuffer.removeEventListener('updateend', onEnd);
      queue.length = 0;
    }
  };
};

// Nutzung innerhalb von sourceopen:
// const appender = createAppender(sourceBuffer);
// segments.forEach((s) => appender.append(s));
Operation gestartet, aktiv: 1

// Wichtig · Fallstricke

  • Nicht zum Weiterfüttern nutzen: Wer in einem updatestart-Handler erneut appendBuffer() oder remove() aufruft, bekommt einen InvalidStateError, weil updating noch true ist. Den nächsten Block hängst du in updateend an.
  • Asynchrone Auslösung: Das Ereignis wird als Task in die Warteschlange gestellt und läuft nicht synchron im Aufruf von appendBuffer(). updating ist aber sofort nach dem Aufruf true.
  • Nicht jede Operation endet mit update: Nach updatestart folgt update, error oder abort. Aufräumarbeiten, etwa das Ausblenden einer Ladeanzeige, gehören deshalb in updateend, denn das kommt immer.
  • QuotaExceededError: Ist der Puffer voll, wirft appendBuffer() synchron eine Ausnahme, und updatestart wird gar nicht ausgelöst.
  • Browser-Kompatibilität: MSE gibt es in Chrome, Edge, Firefox und Safari auf dem Desktop sowie auf dem iPad. Auf dem iPhone steht MSE erst ab iOS 17.1 als ManagedMediaSource zur Verfügung. Prüfe die Unterstützung vorher, z. B. mit 'MediaSource' in window und MediaSource.isTypeSupported(). In Chromium-Browsern funktioniert MSE auch in Dedicated Workers.