Signatur
Beschreibung
encode() übergibt einen Block unkomprimierter Audio-Samples (AudioData) an einen konfigurierten AudioEncoder. Die Methode arbeitet asynchron und kehrt sofort zurück. Das Ergebnis erscheint später als EncodedAudioChunk im output-Callback, den du im Konstruktor angegeben hast. Tritt beim Kodieren ein Fehler auf, wird der error-Callback aufgerufen und der Encoder geschlossen.
Typische Einsatzfälle sind Audioaufnahmen im Browser (z. B. Mikrofon → Opus), eigene WebRTC- oder WebTransport-Pipelines und das Erzeugen von Audiospuren für Container wie WebM oder MP4. Vor dem ersten Aufruf muss der Encoder mit configure() eingerichtet sein. state muss also "configured" sein.
Jeder Aufruf erhöht encodeQueueSize. Ist ein Auftrag erledigt, sinkt der Wert wieder und das Ereignis dequeue wird ausgelöst. So kannst du Rückstau (Backpressure) steuern: Liefert deine Quelle schneller Daten, als der Encoder verarbeiten kann, solltest du keine weiteren Aufträge einreihen. Mit flush() wartest du darauf, dass alle ausstehenden Aufträge fertig sind. Das ist z. B. am Ende einer Aufnahme wichtig.
Der Encoder legt intern eine Kopie (einen Klon) des übergebenen AudioData an. Du kannst und solltest dein eigenes Objekt deshalb direkt nach encode() mit close() freigeben, damit der Speicher nicht vollläuft.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $data Pflicht | AudioData | Die zu kodierenden Audio-Samples. Das Objekt darf nicht geschlossen sein (nicht per close() freigegeben). Abtastrate und Kanalzahl sollten zur Konfiguration aus configure() passen. |
Rückgabewert
undefined). Kodierte Daten werden als EncodedAudioChunk an den output-Callback übergeben.Beispiele
Sinuston synthetisch erzeugen und als Opus kodieren
const chunks = [];
const encoder = new AudioEncoder({
output: (chunk, metadata) => {
chunks.push(chunk);
if (metadata?.decoderConfig) {
console.log('Decoder-Config:', metadata.decoderConfig.codec);
}
},
error: (e) => console.error('Encoder-Fehler:', e)
});
encoder.configure({
codec: 'opus',
sampleRate: 48000,
numberOfChannels: 1,
bitrate: 64000
});
// 1 Sekunde 440-Hz-Sinus in Blöcken zu 960 Frames (20 ms)
const sampleRate = 48000;
const frames = 960;
for (let block = 0; block < 50; block++) {
const samples = new Float32Array(frames);
for (let i = 0; i < frames; i++) {
const t = (block * frames + i) / sampleRate;
samples[i] = Math.sin(2 * Math.PI * 440 * t) * 0.5;
}
const audioData = new AudioData({
format: 'f32-planar',
sampleRate,
numberOfFrames: frames,
numberOfChannels: 1,
timestamp: (block * frames * 1_000_000) / sampleRate, // Mikrosekunden
data: samples
});
encoder.encode(audioData);
audioData.close(); // eigene Kopie sofort freigeben
}
await encoder.flush();
console.log(`Kodierte Chunks: ${chunks.length}`);
encoder.close();
Mikrofon live kodieren (MediaStreamTrackProcessor)
// Hinweis: MediaStreamTrackProcessor gibt es derzeit nur in Chromium-Browsern
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const [track] = stream.getAudioTracks();
const { sampleRate, channelCount = 1 } = track.getSettings();
const encoder = new AudioEncoder({
output: (chunk) => {
// z. B. per WebSocket / WebTransport verschicken
console.log(chunk.type, chunk.timestamp, chunk.byteLength);
},
error: console.error
});
encoder.configure({ codec: 'opus', sampleRate, numberOfChannels: channelCount, bitrate: 32000 });
const processor = new MediaStreamTrackProcessor({ track });
const reader = processor.readable.getReader();
while (true) {
const { value: audioData, done } = await reader.read();
if (done) break;
encoder.encode(audioData);
audioData.close();
}
await encoder.flush();
encoder.close();
Rückstau über encodeQueueSize und dequeue steuern
const MAX_QUEUE = 10;
const encoder = new AudioEncoder({
output: (chunk) => {},
error: console.error
});
encoder.configure({ codec: 'opus', sampleRate: 48000, numberOfChannels: 2 });
// Wartet, bis die Warteschlange wieder Platz hat
const waitForQueue = () =>
encoder.encodeQueueSize < MAX_QUEUE
? Promise.resolve()
: new Promise((resolve) =>
encoder.addEventListener('dequeue', resolve, { once: true })
);
const encodeSafely = async (audioData) => {
if (encoder.state !== 'configured') {
audioData.close();
return;
}
await waitForQueue();
encoder.encode(audioData);
audioData.close();
};
// Wichtig · Fallstricke
- InvalidStateError: Ist
statenicht"configured"(also vorconfigure()oder nachclose()), wirftencode()eineDOMExceptionvom TypInvalidStateError. - TypeError: Ist das übergebene
AudioDataschon geschlossen, wirft die Methode einenTypeError. Rufeclose()daher erst nachencode()auf. - Speicherlecks: Nicht geschlossene
AudioData-Objekte halten Puffer fest. Gib sie immer mitclose()frei. - Zeitstempel werden in Mikrosekunden angegeben, nicht in Millisekunden. Sie sollten lückenlos steigen.
- Fehler beim Kodieren selbst werden nicht als Ausnahme geworfen. Sie kommen asynchron im
error-Callback an, und der Encoder ist danach geschlossen. - Prüfe vorab mit
AudioEncoder.isConfigSupported(), ob der Browser den gewünschten Codec unterstützt. Welche Codecs verfügbar sind (Opus, AAC usw.), hängt vom Browser und von der Plattform ab. - Kompatibilität: WebCodecs gibt es nur in sicheren Kontexten (HTTPS), im Fenster und in Workern. Chromium unterstützt die API seit Version 94, Firefox seit Version 130. Safari unterstützt
AudioEncodererst in neueren Versionen. Nutze Feature-Erkennung:'AudioEncoder' in globalThis.