Back

Audio im Browser aufnehmen mit der Web Audio API

Audio im Browser aufnehmen mit der Web Audio API

Die meisten Entwickler gehen davon aus, dass die Web Audio API für Aufnahmen zuständig ist. Das ist sie nicht – zumindest nicht direkt. Die Web Audio API ist eine Verarbeitungs- und Routing-Engine. Die eigentliche Aufnahme übernimmt die MediaRecorder API. Diese Unterscheidung zu verstehen ist der schnellste Weg, um nicht die falsche Lösung zu bauen.

Dieser Artikel zeigt die aktuell empfohlene Architektur für Audioaufnahmen im Browser: die Erfassung von Mikrofoneingaben mit getUserMedia(), das optionale Routing des Audios durch einen Web-Audio-Graph und die Kodierung mit MediaRecorder.

Wichtigste Erkenntnisse

  • Die Web Audio API verarbeitet und routet Audio, aber die tatsächliche Aufnahme in eine Datei übernimmt der MediaRecorder.
  • Eine vollständige Aufnahme-Pipeline besteht aus drei Stufen: Erfassung mit getUserMedia(), optionale Verarbeitung mit Web-Audio-Nodes und Kodierung mit MediaRecorder.
  • getUserMedia() benötigt einen sicheren Kontext (HTTPS oder localhost) sowie die explizite Mikrofonberechtigung des Nutzers.
  • Verwenden Sie AudioWorklet für eigene DSP-Aufgaben; ScriptProcessorNode ist veraltet und verursacht unter Last Aussetzer.
  • Prüfen Sie vor der Aufnahme stets den MIME-Type-Support mit MediaRecorder.isTypeSupported(), da Safari und Chrome unterschiedliche Formate unterstützen.

Wie Audioaufnahmen im Browser tatsächlich funktionieren

Die moderne Aufnahme-Pipeline besteht aus drei klar voneinander abgegrenzten Stufen:

  1. ErfassunggetUserMedia() fordert den Mikrofonzugriff an und liefert einen MediaStream.
  2. Verarbeitung (optional) — Die Web Audio API analysiert oder transformiert den Stream über Audio-Nodes.
  3. AufnahmeMediaRecorder kodiert den Stream in eine Datei.

Für eine einfache Aufnahme benötigen Sie die Web Audio API nicht. Wenn Sie jedoch Rauschunterdrückung, Verstärkungsregelung, Visualisierung oder eigene Effekte über AudioWorklet einsetzen möchten, fügt sie sich nahtlos in die Mitte dieser Kette ein.

Ein subtiles, aber wichtiges Detail: MediaRecorder nimmt einen MediaStream direkt auf. Wenn Sie die verarbeitete Ausgabe eines Web-Audio-Graphen aufnehmen möchten, müssen Sie den Graph mittels audioContext.createMediaStreamDestination() zurück in einen Stream routen und dessen .stream-Eigenschaft an den MediaRecorder übergeben.

Schritt 1: Mikrofonzugriff mit getUserMedia anfordern

getUserMedia() benötigt einen sicheren Kontext (HTTPS oder localhost) sowie die explizite Erlaubnis des Nutzers, bevor der Browser den Mikrofonzugriff freigibt.

try {
  const stream = await navigator.mediaDevices.getUserMedia({
    audio: {
      echoCancellation: true,
      noiseSuppression: true,
      sampleRate: 44100
    }
  });
} catch (err) {
  console.error('Microphone access failed:', err.name, err.message);
}

Umschließen Sie diesen Aufruf stets mit try/catch. Nutzer können die Berechtigung verweigern, und manche Umgebungen (etwa HTTP-Seiten) lehnen den Aufruf direkt mit einem NotAllowedError oder SecurityError ab. Beachten Sie, dass Constraints wie sampleRate lediglich Hinweise sind – Browser können sie je nach zugrunde liegender Hardware ignorieren.

Schritt 2: Routing über die Web Audio API (optional)

Wenn Sie Audio vor der Aufnahme analysieren oder verarbeiten möchten, erstellen Sie einen AudioContext und leiten den Stream hindurch:

const audioContext = new AudioContext();
const source = audioContext.createMediaStreamSource(stream);

// Example: connect to an AnalyserNode for visualization
const analyser = audioContext.createAnalyser();
source.connect(analyser);

// To record the processed output, route to a MediaStreamDestination
const destination = audioContext.createMediaStreamDestination();
analyser.connect(destination);
// destination.stream is what you pass to MediaRecorder

Für eigene Verarbeitungsschritte – etwa ein Noise Gate oder einen Echtzeit-Pegelmesser – verwenden Sie AudioWorklet anstelle des veralteten ScriptProcessorNode. AudioWorklet läuft außerhalb des Main Threads, blockiert also weder Ihre UI noch verwirft es unter Last Audio-Samples.

