Start · Sprachen · JavaScript · Referenz · OfflineAudioContext

OfflineAudioContext

Schnittstelle

Ein Audio-Kontext, der einen Graphen aus <code>AudioNode</code>s nicht über die Lautsprecher ausgibt, sondern möglichst schnell in einen <code>AudioBuffer</code> rendert.

seit JavaScript Baseline: alle modernen Browser (Web Audio API) Kategorie: webapi

Signatur

interface OfflineAudioContext extends BaseAudioContext

Beschreibung

OfflineAudioContext ist das Gegenstück zu AudioContext: Beide erben von BaseAudioContext und bieten dieselben Fabrikmethoden (createOscillator(), createGain(), createBiquadFilter(), decodeAudioData() …). Der Unterschied liegt in der Ausgabe: Ein OfflineAudioContext spielt nichts auf der Hardware ab, sondern berechnet das Ergebnis des Audiographen so schnell wie die CPU es zulässt und liefert es als AudioBuffer zurück.

Typische Einsatzgebiete sind:

  • Effekte, Filter oder Mischungen auf eine Audiodatei anwenden und das Ergebnis exportieren (z. B. als WAV)
  • Wellenform- oder Spektrumsdaten vorab berechnen (z. B. für Visualisierungen)
  • Audioanalyse wie Tempo- oder Pegelerkennung ohne Echtzeitwiedergabe
  • Automatisierte Tests von Audiographen mit deterministischem Ergebnis

Länge, Kanalanzahl und Abtastrate werden beim Erzeugen fest vorgegeben. Nach dem Aufbau des Graphen startet startRendering() die Berechnung und gibt ein Promise<AudioBuffer> zurück; zusätzlich wird das Ereignis complete (oncomplete) mit einem OfflineAudioCompletionEvent ausgelöst. Mit suspend(zeit) und resume() lässt sich das Rendern an bestimmten Zeitpunkten anhalten, um den Graphen zu verändern.

Wichtige Mitglieder: die schreibgeschützte Eigenschaft length (Länge in Sample-Frames), die Methoden startRendering(), suspend() und resume() sowie das Ereignis complete.

Parameter

Name Typ Default Beschreibung
$numberOfChannels Pflicht number Anzahl der Kanäle des Ergebnis-Buffers (mindestens 1 bis 32 werden unterstützt). In der Objekt-Variante optional, Standard 1.
$length Pflicht number Länge des Ergebnisses in Sample-Frames, also Sekunden * sampleRate. Muss größer als 0 sein.
$sampleRate Pflicht number Abtastrate in Hz (Browser unterstützen mindestens 8000–96000, meist 3000–768000).
$options { numberOfChannels?: number, length: number, sampleRate: number } Alternative Konstruktorform: ein einziges Objekt mit denselben Werten, z. B. new OfflineAudioContext({ length, sampleRate }).

Rückgabewert

Typ
OfflineAudioContext
Beschreibung
Ein neuer Offline-Kontext. startRendering() liefert später ein Promise<AudioBuffer> mit dem gerenderten Audio.

Beispiele

Zwei Sekunden Sinuston offline rendern

const sampleRate = 44100;
const ctx = new OfflineAudioContext(1, sampleRate * 2, sampleRate);

const osc = ctx.createOscillator();
osc.frequency.value = 440;

const gain = ctx.createGain();
// sanftes Ausblenden über die zwei Sekunden
gain.gain.setValueAtTime(1, 0);
gain.gain.linearRampToValueAtTime(0, 2);

osc.connect(gain).connect(ctx.destination);
osc.start(0);

const buffer = await ctx.startRendering();
console.log(buffer.duration, buffer.numberOfChannels, buffer.length);
2 1 88200

Audiodatei filtern und das Ergebnis abspielen

const response = await fetch('/audio/sprache.mp3');
const arrayBuffer = await response.arrayBuffer();

// Zum Dekodieren genügt ein kurzer Offline-Kontext
const decoder = new OfflineAudioContext(1, 1, 44100);
const source = await decoder.decodeAudioData(arrayBuffer);

const offline = new OfflineAudioContext({
  numberOfChannels: source.numberOfChannels,
  length: source.length,
  sampleRate: source.sampleRate,
});

const node = offline.createBufferSource();
node.buffer = source;

const lowpass = offline.createBiquadFilter();
lowpass.type = 'lowpass';
lowpass.frequency.value = 1000;

node.connect(lowpass).connect(offline.destination);
node.start();

const filtered = await offline.startRendering();

// Ergebnis in einem normalen AudioContext abspielen (nach Nutzerinteraktion)
const live = new AudioContext();
const player = live.createBufferSource();
player.buffer = filtered;
player.connect(live.destination);
player.start();

Rendern mit suspend() anhalten und Graphen ändern

const sr = 48000;
const ctx = new OfflineAudioContext(1, sr * 3, sr);

const osc = ctx.createOscillator();
osc.type = 'square';
osc.frequency.value = 220;
osc.connect(ctx.destination);
osc.start();

// Bei Sekunde 1 anhalten und die Frequenz umschalten
ctx.suspend(1).then(() => {
  osc.frequency.value = 330;
  console.log('Pausiert bei', ctx.currentTime.toFixed(2), 's');
  ctx.resume();
});

ctx.oncomplete = (event) => {
  console.log('Fertig, Länge:', event.renderedBuffer.length);
};

await ctx.startRendering();
Pausiert bei 1.00 s Fertig, Länge: 144000

// Wichtig · Fallstricke

  • Nur einmal renderbar: Ein weiterer Aufruf von startRendering() auf demselben Kontext lehnt das Promise mit einem InvalidStateError ab. Für jeden neuen Durchlauf einen neuen OfflineAudioContext erzeugen.
  • Speicherbedarf: Der Ergebnis-Buffer belegt ca. length × numberOfChannels × 4 Byte (32-Bit-Float). Zehn Minuten Stereo bei 48 kHz sind schon rund 230 MB – lange Dateien besser in Abschnitten verarbeiten.
  • Feste Länge: Alles, was nach length Frames klingt (z. B. Hall-Ausklang), wird abgeschnitten. Etwas Reserve einplanen.
  • suspend(): Die Zeit wird auf eine Render-Quantum-Grenze (128 Frames) gerundet; suspend() sollte vor startRendering() bzw. während einer Pause aufgerufen werden. Zeitpunkte außerhalb der Länge oder doppelt belegte Zeitpunkte führen zu Fehlern.
  • Keine Autoplay-Sperre: Da nichts hörbar ausgegeben wird, braucht ein Offline-Kontext keine Nutzergeste – das spätere Abspielen im AudioContext aber schon.
  • Kompatibilität: In allen aktuellen Browsern verfügbar. Sehr alte Safari-Versionen kannten nur webkitOfflineAudioContext mit Callback-basiertem oncomplete statt Promise; die Objekt-Konstruktorform ist dort ebenfalls nicht vorhanden. Nicht in Node.js enthalten (nur über Drittpakete wie node-web-audio-api). AudioWorklet wird im Offline-Kontext unterstützt, MediaElementAudioSourceNode und MediaStream-Knoten dagegen nicht sinnvoll nutzbar.