Start · Sprachen · JavaScript · Referenz · MediaRecorder

MediaRecorder

Schnittstelle

Nimmt einen <code>MediaStream</code> (Kamera, Mikrofon, Bildschirm, Canvas) auf und liefert die kodierten Daten als <code>Blob</code>-Stücke.

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

Signatur

interface MediaRecorder extends EventTarget

Beschreibung

MediaRecorder ist die zentrale Schnittstelle der MediaStream Recording API. Sie nimmt einen MediaStream entgegen, etwa von navigator.mediaDevices.getUserMedia(), getDisplayMedia(), HTMLCanvasElement.captureStream() oder einem Web-Audio-MediaStreamAudioDestinationNode, und kodiert ihn im Browser in ein Containerformat wie WebM, MP4 oder Ogg.

Die Aufnahme läuft über Zustände (state: "inactive", "recording", "paused") und wird mit start(), pause(), resume() und stop() gesteuert. Die kodierten Daten kommen über das Ereignis dataavailable als Blob an. Gibt man start(timeslice) einen Wert mit, wird alle timeslice Millisekunden ein Stück geliefert. Ohne diesen Wert kommt erst beim stop() oder requestData() ein einziger Blob.

Typische Einsatzfälle sind Sprachnotizen, Video-Nachrichten, Bildschirmaufnahmen für Fehlerberichte, der Export von Canvas-Animationen und das stückweise Hochladen langer Aufnahmen auf einen Server.

Wichtige Mitglieder: Eigenschaften stream, mimeType, state, videoBitsPerSecond, audioBitsPerSecond. Methoden start(), stop(), pause(), resume(), requestData(). Statische Methode MediaRecorder.isTypeSupported(). Ereignisse dataavailable, start, stop, pause, resume, error.

Parameter

Name Typ Default Beschreibung
$stream Pflicht MediaStream Der Stream, der aufgenommen werden soll.
$options object {} Optionale Einstellungen für den Konstruktor new MediaRecorder(stream, options).
$options.mimeType string vom Browser gewählt Container und Codecs, z. B. "video/webm;codecs=vp9,opus". Vorher mit MediaRecorder.isTypeSupported() prüfen. Ein nicht unterstützter Typ löst NotSupportedError aus.
$options.audioBitsPerSecond number Ziel-Bitrate für die Audiospur in Bit pro Sekunde.
$options.videoBitsPerSecond number Ziel-Bitrate für die Videospur in Bit pro Sekunde.
$options.bitsPerSecond number Gesamt-Bitrate. Wird auf Audio und Video aufgeteilt, wenn diese nicht einzeln gesetzt sind.

Rückgabewert

Typ
MediaRecorder
Beschreibung
Eine neue Instanz im Zustand "inactive". Die Aufnahme startet erst mit start().

Beispiele

Mikrofon aufnehmen und abspielen

const aufnehmen = async (dauerMs = 3000) => {
  const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
  const recorder = new MediaRecorder(stream);
  const teile = [];

  recorder.addEventListener('dataavailable', (e) => {
    if (e.data.size > 0) teile.push(e.data);
  });

  const fertig = new Promise((resolve) => {
    recorder.addEventListener('stop', resolve, { once: true });
  });

  recorder.start();
  console.log(recorder.state);
  setTimeout(() => recorder.stop(), dauerMs);
  await fertig;

  // Mikrofon freigeben
  stream.getTracks().forEach((t) => t.stop());

  const blob = new Blob(teile, { type: recorder.mimeType });
  const audio = new Audio(URL.createObjectURL(blob));
  await audio.play();
  console.log(blob.type, blob.size > 0);
};

document.querySelector('#rec').addEventListener('click', () => aufnehmen());
recording audio/webm;codecs=opus true

Passenden MIME-Typ ermitteln

const kandidaten = [
  'video/webm;codecs=vp9,opus',
  'video/webm;codecs=vp8,opus',
  'video/mp4;codecs=avc1,mp4a',
  'video/mp4'
];

const mimeType = kandidaten.find((t) => MediaRecorder.isTypeSupported(t)) ?? '';
console.log('Verwende:', mimeType || 'Browser-Standard');

const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
const recorder = new MediaRecorder(stream, {
  mimeType,
  videoBitsPerSecond: 2_500_000,
  audioBitsPerSecond: 128_000
});
console.log(recorder.mimeType);
Verwende: video/webm;codecs=vp9,opus video/webm;codecs=vp9,opus

Bildschirmaufnahme in Stücken hochladen

const stream = await navigator.mediaDevices.getDisplayMedia({ video: true });
const recorder = new MediaRecorder(stream);
let nr = 0;

// Alle 5 Sekunden kommt ein Blob-Stück
recorder.ondataavailable = async ({ data }) => {
  if (!data.size) return;
  await fetch(`/upload?teil=${nr++}`, { method: 'POST', body: data });
};

recorder.onerror = (e) => console.error('Aufnahmefehler:', e.error);

// Endet, wenn der Nutzer die Freigabe beendet
stream.getVideoTracks()[0].addEventListener('ended', () => {
  if (recorder.state !== 'inactive') recorder.stop();
});

recorder.start(5000);

Canvas-Animation als Video exportieren

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const recorder = new MediaRecorder(canvas.captureStream(30));
const teile = [];
recorder.ondataavailable = (e) => teile.push(e.data);
recorder.onstop = () => {
  const url = URL.createObjectURL(new Blob(teile, { type: recorder.mimeType }));
  const a = Object.assign(document.createElement('a'), { href: url, download: 'animation.webm' });
  a.click();
  URL.revokeObjectURL(url);
};

let x = 0;
const zeichne = () => {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillRect(x++ % canvas.width, 50, 40, 40);
  if (recorder.state === 'recording') requestAnimationFrame(zeichne);
};

recorder.start();
zeichne();
setTimeout(() => recorder.stop(), 4000);