Signatur
Beschreibung
appendBufferAsync() ist die Promise-basierte Variante von SourceBuffer.appendBuffer(). Die Methode startet das Anhängen von Mediendaten (Initialisierungs- oder Mediensegmente) an den Puffer. Das zurückgegebene Promise wird erfüllt, sobald die Daten verarbeitet sind. Das entspricht dem Zeitpunkt, an dem bei appendBuffer() das Ereignis updateend ausgelöst wird.
Der Vorteil gegenüber der klassischen Methode: Statt Ereignis-Listener für update, updateend und error zu registrieren, kann man Segmente mit async/await einfach nacheinander anhängen. So bleibt der Code für adaptives Streaming (z. B. DASH oder HLS über die Media Source Extensions) übersichtlich.
Wichtig: Die Methode steht in keiner Spezifikation. Sie war nur ein Experiment in Firefox und ist dort standardmäßig ausgeschaltet. In Produktivcode sollte man immer vorher prüfen, ob sie vorhanden ist, und sonst auf appendBuffer() mit einem eigenen Promise-Wrapper ausweichen (siehe Beispiele).
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $source Pflicht | ArrayBuffer | TypedArray | DataView | Die Mediendaten, die angehängt werden, z. B. ein fMP4- oder WebM-Segment, das per fetch() geladen wurde. |
Rückgabewert
Promise, das ohne Wert erfüllt wird, sobald das Anhängen fertig ist. Es wird abgelehnt, wenn das Anhängen fehlschlägt oder abgebrochen wird (z. B. QuotaExceededError bei vollem Puffer oder InvalidStateError, wenn der SourceBuffer aus der MediaSource entfernt wurde).Beispiele
Plattformübergreifender Wrapper mit Fallback
// Nutzt appendBufferAsync(), wenn vorhanden, sonst appendBuffer() + Ereignisse
const appendAsync = (sourceBuffer, data) => {
if (typeof sourceBuffer.appendBufferAsync === 'function') {
return sourceBuffer.appendBufferAsync(data);
}
return new Promise((resolve, reject) => {
const onEnd = () => { cleanup(); resolve(); };
const onError = () => { cleanup(); reject(new Error('Anhängen fehlgeschlagen')); };
const cleanup = () => {
sourceBuffer.removeEventListener('updateend', onEnd);
sourceBuffer.removeEventListener('error', onError);
};
sourceBuffer.addEventListener('updateend', onEnd);
sourceBuffer.addEventListener('error', onError);
sourceBuffer.appendBuffer(data);
});
};
Segmente nacheinander in ein Video streamen
const video = document.querySelector('video');
const mime = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
const segments = ['init.mp4', 'seg-1.m4s', 'seg-2.m4s', 'seg-3.m4s'];
const mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', async () => {
const sb = mediaSource.addSourceBuffer(mime);
for (const url of segments) {
const data = await (await fetch(url)).arrayBuffer();
await sb.appendBufferAsync(data); // wartet auf das Ende des Anhängens
console.log(`Angehängt: ${url}`);
}
mediaSource.endOfStream();
}, { once: true });
Vollen Puffer (QuotaExceededError) abfangen
const appendWithEviction = async (sb, video, data) => {
try {
await sb.appendBufferAsync(data);
} catch (err) {
if (err.name === 'QuotaExceededError') {
// Alte, bereits abgespielte Daten entfernen und erneut versuchen
const end = Math.max(0, video.currentTime - 10);
await sb.removeAsync(0, end);
await sb.appendBufferAsync(data);
} else {
throw err;
}
}
};
// Wichtig · Fallstricke
- Nicht standardisiert und experimentell: Die Methode gibt es nur in Firefox (ab Version 62) hinter dem Flag
media.mediasource.experimental.enabled. Chrome, Edge und Safari unterstützen sie nicht. Vor der Nutzung immer mittypeof sb.appendBufferAsync === 'function'prüfen. - Wie bei
appendBuffer()darf nicht angehängt werden, währendsourceBuffer.updatingden Werttruehat. Sonst gibt es einenInvalidStateError. Deshalb jedes Anhängen mitawaitabwarten, bevor das nächste startet. - Ist die
MediaSourceim Zustandended, wird sie durch das Anhängen wieder aufopengesetzt. Ist sieclosedoder wurde der Puffer entfernt, schlägt das Promise fehl. - Browser begrenzen den Puffer (oft rund 100–150 MB für Video). Bei langen Streams abgespielte Bereiche mit
remove()freigeben, sonst droht einQuotaExceededError. - Die Media Source Extensions sind in Worker-Kontexten nur eingeschränkt verfügbar. Auf iPhones gibt es statt
MediaSourcenurManagedMediaSource(ab iOS 17.1).