Signatur
Beschreibung
registerProcessor() ist eine globale Funktion, die nur im AudioWorkletGlobalScope verfügbar ist, also in dem Modul, das per audioContext.audioWorklet.addModule() geladen wird. Mit ihr meldest du eine eigene Audio-Verarbeitungsklasse unter einem eindeutigen Namen an. Im Haupt-Thread erzeugt anschließend new AudioWorkletNode(context, name) eine Instanz dieses Prozessors, die direkt im Audio-Rendering-Thread läuft.
Die übergebene Klasse muss von AudioWorkletProcessor erben und eine Methode process(inputs, outputs, parameters) bereitstellen. Optional kann sie über einen statischen Getter parameterDescriptors automatisierbare AudioParam-Werte festlegen. Diese Descriptors werden bei der Registrierung einmal ausgelesen und geprüft.
Du brauchst die Methode immer dann, wenn eingebaute Knoten wie GainNode oder BiquadFilterNode nicht reichen, etwa für eigene Synthesizer, Effekte, Pegelmesser oder Analysen mit geringer Latenz, ohne den Haupt-Thread zu belasten.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $name Pflicht | string | Eindeutiger, nicht leerer Name, unter dem der Prozessor registriert wird. Genau dieser Name wird später an den Konstruktor von AudioWorkletNode übergeben. |
|
| $processorCtor Pflicht | typeof AudioWorkletProcessor | Klassenkonstruktor, der von AudioWorkletProcessor erbt. Er darf optional einen statischen Getter parameterDescriptors haben, der ein iterierbares Objekt von AudioParamDescriptor-Objekten liefert. |
Rückgabewert
Beispiele
Einfacher Rausch-Generator registrieren
// white-noise-processor.js (läuft im AudioWorkletGlobalScope)
class WhiteNoiseProcessor extends AudioWorkletProcessor {
process(inputs, outputs) {
const output = outputs[0];
for (const channel of output) {
for (let i = 0; i < channel.length; i++) {
channel[i] = Math.random() * 2 - 1;
}
}
return true; // Prozessor weiterlaufen lassen
}
}
registerProcessor('white-noise', WhiteNoiseProcessor);
// main.js (Haupt-Thread)
const ctx = new AudioContext();
await ctx.audioWorklet.addModule('white-noise-processor.js');
const noise = new AudioWorkletNode(ctx, 'white-noise');
noise.connect(ctx.destination);
Prozessor mit automatisierbarem Parameter (Gain)
// gain-processor.js
class SimpleGainProcessor extends AudioWorkletProcessor {
static get parameterDescriptors() {
return [{
name: 'gain',
defaultValue: 0.5,
minValue: 0,
maxValue: 1,
automationRate: 'a-rate'
}];
}
process(inputs, outputs, parameters) {
const input = inputs[0];
const output = outputs[0];
const gain = parameters.gain;
for (let ch = 0; ch < input.length; ch++) {
for (let i = 0; i < input[ch].length; i++) {
// Array hat Länge 1, wenn der Wert im Block konstant ist
const g = gain.length > 1 ? gain[i] : gain[0];
output[ch][i] = input[ch][i] * g;
}
}
return true;
}
}
registerProcessor('simple-gain', SimpleGainProcessor);
// main.js
const ctx = new AudioContext();
await ctx.audioWorklet.addModule('gain-processor.js');
const osc = new OscillatorNode(ctx);
const gainNode = new AudioWorkletNode(ctx, 'simple-gain');
gainNode.parameters.get('gain').linearRampToValueAtTime(0, ctx.currentTime + 2);
osc.connect(gainNode).connect(ctx.destination);
osc.start();
Pegelmesser mit Nachrichten an den Haupt-Thread
// meter-processor.js
class MeterProcessor extends AudioWorkletProcessor {
process(inputs) {
const samples = inputs[0][0];
if (samples) {
let sum = 0;
for (const s of samples) sum += s * s;
this.port.postMessage(Math.sqrt(sum / samples.length));
}
return true;
}
}
registerProcessor('meter', 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');
meter.port.onmessage = ({ data }) => console.log('RMS:', data.toFixed(3));
source.connect(meter);
// Wichtig · Fallstricke
- Nur im Worklet-Kontext:
registerProcessorgibt es im Haupt-Thread nicht. Ein Aufruf dort löst einenReferenceErroraus. - Name doppelt vergeben: Ist der Name bereits registriert, wird eine
NotSupportedError-DOMExceptionausgelöst. Ein leerer Name ebenfalls. - Ungültiger Konstruktor: Ist
processorCtorkein Konstruktor oder hat seinprototypekein Objekt, wird einTypeErrorausgelöst. Dasselbe gilt, wennparameterDescriptorskein iterierbares Objekt liefert. Doppelte Parameternamen oder eindefaultValueaußerhalb vonminValue/maxValueführen zuNotSupportedErrorbzw.InvalidStateError. - Reihenfolge:
new AudioWorkletNode()darf erst aufgerufen werden, nachdem das Promise vonaddModule()erfüllt ist. Sonst schlägt der Aufruf fehl, weil der Name noch unbekannt ist. - Rückgabewert von
process(): Gibtprocess()falsezurück, darf der Browser den Knoten beenden, sobald keine aktiven Eingänge mehr anliegen. Für Generatoren solltest dutruezurückgeben. - Performance:
process()läuft im Echtzeit-Audio-Thread, jeweils für Blöcke von meist 128 Samples. Vermeide dort Speicheranlagen,console.logund aufwendige Berechnungen, sonst entstehen Aussetzer. - Sicherer Kontext: AudioWorklet ist nur über HTTPS bzw.
localhostverfügbar. Das Modul unterliegt denselben CORS- und CSP-Regeln wie andere Skripte.