Signatur
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
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 });
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);
};
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));
// Wichtig · Fallstricke
- Nicht zum Weiterfüttern nutzen: Wer in einem
updatestart-Handler erneutappendBuffer()oderremove()aufruft, bekommt einenInvalidStateError, weilupdatingnochtrueist. Den nächsten Block hängst du inupdateendan. - Asynchrone Auslösung: Das Ereignis wird als Task in die Warteschlange gestellt und läuft nicht synchron im Aufruf von
appendBuffer().updatingist aber sofort nach dem Aufruftrue. - Nicht jede Operation endet mit
update: Nachupdatestartfolgtupdate,erroroderabort. Aufräumarbeiten, etwa das Ausblenden einer Ladeanzeige, gehören deshalb inupdateend, denn das kommt immer. QuotaExceededError: Ist der Puffer voll, wirftappendBuffer()synchron eine Ausnahme, undupdatestartwird 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
ManagedMediaSourcezur Verfügung. Prüfe die Unterstützung vorher, z. B. mit'MediaSource' in windowundMediaSource.isTypeSupported(). In Chromium-Browsern funktioniert MSE auch in Dedicated Workers.