Signatur
Beschreibung
Der Konstruktor OfflineAudioContext() gehört zur Web Audio API und legt einen Audio-Kontext an, der nicht in Echtzeit abgespielt wird. Stattdessen rechnet er den kompletten Audio-Graphen (Quellen, Filter, Effekte, Gain-Knoten usw.) unabhängig von der Echtzeit in einen AudioBuffer mit festgelegter Länge, Kanalzahl und Abtastrate. Oft geht das deutlich schneller als in Echtzeit.
Typische Anwendungsfälle sind das Exportieren bearbeiteter Audiodaten (z. B. als WAV), das Vorberechnen von Effekten, das Resampling in eine andere Abtastrate, das Erzeugen von Wellenform-Vorschauen und die Audio-Analyse, z. B. BPM-Erkennung mit Filtern.
Du kannst den Konstruktor auf zwei Arten aufrufen: mit einem Options-Objekt { numberOfChannels, length, sampleRate } (moderne Form) oder mit drei einzelnen Argumenten (ältere Form, weiterhin unterstützt). Die length wird in Sample-Frames angegeben, nicht in Sekunden. Für 3 Sekunden bei 44,1 kHz brauchst du also 3 * 44100.
Wenn der Graph aufgebaut ist, startest du das Rendern mit startRendering(). Die Methode gibt ein Promise<AudioBuffer> zurück. Zusätzlich wird das Event complete ausgelöst.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $options Pflicht | Object | Options-Objekt (moderne Form) mit den Feldern numberOfChannels, length und sampleRate. |
|
| $options.numberOfChannels | number | 1 | Anzahl der Ausgabekanäle, zum Beispiel 2 für Stereo. Alle Browser unterstützen mindestens 32 Kanäle. |
| $options.length Pflicht | number | Länge des Ergebnis-Buffers in Sample-Frames, berechnet als Dauer in Sekunden × sampleRate. Muss größer als 0 sein. |
|
| $options.sampleRate Pflicht | number | Abtastrate in Hz. Garantiert ist mindestens der Bereich 8000–96000 (Chrome: 3000–768000). | |
| $numberOfChannels, length, sampleRate | number, number, number | Ältere Form mit drei einzelnen Argumenten statt eines Options-Objekts. Hier sind alle drei Pflicht. |
Rückgabewert
OfflineAudioContext, dessen destination in einen AudioBuffer mit den angegebenen Eigenschaften rendert.Beispiele
Einen Sinuston offline rendern
const sampleRate = 44100;
const ctx = new OfflineAudioContext({
numberOfChannels: 2,
length: sampleRate * 2, // 2 Sekunden
sampleRate
});
const osc = new OscillatorNode(ctx, { frequency: 440 });
const gain = new GainNode(ctx, { gain: 0.5 });
osc.connect(gain).connect(ctx.destination);
osc.start();
const buffer = await ctx.startRendering();
console.log(buffer.duration, buffer.numberOfChannels, buffer.sampleRate);
Audiodatei laden, filtern und als Buffer zurückgeben
const renderFiltered = async (url) => {
const data = await (await fetch(url)).arrayBuffer();
// Zum Dekodieren reicht ein kleiner Hilfskontext
const tmp = new OfflineAudioContext(1, 1, 44100);
const source = await tmp.decodeAudioData(data);
const ctx = new OfflineAudioContext(
source.numberOfChannels,
source.length,
source.sampleRate
);
const node = new AudioBufferSourceNode(ctx, { buffer: source });
const lowpass = new BiquadFilterNode(ctx, { type: 'lowpass', frequency: 800 });
node.connect(lowpass).connect(ctx.destination);
node.start();
return ctx.startRendering();
};
const result = await renderFiltered('/audio/loop.mp3');
console.log(`Gerendert: ${result.duration.toFixed(2)} s`);
Resampling auf 16 kHz Mono (z. B. für Spracherkennung)
const resample = async (buffer, targetRate = 16000) => {
const length = Math.ceil(buffer.duration * targetRate);
const ctx = new OfflineAudioContext({ numberOfChannels: 1, length, sampleRate: targetRate });
const src = new AudioBufferSourceNode(ctx, { buffer });
src.connect(ctx.destination); // Kanäle werden automatisch auf Mono heruntergemischt
src.start();
return ctx.startRendering();
};
const audioCtx = new AudioContext();
const input = audioCtx.createBuffer(2, 48000, 48000); // 1 s Stille in Stereo
const out = await resample(input);
console.log(out.sampleRate, out.length);
// Wichtig · Fallstricke
- Länge in Samples:
lengthist die Anzahl der Sample-Frames, keine Zeit in Sekunden. Ist der Wert zu klein, wird das Audio abgeschnitten. Bei0oder ungültigen Werten wirft der Konstruktor einenNotSupportedError. - Nur einmal rendern:
startRendering()darf pro Kontext nur einmal aufgerufen werden. Ein zweiter Aufruf führt zu einemInvalidStateError. Für einen neuen Durchlauf brauchst du einen neuen Kontext. - Speicherbedarf: Der ganze Ergebnis-Buffer liegt im Arbeitsspeicher (32-Bit-Float pro Sample und Kanal). Eine Stunde Stereo bei 48 kHz belegt etwa 1,4 GB.
- Kein Autoplay-Problem: Anders als ein
AudioContextbraucht einOfflineAudioContextkeine Nutzerinteraktion, weil er nichts abspielt. - Kompatibilität: Das Options-Objekt wird erst von neueren Browsern unterstützt (Safari ab 14.1). Ältere Safari-Versionen kennen nur
webkitOfflineAudioContextmit drei Argumenten. Für breite Kompatibilität ist die Form mit drei Argumenten die sicherste Wahl. suspend(time)undresume()erlauben es, den Graphen während des Renderns an bestimmten Zeitpunkten zu ändern.