Start · Sprachen · JavaScript · Referenz · AudioContext

AudioContext

Schnittstelle

Stellt einen Audioverarbeitungsgrafen aus verknüpften <code>AudioNode</code>-Objekten bereit und steuert die Audioausgabe in Echtzeit auf dem Ausgabegerät.

seit JavaScript Baseline: alle modernen Browser (Safari ab 14.1 oh Kategorie: webapi

Signatur

interface AudioContext extends BaseAudioContext

Beschreibung

AudioContext ist der zentrale Einstiegspunkt der Web Audio API. Ein Kontext verwaltet einen Graphen aus Audioknoten, also Quellen (z. B. OscillatorNode, AudioBufferSourceNode, MediaElementAudioSourceNode), Effekten (z. B. GainNode, BiquadFilterNode) und Analyse-Knoten (AnalyserNode). Diese Knoten verbindest du mit connect() und leitest das Ergebnis am Ende auf context.destination, also auf die Lautsprecher.

Ein AudioContext eignet sich für Spiele, Synthesizer, Visualisierungen, Echtzeit-Effekte auf Mikrofonsignale und für genau getimte Wiedergabe. Alle Zeitangaben beziehen sich auf die hochauflösende Uhr currentTime. Damit lassen sich Ereignisse sampelgenau planen, was mit setTimeout nicht möglich ist.

Wichtige Mitglieder (teils von BaseAudioContext geerbt): state ("suspended", "running", "closed"), sampleRate, currentTime, destination, baseLatency, outputLatency sowie die Methoden resume(), suspend(), close(), decodeAudioData(), getOutputTimestamp(), createMediaElementSource(), createMediaStreamSource() und createMediaStreamDestination(). Zum Offline-Rendern ohne Ausgabegerät gibt es OfflineAudioContext.

In der Regel reicht ein einziger Kontext pro Seite. Er belegt Systemressourcen und sollte daher wiederverwendet und nicht mehr benötigt mit close() freigegeben werden.

Parameter

Name Typ Default Beschreibung
$options AudioContextOptions {} Optionales Konfigurationsobjekt für den Konstruktor new AudioContext(options).
$options.latencyHint "interactive" | "balanced" | "playback" | number "interactive" Gewünschte Latenz: "interactive" für möglichst geringe Latenz, "playback" für stromsparende Wiedergabe oder eine Zahl in Sekunden.
$options.sampleRate number Abtastrate des Ausgabegeräts Abtastrate in Hz (z. B. 44100 oder 48000). Ohne Angabe gilt die Rate des Geräts.
$options.sinkId string | { type: "none" } "" (Standardgerät) ID des Audio-Ausgabegeräts oder { type: "none" } für eine Verarbeitung ohne Ausgabe. Wird noch nicht von allen Browsern unterstützt.

Rückgabewert

Typ
AudioContext
Beschreibung
Ein neuer Audiokontext. Sein state ist "running" oder "suspended", falls die Autoplay-Richtlinie noch keine Nutzerinteraktion erkannt hat.

Beispiele

Kontext bei Nutzerinteraktion erzeugen und Ton abspielen

let ctx;

document.querySelector('#play').addEventListener('click', async () => {
  // Kontext erst nach einer Nutzeraktion anlegen (Autoplay-Richtlinie)
  ctx ??= new AudioContext({ latencyHint: 'interactive' });
  if (ctx.state === 'suspended') await ctx.resume();

  const osc = ctx.createOscillator();
  const gain = ctx.createGain();
  osc.type = 'sine';
  osc.frequency.value = 440; // Kammerton A

  // Kurzes Ein- und Ausblenden, damit es nicht knackt
  const now = ctx.currentTime;
  gain.gain.setValueAtTime(0, now);
  gain.gain.linearRampToValueAtTime(0.3, now + 0.02);
  gain.gain.exponentialRampToValueAtTime(0.001, now + 1);

  osc.connect(gain).connect(ctx.destination);
  osc.start(now);
  osc.stop(now + 1);

  console.log(ctx.state, ctx.sampleRate);
});
running 48000

Audiodatei laden, dekodieren und abspielen

const ctx = new AudioContext();

const loadSound = async (url) => {
  const res = await fetch(url);
  const data = await res.arrayBuffer();
  return ctx.decodeAudioData(data); // Promise<AudioBuffer>
};

const playBuffer = (buffer, when = 0) => {
  const src = ctx.createBufferSource();
  src.buffer = buffer;
  src.connect(ctx.destination);
  src.start(ctx.currentTime + when);
  return src;
};

document.querySelector('#shot').addEventListener('click', async () => {
  await ctx.resume();
  const buffer = await loadSound('/sounds/laser.mp3');
  console.log(`Dauer: ${buffer.duration.toFixed(2)} s`);
  playBuffer(buffer);
});
Dauer: 0.84 s

<audio>-Element analysieren (Pegelanzeige)

const audioEl = document.querySelector('audio');
const ctx = new AudioContext();
const source = ctx.createMediaElementSource(audioEl);
const analyser = ctx.createAnalyser();
analyser.fftSize = 256;

source.connect(analyser).connect(ctx.destination);
const data = new Uint8Array(analyser.frequencyBinCount);

const tick = () => {
  analyser.getByteFrequencyData(data);
  const avg = data.reduce((a, b) => a + b, 0) / data.length;
  document.querySelector('#meter').style.width = `${avg / 2.55}%`;
  requestAnimationFrame(tick);
};

audioEl.addEventListener('play', async () => {
  await ctx.resume();
  tick();
});

Kontext pausieren und freigeben

const ctx = new AudioContext();

ctx.addEventListener('statechange', () => {
  console.log('Status:', ctx.state);
});

const pause = () => ctx.suspend();   // Uhr hält an, spart Rechenzeit
const weiter = () => ctx.resume();
const beenden = async () => {
  await ctx.close();                 // Ressourcen endgültig freigeben
  console.log('Geschlossen:', ctx.state);
};

await weiter();
await pause();
await beenden();
Status: running Status: suspended Status: closed Geschlossen: closed

// Wichtig · Fallstricke

  • Autoplay-Richtlinie: Wird ein Kontext ohne Nutzerinteraktion erzeugt, startet er meist im Zustand "suspended". Rufe resume() in einem click- oder keydown-Handler auf, sonst bleibt es still und es erscheint keine Fehlermeldung.
  • Ressourcen: Browser begrenzen die Zahl gleichzeitiger Kontexte. Lege keinen neuen Kontext pro Ton an. Verwende einen gemeinsamen Kontext und schließe ihn mit close(). Nach close() lässt er sich nicht wiederverwenden.
  • Einmal-Quellen: AudioBufferSourceNode und OscillatorNode kann man nur einmal starten. Für jede Wiedergabe brauchst du einen neuen Knoten. Das ist günstig, weil der AudioBuffer wiederverwendet werden kann.
  • createMediaElementSource: Pro <audio>/<video>-Element ist nur ein Aufruf erlaubt. Bei Medien von fremden Ursprüngen ohne passende CORS-Header (crossorigin-Attribut) liefert die Analyse nur Stille.
  • Kompatibilität: Ältere Safari-Versionen (vor 14.1) kennen nur webkitAudioContext. Als Rückfall dient const AC = window.AudioContext || window.webkitAudioContext;. sinkId/setSinkId() ist noch nicht überall verfügbar.
  • Knacken vermeiden: Setze Lautstärke nicht sprunghaft, sondern mit setValueAtTime() und Rampen. exponentialRampToValueAtTime() darf den Zielwert 0 nicht verwenden.