Signatur
Beschreibung
Das Ereignis audioprocess ist das Herzstück eines ScriptProcessorNode: Jedes Mal, wenn die Web Audio API einen Block von Samples (Größe = bufferSize, z. B. 4096) gesammelt hat, ruft sie den Handler mit einem AudioProcessingEvent auf. Darin stehen inputBuffer (eingehende Daten), outputBuffer (zu füllende Ausgabe) und playbackTime (Zeitpunkt, zu dem die Ausgabe im AudioContext hörbar wird).
Registriert wird der Handler entweder mit addEventListener("audioprocess", handler) oder über die Eigenschaft onaudioprocess. Typische Einsätze waren eigene Effekte (Verstärkung, Verzerrung), Pegelmessung (VU-Meter), Aufnahme von Mikrofondaten oder das Erzeugen synthetischer Klänge in JavaScript.
Wichtig: Der Handler läuft auf dem Haupt-Thread. Blockierendes JavaScript, Layout-Arbeit oder Garbage Collection können daher zu Aussetzern (Knacksern) führen. Die gesamte Schnittstelle ist veraltet und wurde durch AudioWorkletNode mit einem AudioWorkletProcessor ersetzt, der in einem eigenen Audio-Thread läuft. Für neuen Code sollte ausschließlich AudioWorklet verwendet werden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "audioprocess". |
|
| $handler Pflicht | (event: AudioProcessingEvent) => void | Callback, das ein AudioProcessingEvent mit inputBuffer, outputBuffer (beide AudioBuffer) und playbackTime (number, Sekunden) erhält. |
|
| $options | boolean|AddEventListenerOptions | false | Übliche Optionen von addEventListener, z. B. { once: true } oder { signal }. |
Rückgabewert
event.outputBuffer geschrieben.Beispiele
Weißes Rauschen per addEventListener erzeugen
const ctx = new AudioContext();
// 4096 Samples Puffer, 0 Eingänge, 1 Ausgangskanal
const processor = ctx.createScriptProcessor(4096, 0, 1);
const onProcess = (event) => {
const output = event.outputBuffer.getChannelData(0);
for (let i = 0; i < output.length; i++) {
output[i] = (Math.random() * 2 - 1) * 0.1; // leises Rauschen
}
};
processor.addEventListener("audioprocess", onProcess);
processor.connect(ctx.destination);
// Nach 2 Sekunden stoppen: Listener entfernen und Knoten trennen
setTimeout(() => {
processor.removeEventListener("audioprocess", onProcess);
processor.disconnect();
}, 2000);
Lautstärke halbieren über onaudioprocess
const ctx = new AudioContext();
const osc = ctx.createOscillator();
const processor = ctx.createScriptProcessor(2048, 1, 1);
processor.onaudioprocess = ({ inputBuffer, outputBuffer }) => {
for (let ch = 0; ch < outputBuffer.numberOfChannels; ch++) {
const input = inputBuffer.getChannelData(ch);
const output = outputBuffer.getChannelData(ch);
for (let i = 0; i < input.length; i++) {
output[i] = input[i] * 0.5;
}
}
};
osc.connect(processor);
processor.connect(ctx.destination);
osc.start();
osc.stop(ctx.currentTime + 1);
// Handler wieder abmelden
osc.addEventListener("ended", () => {
processor.onaudioprocess = null;
processor.disconnect();
});
Mikrofon-Pegel (RMS) messen
const startMeter = async () => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const ctx = new AudioContext();
const source = ctx.createMediaStreamSource(stream);
const processor = ctx.createScriptProcessor(4096, 1, 1);
processor.addEventListener("audioprocess", (event) => {
const data = event.inputBuffer.getChannelData(0);
let sum = 0;
for (const sample of data) sum += sample * sample;
const rms = Math.sqrt(sum / data.length);
console.log(`Pegel: ${rms.toFixed(3)} @ ${event.playbackTime.toFixed(2)} s`);
});
source.connect(processor);
// Verbindung zum Ziel nötig, sonst feuert das Ereignis in manchen Browsern nicht
processor.connect(ctx.destination);
};
startMeter();
// Wichtig · Fallstricke
- Veraltet:
ScriptProcessorNodeundaudioprocesssind aus der Spezifikation als deprecated markiert. Browser unterstützen sie noch, eine Entfernung ist aber möglich. VerwendeAudioWorkletNode(in allen modernen Browsern verfügbar, nur in sicheren Kontexten/HTTPS). - Haupt-Thread: Der Handler konkurriert mit DOM- und UI-Arbeit. Größere
bufferSize-Werte (4096, 8192, 16384) verringern Aussetzer, erhöhen aber die Latenz. - Ausgang verbinden: In Chromium feuert das Ereignis nur zuverlässig, wenn der Knoten mit
ctx.destination(direkt oder indirekt) verbunden ist – auch wenn nur analysiert werden soll. Dann den Ausgabepuffer mit Nullen belassen. - Puffer nicht speichern:
inputBuffer/outputBufferkönnen wiederverwendet werden. Wer Daten aufzeichnet, muss sie kopieren (z. B.new Float32Array(data)). - Wird
outputBuffernicht beschrieben, entsteht Stille. Keine Allokationen im Handler, um GC-Pausen zu vermeiden. - Ein angehaltener
AudioContext(Autoplay-Richtlinie) löst keine Ereignisse aus – ggf.ctx.resume()nach Nutzerinteraktion aufrufen.