Signatur
Beschreibung
Eine AudioWorkletNode lebt im Haupt-Thread, der zugehörige AudioWorkletProcessor dagegen im Audio-Rendering-Thread (AudioWorkletGlobalScope). Beide Objekte sind über einen MessageChannel verbunden: Die Node erhält das eine Ende als node.port, der Prozessor das andere Ende als this.port.
Über diesen Port lassen sich beliebige strukturiert klonbare Daten in beide Richtungen senden, z. B. Konfigurationen, Samples, Pegelmessungen oder Statusmeldungen. Mit postMessage() sendet man, empfangen wird über onmessage oder addEventListener("message", …).
Für Werte, die sich kontinuierlich und sample-genau ändern sollen (Lautstärke, Frequenz), sind AudioParams über parameterDescriptors meist besser geeignet. Der Port ist das Mittel der Wahl für unregelmäßige, strukturierte oder größere Datenmengen und für Rückmeldungen vom Prozessor an die Oberfläche.
Rückgabewert
MessagePort, der mit dem port des zugehörigen AudioWorkletProcessor verbunden ist. Die Eigenschaft ist schreibgeschützt und liefert immer dasselbe Objekt.Beispiele
Nachrichten in beide Richtungen senden
// processor.js (läuft im AudioWorkletGlobalScope)
class PingProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.port.onmessage = (event) => {
if (event.data === 'ping') this.port.postMessage('pong');
};
}
process() {
return true;
}
}
registerProcessor('ping-processor', PingProcessor);
// main.js (Haupt-Thread)
const ctx = new AudioContext();
await ctx.audioWorklet.addModule('processor.js');
const node = new AudioWorkletNode(ctx, 'ping-processor');
node.port.onmessage = (event) => console.log('Antwort:', event.data);
node.port.postMessage('ping');
Pegelmessung vom Prozessor an die UI melden
// meter-processor.js
class MeterProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.frames = 0;
}
process(inputs) {
const channel = inputs[0][0];
if (channel) {
let sum = 0;
for (const s of channel) sum += s * s;
// nur ca. alle 20 Blöcke senden, um den Port nicht zu fluten
if (++this.frames % 20 === 0) {
this.port.postMessage({ rms: Math.sqrt(sum / channel.length) });
}
}
return true;
}
}
registerProcessor('meter-processor', MeterProcessor);
// main.js
const ctx = new AudioContext();
await ctx.audioWorklet.addModule('meter-processor.js');
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const source = ctx.createMediaStreamSource(stream);
const meter = new AudioWorkletNode(ctx, 'meter-processor');
source.connect(meter);
meter.port.addEventListener('message', ({ data }) => {
document.querySelector('#level').value = data.rms;
});
meter.port.start(); // bei addEventListener nötig!
Große Puffer per Transfer ohne Kopie übergeben
const ctx = new AudioContext();
await ctx.audioWorklet.addModule('sampler-processor.js');
const sampler = new AudioWorkletNode(ctx, 'sampler-processor');
const response = await fetch('kick.wav');
const audioBuffer = await ctx.decodeAudioData(await response.arrayBuffer());
const samples = audioBuffer.getChannelData(0).slice(); // eigene Kopie
// ArrayBuffer wird übertragen statt kopiert
sampler.port.postMessage({ type: 'load', samples }, [samples.buffer]);
console.log(samples.length); // danach im Haupt-Thread unbrauchbar
// Wichtig · Fallstricke
start()nicht vergessen: WeraddEventListener("message", …)stattonmessageverwendet, mussport.start()aufrufen, sonst kommen keine Nachrichten an.- Keine Echtzeit-Garantie: Nachrichten werden asynchron zugestellt und sind nicht sample-genau. Für präzise Automation
AudioParams nutzen. - Performance: Im
process()-Callback nicht bei jedem Block (128 Frames) senden. Das Klonen verursacht Speicherbelegung und Garbage Collection im Audio-Thread und damit Knackser. Nachrichten drosseln oder für Hochfrequenz-Daten einenSharedArrayBufferverwenden (setzt Cross-Origin-Isolation per COOP/COEP voraus). - Große Puffer über die Transfer-Liste von
postMessage()übergeben, damit nicht kopiert wird. Der Puffer ist danach beim Absender unbrauchbar (Länge 0). - Funktionen, DOM-Knoten und andere nicht klonbare Werte lösen einen
DataCloneErroraus. - AudioWorklet steht nur in sicheren Kontexten (HTTPS oder localhost) zur Verfügung.