Start · Sprachen · JavaScript · Referenz · OfflineAudioContext: complete

OfflineAudioContext: complete

Ereignis

Wird ausgelöst, wenn ein <code>OfflineAudioContext</code> das Rendern beendet hat. Das Ereignis liefert den fertigen <code>AudioBuffer</code> in <code>event.renderedBuffer</code>.

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

Signatur

offlineAudioContext.addEventListener("complete", handler)

Beschreibung

Das Ereignis complete wird auf einem OfflineAudioContext ausgelöst, sobald das Rendern nach startRendering() fertig ist. Das Ereignisobjekt ist ein OfflineAudioCompletionEvent. Seine Eigenschaft renderedBuffer enthält das Ergebnis als AudioBuffer.

Einen Listener meldest du mit addEventListener("complete", handler) an oder alternativ über die Eigenschaft oncomplete. Das Ereignis wird nicht weitergereicht (kein Bubbling) und lässt sich nicht abbrechen.

In modernem Code nutzt man meist das Promise, das startRendering() zurückgibt. Es wird mit demselben AudioBuffer erfüllt. Das Ereignis ist trotzdem nützlich, wenn mehrere unabhängige Programmteile auf das Ende des Renderns reagieren sollen. Es hilft auch bei älterem Code, der noch mit Rückruffunktionen arbeitet.

Typische Einsatzfälle sind das Exportieren von Audio (z. B. als WAV), das Anwenden von Effekten schneller als in Echtzeit, Wellenform-Vorschauen und die Analyse von Audiodateien ohne Wiedergabe.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname "complete".
$handler Pflicht (event: OfflineAudioCompletionEvent) => void Rückruffunktion. Sie erhält ein OfflineAudioCompletionEvent, dessen Eigenschaft renderedBuffer den fertigen AudioBuffer enthält.
$options boolean | AddEventListenerOptions false Optionale Listener-Optionen, z. B. { once: true } oder { signal }.

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück. Das fertige Audio steht im Handler unter event.renderedBuffer (AudioBuffer).

Beispiele

Rendern abschließen mit addEventListener

// 2 Sekunden Stereo bei 44,1 kHz offline rendern
const ctx = new OfflineAudioContext(2, 44100 * 2, 44100);

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

ctx.addEventListener("complete", (event) => {
  const buffer = event.renderedBuffer;
  console.log(`Fertig: ${buffer.duration} s, ${buffer.numberOfChannels} Kanäle`);
}, { once: true });

ctx.startRendering();
Fertig: 2 s, 2 Kanäle

Variante mit der Eigenschaft oncomplete

const ctx = new OfflineAudioContext(1, 48000, 48000);
const osc = ctx.createOscillator();
osc.connect(ctx.destination);
osc.start();

ctx.oncomplete = ({ renderedBuffer }) => {
  const samples = renderedBuffer.getChannelData(0);
  const peak = samples.reduce((max, s) => Math.max(max, Math.abs(s)), 0);
  console.log("Spitzenpegel:", peak.toFixed(2));
  ctx.oncomplete = null; // Handler wieder entfernen
};

ctx.startRendering();
Spitzenpegel: 1.00

Datei mit Effekt offline bearbeiten und abspielen (Promise + Ereignis)

const processFile = async (url) => {
  const res = await fetch(url);
  const data = await res.arrayBuffer();

  // Zum Dekodieren genügt ein kleiner temporärer Kontext
  const tmp = new OfflineAudioContext(2, 1, 44100);
  const source = await tmp.decodeAudioData(data);

  const ctx = new OfflineAudioContext(
    source.numberOfChannels, source.length, source.sampleRate
  );
  const node = ctx.createBufferSource();
  node.buffer = source;
  const gain = ctx.createGain();
  gain.gain.value = 0.5; // Lautstärke halbieren
  node.connect(gain).connect(ctx.destination);
  node.start();

  // Ereignis z. B. für eine Fortschrittsanzeige
  const onDone = () => console.log("Rendern beendet");
  ctx.addEventListener("complete", onDone);

  const rendered = await ctx.startRendering(); // gleicher Buffer wie event.renderedBuffer
  ctx.removeEventListener("complete", onDone);

  const live = new AudioContext();
  const player = live.createBufferSource();
  player.buffer = rendered;
  player.connect(live.destination);
  player.start();
};

processFile("/audio/sample.mp3");
Rendern beendet

// Wichtig · Fallstricke

  • Ereignis oder Promise: startRendering() gibt ein Promise zurück, das mit demselben AudioBuffer erfüllt wird. Für neuen Code ist await meist übersichtlicher. Nutzt du beides, verarbeite das Ergebnis nicht versehentlich doppelt.
  • Nur einmal pro Kontext: Ein OfflineAudioContext rendert nur einmal. Ein zweiter Aufruf von startRendering() weist das Promise mit einem InvalidStateError zurück. Danach kommt kein weiteres complete. Für einen neuen Durchlauf brauchst du einen neuen Kontext.
  • Listener vorher anmelden: Melde den Handler an, bevor du startRendering() aufrufst. Sonst kann das Ereignis bei sehr kurzen Puffern verpasst werden.
  • Speicher: Die Länge (length) wird beim Erzeugen fest vorgegeben. Lange Puffer mit vielen Kanälen belegen viel Arbeitsspeicher (32-Bit-Float pro Sample und Kanal).
  • Kompatibilität: Das Ereignis und oncomplete funktionieren in allen modernen Browsern. Sehr alte Safari-Versionen brauchten webkitOfflineAudioContext und kannten die Promise-Variante nicht. Dort war oncomplete der einzige Weg.
  • Kein Bubbling, nicht abbrechbar: preventDefault() hat keine Wirkung.