Signatur
Beschreibung
ScriptProcessorNode ist ein AudioNode der Web Audio API, über den Audiodaten direkt mit JavaScript verarbeitet werden. Der Knoten hat einen Eingangs- und einen Ausgangspuffer. Sobald ein Block von bufferSize Samples bereitliegt, wird ein AudioProcessingEvent (audioprocess) ausgelöst. Im Handler liest man aus event.inputBuffer und schreibt in event.outputBuffer.
Man erzeugt ihn nicht per Konstruktor, sondern mit der Fabrikmethode BaseAudioContext.createScriptProcessor(bufferSize, numberOfInputChannels, numberOfOutputChannels). Die unten beschriebenen Parameter gehören zu dieser Methode. Der wichtigste Wert auf dem Knoten selbst ist die schreibgeschützte Eigenschaft bufferSize. Außerdem gibt es den Event-Handler onaudioprocess.
Typische Einsatzgebiete sind eigene Effekte (etwa Verstärkung, Verzerrung oder Bitcrusher), Pegelmessung, das Aufnehmen roher PCM-Daten oder synthetisch erzeugte Signale wie Rauschen. Die Verarbeitung läuft allerdings im Haupt-Thread. Wenn die Oberfläche stark ausgelastet ist, kommt es deshalb zu Aussetzern und zusätzlicher Latenz.
Der Knoten ist in der Spezifikation als veraltet markiert und wird durch AudioWorkletNode ersetzt, der in einem eigenen Audio-Thread läuft. Für neuen Code sollte man AudioWorklet verwenden. ScriptProcessorNode ist vor allem für sehr alte Browser oder bestehenden Code gedacht.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $bufferSize | number | 0 | Parameter von createScriptProcessor(): Anzahl der Sample-Frames pro audioprocess-Aufruf. Erlaubt sind 256, 512, 1024, 2048, 4096, 8192 und 16384. Bei 0 wählt der Browser einen passenden Wert. Kleine Werte ergeben weniger Latenz, aber ein höheres Risiko für Aussetzer. |
| $numberOfInputChannels | number | 2 | Anzahl der Eingangskanäle (maximal 32). numberOfInputChannels und numberOfOutputChannels dürfen nicht beide 0 sein. |
| $numberOfOutputChannels | number | 2 | Anzahl der Ausgangskanäle (maximal 32). |
Rückgabewert
createScriptProcessor() gibt einen neuen ScriptProcessorNode zurück. Er hat die schreibgeschützte Eigenschaft bufferSize (number) und den Handler onaudioprocess.Beispiele
Knoten erzeugen und Lautstärke halbieren
const ctx = new AudioContext();
const osc = ctx.createOscillator();
const processor = ctx.createScriptProcessor(4096, 1, 1);
processor.onaudioprocess = (event) => {
const input = event.inputBuffer.getChannelData(0);
const output = event.outputBuffer.getChannelData(0);
for (let i = 0; i < input.length; i++) {
output[i] = input[i] * 0.5; // Verstärkung 0.5
}
};
osc.connect(processor);
processor.connect(ctx.destination);
osc.start();
console.log(processor.bufferSize);
Weißes Rauschen erzeugen (nur Ausgang)
const ctx = new AudioContext();
// Keine Eingänge, zwei Ausgangskanäle
const noise = ctx.createScriptProcessor(2048, 0, 2);
noise.addEventListener('audioprocess', ({ outputBuffer }) => {
for (let ch = 0; ch < outputBuffer.numberOfChannels; ch++) {
const data = outputBuffer.getChannelData(ch);
for (let i = 0; i < data.length; i++) {
data[i] = Math.random() * 2 - 1;
}
}
});
noise.connect(ctx.destination);
// Stoppen: noise.disconnect();
Mikrofonpegel (RMS) messen
const startMeter = async () => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const ctx = new AudioContext();
const source = ctx.createMediaStreamSource(stream);
const meter = ctx.createScriptProcessor(1024, 1, 1);
meter.onaudioprocess = (e) => {
const samples = e.inputBuffer.getChannelData(0);
let sum = 0;
for (const s of samples) sum += s * s;
const rms = Math.sqrt(sum / samples.length);
console.log(`Pegel: ${(20 * Math.log10(rms || 1e-8)).toFixed(1)} dBFS`);
};
source.connect(meter);
// Viele Browser feuern das Event nur, wenn der Knoten mit dem Ziel verbunden ist
meter.connect(ctx.destination);
};
startMeter();
// Wichtig · Fallstricke
- Veraltet: Für neue Projekte
AudioWorkletNodeverwenden. Eine Entfernung ist derzeit nicht angekündigt, aber auch nicht auszuschließen. - Haupt-Thread: Aufwendige Berechnungen, DOM-Arbeit oder die Garbage Collection können zu Knacksern und Aussetzern führen. Im Handler möglichst keine Objekte anlegen.
- Das
audioprocess-Event wird in manchen Browsern (z. B. Chrome) nur ausgelöst, wenn der Knoten mit einem Ausgang verbunden ist, etwa mitctx.destination. Das gilt auch dann, wenn er nur Daten analysiert. - Der Ausgangspuffer muss vollständig beschrieben werden. Andernfalls sind die Samples zwar meist Stille, in manchen Browsern aber undefiniert.
- Ein ungültiger
bufferSizelöst einenIndexSizeErroraus. Sind beide Kanalzahlen0, gibt es einenNotSupportedError. - Durch die Pufferung entsteht immer eine zusätzliche Latenz von mindestens einem Block (bei 4096 Samples und 48 kHz etwa 85 ms).
- Einen
new ScriptProcessorNode()-Konstruktor gibt es nicht. Der Knoten wird nur übercreateScriptProcessor()erzeugt. - Mikrofonzugriff per
getUserMediafunktioniert nur in einem sicheren Kontext (HTTPS). Außerdem muss derAudioContextwegen der Autoplay-Regeln oft erst nach einer Nutzeraktion gestartet werden (ctx.resume()).