Hinweis: Unter iOS Safari startet der AudioContext in einem suspendierten Zustand, bis er durch eine direkte Nutzerinteraktion ausgelöst wird. Erstellen Sie ihn (oder rufen Sie audioContext.resume() auf) innerhalb eines Button-Click-Handlers, nicht beim Seitenladen.

Schritt 3: Aufnehmen und Exportieren mit MediaRecorder

MediaRecorder nimmt einen MediaStream entgegen und kodiert ihn. Codieren Sie den MIME-Type nicht fest – prüfen Sie zuerst die Unterstützung:

function pickMimeType() {
  const candidates = [
    'audio/webm;codecs=opus',
    'audio/ogg;codecs=opus',
    'audio/mp4'
  ];
  return candidates.find(type => MediaRecorder.isTypeSupported(type)) || '';
}

const mimeType = pickMimeType();
const recorder = new MediaRecorder(stream, mimeType ? { mimeType } : undefined);
const chunks = [];

recorder.ondataavailable = (e) => {
  if (e.data.size > 0) chunks.push(e.data);
};

recorder.onstop = () => {
  const blob = new Blob(chunks, {
    type: recorder.mimeType || mimeType || chunks[0]?.type || 'audio/webm'
  });

  const url = URL.createObjectURL(blob);
  document.querySelector('audio').src = url;
};

recorder.start();

WebM/Opus ist in der Regel die beste Standardwahl für moderne Browser – geringe Dateigröße bei exzellenter Qualität. Safari bevorzugt häufig audio/mp4. Eine Liste von Kandidaten durchzugehen und dem Browser den ersten unterstützten Typ wählen zu lassen, ist die zuverlässigste Strategie. Den aktuellen Browser-Support für MediaRecorder und zugehörige Formate können Sie auf Can I Use überprüfen.

MediaRecorder vs. Web Audio API: Schnellreferenz

AnforderungLösung
Einfache MikrofonaufnahmegetUserMedia + MediaRecorder
Echtzeit-Effekte oder -FilterWeb Audio API Nodes
Eigene DSP-VerarbeitungAudioWorklet
Audio-VisualisierungAnalyserNode
Kodierung in eine DateiMediaRecorder

Was Sie vermeiden sollten

  • ScriptProcessorNode — veraltet, läuft auf dem Main Thread, verursacht unter Last Audio-Aussetzer.
  • Fest codierte MIME-Types — scheitern stillschweigend in Safari und älteren Firefox-Versionen.
  • AudioContext beim Seitenladen erstellen — Browser suspendieren ihn bis zu einer Nutzergeste; resumen Sie ihn daher in einem Event-Handler.
  • Den Stream nicht zu stoppen — rufen Sie nach Abschluss stream.getTracks().forEach(t => t.stop()) auf, sonst bleibt die Mikrofonanzeige aktiv.

Fazit

Audioaufnahmen im Browser sind eine Aufgabe für zwei APIs: getUserMedia() und MediaRecorder übernehmen Erfassung und Kodierung, während die Web Audio API alles dazwischen abdeckt. Beginnen Sie mit der einfachsten Pipeline, die Ihre Anforderungen erfüllt, ergänzen Sie Web-Audio-Verarbeitung nur bei Bedarf und prüfen Sie immer die MIME-Type-Unterstützung, bevor Sie den MediaRecorder konfigurieren. Das ist die gesamte Architektur in einem Satz.

FAQs

Nein. Für eine einfache Aufnahme reichen getUserMedia() und MediaRecorder aus. Die Web Audio API wird erst dann notwendig, wenn Sie das Audio vor der Aufnahme verarbeiten, analysieren oder transformieren müssen – etwa für Filter, Visualisierungen oder eigene DSP-Logik über ein AudioWorklet.

Safari und Chrome unterstützen unterschiedliche Aufnahmeformate. Safari bevorzugt häufig audio/mp4, während Chrome meist WebM/Opus verwendet. Wenn Sie einen nicht unterstützten MIME-Type fest codieren, kann der MediaRecorder einen Fehler werfen oder unbrauchbare Ausgaben erzeugen. Verwenden Sie immer MediaRecorder.isTypeSupported(), um zur Laufzeit ein kompatibles Format zu ermitteln.

Erstellen Sie mit audioContext.createMediaStreamDestination() einen MediaStreamAudioDestinationNode, verbinden Sie den letzten Node Ihres Audio-Graphen damit und übergeben Sie dessen .stream-Eigenschaft an den MediaRecorder. So erfassen Sie das nachverarbeitete Audio statt des rohen Mikrofonstreams aus getUserMedia().

iOS Safari verlangt, dass AudioContext innerhalb einer direkten Nutzergeste – etwa einem Click- oder Touch-Event – erstellt oder fortgesetzt wird. Wenn Sie ihn beim Seitenladen instanziieren, bleibt er suspendiert. Verlagern Sie die AudioContext-Erstellung in einen Button-Handler oder rufen Sie dort audioContext.resume() auf, um Wiedergabe und Verarbeitung freizuschalten.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay