Signatur
Beschreibung
Die Methode createAnalyser() eines AudioContext oder OfflineAudioContext erzeugt einen AnalyserNode. Dieser Knoten reicht das Audiosignal unverändert weiter und stellt gleichzeitig per schneller Fourier-Transformation (FFT) berechnete Frequenzdaten sowie die rohe Wellenform (Zeitbereich) bereit.
Typische Einsatzzwecke sind Spektrum-Anzeigen, Oszilloskop-Darstellungen, Pegelmesser (VU-Meter), Sprachaktivitätserkennung oder einfache Tonhöhenerkennung. Den Knoten hängt man zwischen eine Quelle (z. B. MediaElementAudioSourceNode oder MediaStreamAudioSourceNode) und das Ziel. Ein Anschluss an destination ist nicht zwingend nötig, wenn nur analysiert werden soll.
Die Daten liest man üblicherweise in einer requestAnimationFrame-Schleife mit getByteFrequencyData(), getFloatFrequencyData(), getByteTimeDomainData() oder getFloatTimeDomainData() aus. Über fftSize, smoothingTimeConstant, minDecibels und maxDecibels steuert man Auflösung und Glättung.
Alternativ lässt sich der Knoten direkt mit dem Konstruktor new AnalyserNode(context, options) erzeugen. Damit können die Optionen gleich beim Erzeugen gesetzt werden.
Rückgabewert
AnalyserNode mit Standardwerten: fftSize = 2048, frequencyBinCount = 1024, smoothingTimeConstant = 0.8, minDecibels = -100, maxDecibels = -30.Beispiele
Analyser erzeugen und konfigurieren
const ctx = new AudioContext();
const analyser = ctx.createAnalyser();
analyser.fftSize = 512; // Zweierpotenz von 32 bis 32768
analyser.smoothingTimeConstant = 0.6; // 0 = keine Glättung, 1 = maximal
console.log(analyser.frequencyBinCount); // halbe fftSize
console.log(analyser.minDecibels, analyser.maxDecibels);
Frequenzspektrum eines <audio>-Elements auf Canvas zeichnen
const audio = document.querySelector('audio');
const canvas = document.querySelector('canvas');
const g = canvas.getContext('2d');
const ctx = new AudioContext();
const source = ctx.createMediaElementSource(audio);
const analyser = ctx.createAnalyser();
analyser.fftSize = 256;
// Quelle -> Analyser -> Lautsprecher
source.connect(analyser).connect(ctx.destination);
const data = new Uint8Array(analyser.frequencyBinCount);
const draw = () => {
requestAnimationFrame(draw);
analyser.getByteFrequencyData(data);
g.clearRect(0, 0, canvas.width, canvas.height);
const barWidth = canvas.width / data.length;
data.forEach((value, i) => {
const h = (value / 255) * canvas.height;
g.fillStyle = `hsl(${i * 2}, 80%, 50%)`;
g.fillRect(i * barWidth, canvas.height - h, barWidth - 1, h);
});
};
// AudioContext erst nach Nutzerinteraktion starten
audio.addEventListener('play', async () => {
await ctx.resume();
draw();
}, { once: true });
Mikrofon-Pegel (RMS) messen
const startLevelMeter = async () => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const ctx = new AudioContext();
const mic = ctx.createMediaStreamSource(stream);
const analyser = ctx.createAnalyser();
analyser.fftSize = 2048;
mic.connect(analyser); // nicht an destination -> keine Rückkopplung
const buffer = new Float32Array(analyser.fftSize);
const tick = () => {
analyser.getFloatTimeDomainData(buffer);
const rms = Math.sqrt(buffer.reduce((sum, s) => sum + s * s, 0) / buffer.length);
const db = 20 * Math.log10(rms || 1e-8);
console.log(`Pegel: ${db.toFixed(1)} dBFS`);
setTimeout(tick, 500);
};
tick();
};
document.querySelector('#start').addEventListener('click', startLevelMeter);
// Wichtig · Fallstricke
- Autoplay-Richtlinie: Ein
AudioContextstartet in vielen Browsern im Zustand"suspended". Rufen Siectx.resume()erst nach einer Nutzerinteraktion auf, sonst liefert der Analyser nur Nullen bzw. Stille. fftSizemuss eine Zweierpotenz zwischen 32 und 32768 sein, sonst wird einIndexSizeErrorgeworfen. Die Länge des Arrays für Frequenzdaten entsprichtfrequencyBinCount(halbefftSize), für Zeitdaten dagegenfftSize.- CORS: Bei
createMediaElementSource()mit Audiodateien von fremden Domains liefert der Analyser ohne passende CORS-Header (undcrossorigin="anonymous"am Element) nur Nullwerte. - Ein
MediaElementSourceNodekann pro<audio>-Element nur einmal erzeugt werden. Ein zweiter Aufruf wirft einenInvalidStateError. - Den Mikrofon-Eingang nicht an
destinationanschließen, sonst entsteht eine Rückkopplung. - Leistung: Legen Sie die typisierten Arrays einmal an und verwenden Sie sie wieder, statt sie in jedem Frame neu zu erzeugen. Große
fftSize-Werte kosten Rechenzeit und verringern die zeitliche Auflösung. - Der Knoten wird von allen modernen Browsern unterstützt. Ältere Safari-Versionen benötigten
webkitAudioContext.