JavaScript Web Audio API
Die JavaScript Web Audio API erklärt: Audiograph mit AudioContext und AudioNodes aufbauen, Sounds laden und abspielen, Lautstärke steuern, Töne erzeugen und die Autoplay-Richtlinie des Browsers beachten.
Die Web Audio API ermöglicht es Ihnen, Sound direkt im Browser zu erzeugen, zu laden, zu verarbeiten und abzuspielen – ganz ohne Plugins. Dieser Leitfaden führt Sie durch die wichtigsten Grundbausteine: Wie Sie einen Audio-Kontext erstellen, Sounddateien laden und abspielen, die Lautstärke steuern, Töne mit einem Oszillator erzeugen und die Autoplay-Richtlinie des Browsers umgehen. Jedes Beispiel ist klein und in sich geschlossen, sodass Sie es direkt in eine Seite einfügen und das Ergebnis hören können.
Einführung in die Web Audio API
Die Web Audio API ist eine JavaScript API zur Verarbeitung und Synthese von Audio in Webanwendungen. Anders als ein einfaches <audio>-Element – das eine Datei von Anfang bis Ende abspielt – bietet die Web Audio API einen Graphen aus verbundenen Knoten, die Sound in Echtzeit leiten, mischen und transformieren. Das macht sie zum richtigen Werkzeug für Spiele, Musik-Apps, Synthesizer und Audio-Visualisierer.
Denken in Audiographen
Jeder Sound in der Web Audio API fließt durch eine Kette von Knoten, von einer Quelle zu einem Ziel:
source → (effects) → destination
(file, (gain, (your
oscillator) filter) speakers)Die drei Konzepte, auf die Sie zuerst treffen werden:
- AudioContext — der Container, der den gesamten Graphen und die Audiouhr besitzt. Sie erstellen einen pro Seite und verwenden ihn wieder.
- AudioNode — eine modulare Verarbeitungseinheit. Quellknoten erzeugen Sound (ein Buffer oder ein Oszillator), Effektknoten transformieren ihn (Gain, Filter, Panner), und der Zielknoten sendet ihn an die Lautsprecher.
- AudioBuffer — dekodierte, im Speicher abgelegte Audiodaten, ideal für kurze Sounds (Effekte, Samples), die Sie wiederholt mit präzisem Timing auslösen.
Sie bauen einen Graphen, indem Sie node.connect(otherNode) aufrufen. Audio endet immer bei audioContext.destination.
Erste Schritte mit der Web Audio API
Um mit Audio zu arbeiten, erstellen Sie zunächst einen AudioContext, der als Container für Ihren Audiographen dient.
Einen AudioContext erstellen
const audioContext = new (window.AudioContext || window.webkitAudioContext)();Dies initialisiert einen neuen AudioContext. Der webkit-Fallback deckt ältere Safari-Versionen ab; moderne Browser unterstützen den AudioContext direkt ohne Präfix.
Autoplay-Richtlinie beachten. Browser erstellen den Kontext im Zustand
"suspended"und verweigern die Audiowiedergabe, bis der Nutzer mit der Seite interagiert (ein Klick oder Tastendruck). Setzen Sie die Wiedergabe immer innerhalb eines Event-Handlers fort, bevor Sie abspielen:button.addEventListener("click", async () => { if (audioContext.state === "suspended") { await audioContext.resume(); } // ...jetzt ist es sicher abzuspielen });Wenn Audio stumm bleibt und keine Fehler in der Konsole erscheinen, ist ein nicht fortgesetzter Kontext die häufigste Ursache.
Audio laden und abspielen
Um eine Sounddatei abzuspielen, laden Sie sie in einen AudioBuffer und verbinden dann einen Quellknoten mit dem Kontext für die Wiedergabe.
Audiodateien laden
Hierbei wird die Fetch API und async/await verwendet, um die Datei herunterzuladen und zu dekodieren:
async function loadAudioFile(url, audioContext) {
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
return audioBuffer;
}Die Funktion ruft die Datei ab, liest sie als rohen ArrayBuffer und übergibt diesen an decodeAudioData, das Formate wie MP3, WAV oder OGG in einen wiedergabebereiten AudioBuffer dekomprimiert. Die Dekodierung erfolgt außerhalb des Haupt-Threads und gibt ein Promise zurück, daher await verwenden.
Die geladene Audio abspielen
function playAudio(audioBuffer, audioContext) {
const sourceNode = audioContext.createBufferSource();
sourceNode.buffer = audioBuffer;
sourceNode.connect(audioContext.destination);
sourceNode.start();
}Dies erstellt einen BufferSourceNode, verweist ihn auf den dekodierten Buffer, verbindet ihn mit den Lautsprechern (audioContext.destination) und startet die Wiedergabe.
Ein Quellknoten ist Einmalverwendung. Ein
AudioBufferSourceNodekann nur einmal gestartet werden – nachdem er gestoppt wurde, müssen Sie einen neuen erstellen, um denselben Buffer erneut abzuspielen. DerAudioBufferselbst ist wiederverwendbar, behalten Sie also den Buffer und erstellen Sie jedes Mal einen neuen, günstigen Quellknoten:// ❌ Throws after the first play: "cannot call start more than once" // sourceNode.start(); // sourceNode.start(); // ✅ One fresh source node per playback function playOnce(buffer, ctx) { const src = ctx.createBufferSource(); src.buffer = buffer; src.connect(ctx.destination); src.start(); }
Audio manipulieren
Die Web Audio API glänzt, wenn Sie Effektknoten zwischen Quelle und Ziel einfügen. Der häufigste ist der Gain-Knoten zur Lautstärkeregelung.
Einen Gain-Knoten erstellen
function createGainNode(audioContext, volume) {
const gainNode = audioContext.createGain();
gainNode.gain.value = volume; // 1 = full volume, 0 = silent, 0.5 = half
return gainNode;
}Ein GainNode multipliziert das Signal mit seinem gain-Wert. Die gain-Eigenschaft ist ein AudioParam, was bedeutet, dass Sie auch sanfte Änderungen über Zeit planen können (für Überblendungen), anstatt einen Wert abrupt zu setzen:
// Fade from silent to full volume over 2 seconds, avoiding clicks/pops
gainNode.gain.setValueAtTime(0, audioContext.currentTime);
gainNode.gain.linearRampToValueAtTime(1, audioContext.currentTime + 2);Knoten für Audioeffekte verbinden
function applyEffects(audioBuffer, volume, audioContext) {
const sourceNode = audioContext.createBufferSource();
sourceNode.buffer = audioBuffer;
const gainNode = createGainNode(audioContext, volume);
// source → gain → destination
sourceNode.connect(gainNode);
gainNode.connect(audioContext.destination);
sourceNode.start();
}Dies baut einen Drei-Knoten-Graphen: Die Quelle speist den Gain-Knoten, und der Gain-Knoten speist das Ziel. Fügen Sie auf dieselbe Weise weitere Effektknoten ein – zum Beispiel einen BiquadFilterNode zur Klangregelung:
const filter = audioContext.createBiquadFilter();
filter.type = "lowpass"; // let low frequencies through, cut highs
filter.frequency.value = 800; // cutoff in Hz
sourceNode.connect(filter);
filter.connect(gainNode);
gainNode.connect(audioContext.destination);Die Reihenfolge ist entscheidend: Das Signal fließt in Richtung Ihrer connect-Aufrufe.
Ein lauffähiges Beispiel: ein Tongenerator
Für eine eigenständige Demo, die keine Audiodatei benötigt, ist hier ein Tongenerator, der aus einem Oszillator aufgebaut ist. Er behandelt auch die Autoplay-Richtlinie, indem er den Kontext beim ersten Klick fortsetzt.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Simple Tone Generator</title>
</head>
<body>
<h1>Simple Tone Generator</h1>
<button onclick="playTone()">Play Tone</button>
<button onclick="stopTone()">Stop Tone</button>
<script>
let audioContext;
let oscillator;
async function playTone() {
if (!audioContext) {
audioContext = new (window.AudioContext ||
window.webkitAudioContext)();
}
// Satisfy the autoplay policy: resume on user gesture
if (audioContext.state === "suspended") {
await audioContext.resume();
}
if (!oscillator) {
oscillator = audioContext.createOscillator();
oscillator.type = "sine"; // Sine wave — other values are 'square', 'sawtooth', 'triangle'
oscillator.frequency.setValueAtTime(440, audioContext.currentTime); // A4 note, 440 Hz
oscillator.connect(audioContext.destination);
oscillator.start();
}
}
function stopTone() {
if (oscillator) {
oscillator.stop();
oscillator.disconnect();
oscillator = null; // Reset the oscillator to allow a new one to be created next time
}
}
</script>
</body>
</html>So funktioniert es:
- Oszillatorknoten — erzeugt eine reine Sinuswelle bei 440 Hz (der A4-Ton, der zum Stimmen verwendet wird). Andere
type-Werte sind"square","sawtooth"und"triangle", jeder mit einem anderen Klangcharakter. - Steuerfunktionen —
playTonesetzt den Kontext fort und startet den Oszillator;stopTonestoppt ihn, trennt die Verbindung und setzt die Variable zurück, damit beim nächsten Mal ein neuer Oszillator erstellt werden kann. - Warum
oscillator = nullzurücksetzen? Wie ein Buffer-Quellknoten ist ein Oszillator Einmalverwendung – einmal gestoppt kann er nicht neu gestartet werden, daher bauen Sie einen neuen für den nächsten Ton.
Wann die Web Audio API verwenden
| Anwendungsfall | Greifen Sie zu… |
|---|---|
| Einen einzelnen Hintergrund-Track oder Podcast abspielen | Einem einfachen <audio>-Element – einfacher, weniger Code |
| Soundeffekte in einem Spiel mit präzisem Timing | Web Audio API + AudioBuffer |
| Lautstärkeregelung, Überblendungen, Filter, Panning | Web Audio API Gain-/Filter-/Panner-Knoten |
| Synthesizer und erzeugte Töne | Web Audio API OscillatorNode |
| Echtzeit-Wellenform-/Frequenzvisualisierer | Web Audio API AnalyserNode |
Wenn Sie nur Start/Stop-Wiedergabe benötigen, reicht das <audio>-Element aus. Wählen Sie die Web Audio API, sobald Sie Verarbeitung, Timing oder Synthese benötigen.
Fazit
Die Web Audio API verwandelt den Browser in eine programmierbare Mischkonsole: Sie verdrahten einen Graphen aus Knoten von einer Quelle über Effekte zu den Lautsprechern und steuern jeden Schritt in Echtzeit. Behalten Sie diese Erkenntnisse im Hinterkopf:
- Erstellen Sie einen
AudioContextund setzen Sie ihn bei einer Nutzergeste fort, bevor Sie abspielen. - Verwenden Sie
AudioBuffers wieder, erstellen Sie aber für jede Wiedergabe einen neuen Quell-/Oszillatorknoten. - Bauen Sie Effekte, indem Sie Knoten mit
connect()verketten und immer beiaudioContext.destinationenden.
Erkunden Sie von hier aus verwandte Browser-Funktionen wie die Web MIDI API zum Verbinden von Musikinstrumenten oder die Web Animations API, um Visualisierungen mit Ihrem Audio zu synchronisieren.