Start · Sprachen · JavaScript · Referenz · AudioDecoder.decode()

AudioDecoder.decode()

Methode

Stellt eine Steuerungsnachricht in die Warteschlange, die einen <code>EncodedAudioChunk</code> decodiert; das Ergebnis kommt als <code>AudioData</code> im <code>output</code>-Callback an.

seit JavaScript WebCodecs API – Chrome/Edge 94+, Safari 26+, Firef Kategorie: webapi

Signatur

AudioDecoder.prototype.decode(chunk)

Beschreibung

Mit decode() übergeben Sie einem konfigurierten AudioDecoder ein Stück komprimierter Audiodaten (EncodedAudioChunk), z. B. ein AAC- oder Opus-Paket, das Sie vorher aus einem Container (MP4, WebM, Ogg) herausgelöst haben. Die Methode arbeitet asynchron: Sie gibt sofort zurück, die decodierten Samples werden später als AudioData-Objekt an den output-Callback geliefert, der im Konstruktor angegeben wurde.

Voraussetzung ist, dass der Decoder sich im Zustand "configured" befindet, also configure() vorher aufgerufen wurde. Jeder Aufruf erhöht decodeQueueSize; sobald der Decoder ein Paket verarbeitet hat, sinkt der Wert wieder und das Ereignis dequeue wird ausgelöst. Darüber lässt sich eine Rückstausteuerung (Backpressure) umsetzen, damit der Speicher nicht vollläuft.

Der erste Chunk nach configure() oder flush() muss ein Key-Chunk sein (type: "key"). Bei den meisten Audio-Codecs ist jeder Chunk ein Key-Chunk. Fehler bei der Decodierung werfen keine Ausnahme am Aufrufort, sondern landen im error-Callback, und der Decoder wird dabei geschlossen.

Um sicherzugehen, dass alle ausstehenden Ausgaben geliefert wurden (z. B. am Dateiende), rufen Sie anschließend await decoder.flush() auf.

Parameter

Name Typ Default Beschreibung
$chunk Pflicht EncodedAudioChunk Das zu decodierende Stück komprimierter Audiodaten mit type ("key" oder "delta"), timestamp (Mikrosekunden), optional duration und data.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined). Decodierte Daten kommen als AudioData im output-Callback an.

Beispiele

Decoder einrichten und einen Opus-Chunk decodieren

const decoder = new AudioDecoder({
  output: (audioData) => {
    console.log(`Frames: ${audioData.numberOfFrames}, Rate: ${audioData.sampleRate}`);
    audioData.close(); // Speicher sofort freigeben
  },
  error: (e) => console.error('Decodierfehler:', e.message),
});

decoder.configure({
  codec: 'opus',
  sampleRate: 48000,
  numberOfChannels: 2,
});

// opusPacket: Uint8Array aus einem WebM/Ogg-Demuxer
const chunk = new EncodedAudioChunk({
  type: 'key',
  timestamp: 0,       // Mikrosekunden
  duration: 20000,    // 20 ms
  data: opusPacket,
});

decoder.decode(chunk);
await decoder.flush();
console.log('Fertig, Zustand:', decoder.state);
Frames: 960, Rate: 48000 Fertig, Zustand: configured

Viele Chunks mit Backpressure über decodeQueueSize

const waitForDequeue = (decoder) =>
  new Promise((resolve) =>
    decoder.addEventListener('dequeue', resolve, { once: true })
  );

const decodeAll = async (decoder, packets) => {
  for (const { data, timestamp, duration } of packets) {
    // Warteschlange nicht über 10 Einträge anwachsen lassen
    while (decoder.decodeQueueSize > 10) {
      await waitForDequeue(decoder);
    }
    decoder.decode(new EncodedAudioChunk({ type: 'key', timestamp, duration, data }));
  }
  await decoder.flush();
};

Unterstützung prüfen und AAC mit description konfigurieren

const config = {
  codec: 'mp4a.40.2', // AAC-LC
  sampleRate: 44100,
  numberOfChannels: 2,
  description: audioSpecificConfig, // ArrayBuffer aus der MP4-esds-Box
};

const { supported } = await AudioDecoder.isConfigSupported(config);
if (!supported) {
  console.warn('AAC wird nicht unterstützt');
} else {
  const decoder = new AudioDecoder({
    output: (data) => { /* an AudioWorklet weiterreichen */ data.close(); },
    error: console.error,
  });
  decoder.configure(config);
  decoder.decode(new EncodedAudioChunk({ type: 'key', timestamp: 0, data: aacFrame }));
}

// Wichtig · Fallstricke

  • InvalidStateError (DOMException) wird synchron geworfen, wenn state nicht "configured" ist, also vor configure() oder nach close().
  • DataError wird geworfen, wenn der erste Chunk nach configure()/flush() kein Key-Chunk ist.
  • Fehler beim eigentlichen Decodieren kommen asynchron im error-Callback an. Danach ist der Decoder "closed" und muss neu erzeugt werden.
  • Rufen Sie für jedes AudioData-Objekt close() auf. Sonst bleibt der Speicher belegt und der Decoder kann ins Stocken geraten.
  • decode() übernimmt keinen Container. Das Demuxen (MP4, WebM usw.) müssen Sie selbst erledigen, z. B. mit mp4box.js.
  • Die Methode ist nur in sicheren Kontexten (HTTPS) sowie in Window und Dedicated Workern verfügbar. Welche Codecs unterstützt werden, hängt von Browser und Plattform ab; prüfen Sie das mit AudioDecoder.isConfigSupported(). Firefox unterstützt die Schnittstelle erst ab Version 130, Safari erst seit Kurzem.