Signatur
Beschreibung
Ein AudioWorkletProcessor läuft im AudioWorkletGlobalScope, also auf dem Audio-Rendering-Thread und getrennt vom Haupt-Thread. Die Eigenschaft port liefert einen MessagePort, der mit AudioWorkletNode.port auf der Haupt-Thread-Seite verbunden ist. Über dieses Kanalpaar tauschen beide Seiten mit postMessage() und dem message-Event beliebige strukturierbar klonbare Daten aus.
Typische Anwendungsfälle sind das Senden von Konfigurationen oder Befehlen an den Prozessor (z. B. „Reset“, neue Filterkoeffizienten, Samples zum Abspielen) und das Zurückmelden von Messwerten wie Pegel, erkannten Tonhöhen oder Statusinformationen an die Benutzeroberfläche.
Für Werte, die sich pro Sample oder pro Block kontinuierlich und zeitgenau ändern sollen, ist AudioParam (über static get parameterDescriptors()) meist die bessere Wahl. Der Port eignet sich für seltene, ereignisartige Nachrichten. Größere Binärdaten sollten als Transferable (z. B. ArrayBuffer) übertragen werden, um Kopien zu vermeiden.
Rückgabewert
AudioWorkletNode.port verbundene MessagePort. Die Eigenschaft ist schreibgeschützt; der Port ist bereits gestartet, wenn onmessage gesetzt wird.Beispiele
Befehle vom Haupt-Thread empfangen
// gain-processor.js (AudioWorkletGlobalScope)
class GainProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.gain = 1;
// Nachrichten vom AudioWorkletNode entgegennehmen
this.port.onmessage = (event) => {
const { type, value } = event.data;
if (type === 'setGain') this.gain = value;
};
}
process(inputs, outputs) {
const input = inputs[0];
const output = outputs[0];
for (let ch = 0; ch < output.length; ch++) {
const inCh = input[ch];
const outCh = output[ch];
if (!inCh) continue;
for (let i = 0; i < outCh.length; i++) outCh[i] = inCh[i] * this.gain;
}
return true;
}
}
registerProcessor('gain-processor', GainProcessor);
// main.js (Haupt-Thread)
const ctx = new AudioContext();
await ctx.audioWorklet.addModule('gain-processor.js');
const node = new AudioWorkletNode(ctx, 'gain-processor');
node.port.postMessage({ type: 'setGain', value: 0.5 });
Pegelmesser: Werte an die Oberfläche zurückmelden
// 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;
const rms = Math.sqrt(sum / channel.length);
// nur ca. alle 20 Blöcke senden, um den Port nicht zu fluten
if (++this.frames % 20 === 0) this.port.postMessage({ rms });
}
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.onmessage = ({ data }) => {
console.log(`Pegel: ${data.rms.toFixed(3)}`);
};
Audiodaten per Transferable übertragen
// main.js – Sample-Daten ohne Kopie an den Prozessor schicken
const samples = new Float32Array(48000).map((_, i) => Math.sin(i / 10));
node.port.postMessage({ type: 'load', buffer: samples.buffer }, [samples.buffer]);
console.log(samples.byteLength); // Puffer wurde übertragen
// im Prozessor-Konstruktor
this.port.onmessage = ({ data }) => {
if (data.type === 'load') this.sample = new Float32Array(data.buffer);
};
// Wichtig · Fallstricke
- Echtzeit-Thread:
process()läuft unter harten Zeitvorgaben (ca. 2,67 ms pro 128-Frame-Block bei 48 kHz). HäufigespostMessage()erzeugt Objekte und Garbage-Collection-Druck – Nachrichten drosseln oder für kontinuierlichen DatenaustauschSharedArrayBuffermit Ringpuffer verwenden (erfordert Cross-Origin-Isolation via COOP/COEP-Header). - Mit
onmessagewird der Port automatisch gestartet; beiaddEventListener('message', …)mussport.start()explizit aufgerufen werden. - Nachrichten kommen asynchron an, also nicht sample-genau. Für zeitgenaue Parameteränderungen
AudioParamnutzen. - Für einmalige Startwerte kann alternativ
processorOptionsimAudioWorkletNode-Konstruktor verwendet werden – die Werte stehen dann bereits im Prozessor-Konstruktor zur Verfügung. - AudioWorklet steht nur in sicheren Kontexten (HTTPS oder localhost) zur Verfügung. Unterstützt in Chrome 66+, Firefox 76+ und Safari 14.1+.