Start · Sprachen · JavaScript · Referenz · AudioEncoder.flush()

AudioEncoder.flush()

Methode

Gibt ein Promise zurück, das erfüllt wird, sobald alle ausstehenden Kodierungsaufträge des <code>AudioEncoder</code> abgearbeitet und ausgegeben wurden.

seit JavaScript WebCodecs API – Chromium 94+, Safari 26+ (Firefox: Kategorie: webapi

Signatur

AudioEncoder.prototype.flush()

Beschreibung

Die Methode flush() der Schnittstelle AudioEncoder (WebCodecs-API) zwingt den Encoder, alle noch in der internen Warteschlange liegenden AudioData-Blöcke fertig zu kodieren. Jeder dabei entstehende EncodedAudioChunk wird über den beim Konstruktor angegebenen output-Callback ausgegeben. Erst danach wird das zurückgegebene Promise erfüllt.

Encoder puffern Eingaben oft intern, z. B. weil Codecs wie Opus oder AAC in festen Rahmengrößen arbeiten. Ohne flush() können die letzten Audiodaten eines Streams deshalb im Encoder hängen bleiben. Typische Einsatzfälle sind:

  • das Ende einer Aufnahme, bevor die Datei gemuxt oder hochgeladen wird,
  • ein Wechsel der Konfiguration, wenn alle Daten mit den alten Einstellungen fertig kodiert sein sollen,
  • das Aufräumen, bevor close() aufgerufen wird.

flush() darf nur aufgerufen werden, wenn der Encoder im Zustand "configured" ist (encoder.state). Sonst wird ein Promise zurückgegeben, das mit einer InvalidStateError-DOMException abgelehnt wird. Rufst du während eines laufenden Flush reset() oder close() auf, wird das Promise mit einer AbortError-DOMException abgelehnt.

Rückgabewert

Typ
Promise<undefined>
Beschreibung
Ein Promise, das mit undefined erfüllt wird, sobald alle ausstehenden Kodierungsaufträge abgeschlossen sind und ihre output-Callbacks ausgeführt wurden. Abgelehnt wird es mit InvalidStateError (Encoder nicht konfiguriert), mit AbortError (durch reset()/close() abgebrochen) oder mit einem Kodierungsfehler.

Beispiele

Aufnahme abschließen und alle Chunks einsammeln

const chunks = [];

const encoder = new AudioEncoder({
  output: (chunk) => chunks.push(chunk),
  error: (e) => console.error('Encoder-Fehler:', e)
});

encoder.configure({
  codec: 'opus',
  sampleRate: 48000,
  numberOfChannels: 1,
  bitrate: 64000
});

// 1 Sekunde Sinuston als AudioData erzeugen
const sampleRate = 48000;
const samples = new Float32Array(sampleRate);
for (let i = 0; i < samples.length; i++) {
  samples[i] = Math.sin(2 * Math.PI * 440 * i / sampleRate) * 0.2;
}

const data = new AudioData({
  format: 'f32',
  sampleRate,
  numberOfFrames: samples.length,
  numberOfChannels: 1,
  timestamp: 0,
  data: samples
});

encoder.encode(data);
data.close();

// Warten, bis wirklich alles kodiert ist
await encoder.flush();
console.log('Fertig, Chunks:', chunks.length);
encoder.close();
Fertig, Chunks: 50

Mikrofon-Stream sauber beenden

const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const [track] = stream.getAudioTracks();
const settings = track.getSettings();

const encoder = new AudioEncoder({
  output: (chunk, meta) => {
    // hier z. B. an einen Muxer weiterreichen
    console.log('Chunk', chunk.timestamp, chunk.byteLength);
  },
  error: console.error
});

encoder.configure({
  codec: 'opus',
  sampleRate: settings.sampleRate ?? 48000,
  numberOfChannels: settings.channelCount ?? 1
});

const reader = new MediaStreamTrackProcessor({ track }).readable.getReader();

const stopAfter = (ms) => new Promise((r) => setTimeout(r, ms));
const stop = stopAfter(3000).then(() => track.stop());

while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  encoder.encode(value);
  value.close();
}

await stop;
await encoder.flush(); // letzte gepufferte Frames ausgeben
encoder.close();
console.log('Aufnahme vollständig kodiert');
Chunk 0 ... ... Aufnahme vollständig kodiert

Fehlerbehandlung bei falschem Zustand

const encoder = new AudioEncoder({
  output: () => {},
  error: console.error
});

// Noch nicht konfiguriert → state === 'unconfigured'
try {
  await encoder.flush();
} catch (err) {
  console.log(err.name, '- Zustand:', encoder.state);
}
InvalidStateError - Zustand: unconfigured

// Wichtig · Fallstricke

  • Immer vor close() abwarten: close() verwirft alle ausstehenden Aufträge sofort. Ohne ein vorheriges await encoder.flush() fehlen die letzten Audiodaten.
  • Nicht bei jedem Frame flushen: Ein Flush leert die Pipeline komplett. Bei manchen Codecs wird dabei der letzte Rahmen aufgefüllt, und Encoder-Optimierungen gehen verloren. Nutze flush() nur am Stream-Ende oder bei Konfigurationswechseln. Für Rückstau-Steuerung eignen sich encodeQueueSize und das Event dequeue besser.
  • Abbruch: reset() oder close() während eines laufenden Flush lehnen das Promise mit AbortError ab. Fange diesen Fall ab.
  • Fehler-Callback: Kodierungsfehler landen zusätzlich im error-Callback, und der Encoder wechselt in den Zustand "closed".
  • Kompatibilität: Die WebCodecs-API gibt es nur in sicheren Kontexten (HTTPS) und in Window- und Dedicated-Worker-Kontexten. AudioEncoder wird von Chromium-Browsern seit Version 94 unterstützt. In Safari und Firefox ist die Unterstützung jüngeren Datums bzw. eingeschränkt. Prüfe vorher mit 'AudioEncoder' in globalThis und AudioEncoder.isConfigSupported().