Signatur
Beschreibung
Das Ereignis sourceended gehört zur Media Source Extensions API (MSE). Es wird an einem MediaSource-Objekt ausgelöst, sobald dessen readyState von "open" auf "ended" wechselt. Das geschieht, wenn die Anwendung MediaSource.prototype.endOfStream() aufruft. Damit teilt sie dem Browser mit, dass keine weiteren Mediendaten mehr angehängt werden.
Du kannst den Handler per addEventListener("sourceended", handler) oder über die Eigenschaft mediaSource.onsourceended registrieren. Das Ereignis ist ein einfaches Event ohne zusätzliche Eigenschaften. Es bubbelt nicht und lässt sich nicht abbrechen.
In der Praxis dient sourceended dazu, eigene Streaming-Player (Adaptive Streaming, DASH/HLS-Implementierungen) zu steuern: Oberflächenelemente aktualisieren, Download-Logik beenden oder Statistiken protokollieren. Wichtig ist, dass "ended" nicht endgültig ist. Ein erneuter Aufruf von SourceBuffer.appendBuffer() oder remove() setzt den Zustand wieder auf "open" und löst dabei sourceopen erneut aus.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignistyp, hier immer "sourceended". |
|
| $handler Pflicht | (event: Event) => void | Callback, der mit einem gewöhnlichen Event-Objekt aufgerufen wird; event.target ist die betroffene MediaSource. |
|
| $options | boolean | AddEventListenerOptions | false | Optionale Listener-Optionen wie once oder signal. |
Rückgabewert
addEventListener() gibt nichts zurück. Der Handler erhält ein Event ohne zusätzliche Eigenschaften.Beispiele
Stream abschließen und auf sourceended reagieren
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);
const data = await (await fetch('/media/clip.mp4')).arrayBuffer();
sourceBuffer.addEventListener('updateend', () => {
// Alle Daten angehängt → Stream beenden
if (!sourceBuffer.updating && mediaSource.readyState === 'open') {
mediaSource.endOfStream();
}
}, { once: true });
sourceBuffer.appendBuffer(data);
});
mediaSource.addEventListener('sourceended', () => {
console.log('Stream beendet, readyState:', mediaSource.readyState);
console.log('Dauer:', mediaSource.duration.toFixed(2), 's');
});
Handler über die on-Property setzen und wieder entfernen
const mediaSource = new MediaSource();
document.querySelector('video').src = URL.createObjectURL(mediaSource);
mediaSource.onsourceended = (event) => {
console.log('sourceended auf', event.target.constructor.name);
document.querySelector('#status').textContent = 'Vollständig geladen';
// Handler nur einmal benötigt
mediaSource.onsourceended = null;
};
Alle Zustandswechsel protokollieren und Listener per AbortController entfernen
const mediaSource = new MediaSource();
const controller = new AbortController();
const log = (e) => console.log(`${e.type} → readyState=${mediaSource.readyState}`);
for (const type of ['sourceopen', 'sourceended', 'sourceclose']) {
mediaSource.addEventListener(type, log, { signal: controller.signal });
}
const video = document.querySelector('video');
video.src = URL.createObjectURL(mediaSource);
// Später, z. B. beim Zerstören des Players:
// controller.abort(); // entfernt alle drei Listener
// Wichtig · Fallstricke
endOfStream()darf nur aufgerufen werden, wennreadyState === "open"ist und keinSourceBuffergerade aktualisiert (updating === false). Sonst wirft die Methode eineInvalidStateError-DOMException, undsourceendedwird nicht ausgelöst.- Auch
endOfStream("network")oderendOfStream("decode")lösensourceendedaus. Das Ereignis selbst unterscheidet aber nicht zwischen regulärem Ende und Fehler. Den Fehlerfall erkennst du zusätzlich amerror-Ereignis des<video>-Elements. - Der Zustand
"ended"lässt sich umkehren:appendBuffer()oderremove()öffnet die Quelle wieder und löstsourceopenerneut aus. Programmiere Handler daher so, dass sie mehrfach laufen dürfen (idempotent). sourceendedist nicht dasselbe wie dasended-Ereignis des Media-Elements. Letzteres kommt erst, wenn die Wiedergabe tatsächlich das Ende erreicht hat.- Kompatibilität: Das Ereignis wird in Chrome, Edge, Firefox und Safari (Desktop) unterstützt. Auf dem iPhone steht MSE erst ab iOS 17.1 als
ManagedMediaSourcezur Verfügung. Prüfe die Unterstützung mit'MediaSource' in windowbzw.MediaSource.isTypeSupported().