Signatur
Beschreibung
Das Ereignis dataavailable ist der zentrale Kanal, über den ein MediaRecorder seine aufgezeichneten Daten herausgibt. Der Handler erhält ein BlobEvent, dessen Eigenschaft data einen Blob mit den kodierten Mediendaten enthält (z. B. WebM/Opus oder MP4/AAC). Man registriert den Handler mit addEventListener("dataavailable", …) oder über die Eigenschaft ondataavailable.
Das Ereignis wird in folgenden Situationen ausgelöst:
- wenn
stop()aufgerufen wird – der restliche Puffer wird geliefert, danach folgt dasstop-Ereignis, - wenn der aufgezeichnete Medienstrom endet (z. B. alle Tracks beendet),
- wenn
requestData()aufgerufen wird – die bisher gesammelten Daten werden geliefert und ein neuer Blob begonnen, - periodisch alle
timesliceMillisekunden, wennstart(timeslice)mit einem Intervall aufgerufen wurde.
Ohne timeslice entsteht typischerweise nur ein einziger großer Blob am Ende der Aufnahme. Mit timeslice erhält man Teilstücke (Chunks), die man sammeln und später zu einem Blob zusammenfügen oder direkt streamen (z. B. per WebSocket oder fetch) kann. Nur der erste Chunk enthält die Container-Header – einzelne spätere Chunks sind für sich allein meist nicht abspielbar.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignisname "dataavailable". |
|
| $handler Pflicht | (event: BlobEvent) => void | Callback, das ein BlobEvent erhält. event.data ist der Blob mit den Mediendaten, event.timecode der Zeitstempel (ms) des Blob-Anfangs. |
|
| $options | boolean | AddEventListenerOptions | false | Optionale Listener-Optionen wie once oder signal. |
Rückgabewert
addEventListener gibt nichts zurück. Der Handler erhält ein BlobEvent.Beispiele
Mikrofonaufnahme mit addEventListener und Download
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const recorder = new MediaRecorder(stream);
const chunks = [];
recorder.addEventListener('dataavailable', (event) => {
if (event.data.size > 0) chunks.push(event.data);
});
recorder.addEventListener('stop', () => {
const blob = new Blob(chunks, { type: recorder.mimeType });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'aufnahme.webm';
a.click();
URL.revokeObjectURL(url);
stream.getTracks().forEach((t) => t.stop());
});
recorder.start();
setTimeout(() => recorder.stop(), 5000); // 5 Sekunden aufnehmen
Chunks alle 1000 ms per ondataavailable hochladen
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
const recorder = new MediaRecorder(stream, { mimeType: 'video/webm;codecs=vp9,opus' });
let index = 0;
recorder.ondataavailable = async ({ data, timecode }) => {
if (!data.size) return;
console.log(`Chunk ${index}: ${data.size} Bytes @ ${Math.round(timecode)} ms`);
await fetch(`/upload?chunk=${index++}`, { method: 'POST', body: data });
};
recorder.start(1000); // alle 1 s ein dataavailable-Ereignis
requestData() und Listener wieder entfernen
const stream = await navigator.mediaDevices.getDisplayMedia({ video: true });
const recorder = new MediaRecorder(stream);
const onData = (event) => {
console.log('Zwischenstand:', event.data.size, 'Bytes');
};
recorder.addEventListener('dataavailable', onData);
recorder.start();
// Nach 3 s Zwischenstand abrufen, dann Listener entfernen
setTimeout(() => {
recorder.requestData();
setTimeout(() => {
recorder.removeEventListener('dataavailable', onData);
recorder.stop();
}, 0);
}, 3000);
// Wichtig · Fallstricke
- Reihenfolge: Beim Aufruf von
stop()kommt zuerst das letztedataavailable, danachstop. Den finalen Blob daher imstop-Handler zusammensetzen, nicht direkt nachstop(). - Leere Blobs:
event.data.sizekann0sein – vor dem Speichern prüfen. - Chunks sind nicht eigenständig: Nur der erste Chunk enthält Container-Header. Für Wiedergabe alle Chunks in Reihenfolge zu einem
Blobzusammenfügen. - timeslice ist ein Richtwert: Browser können das Intervall auf einen Mindestwert anheben oder leicht abweichen.
- MIME-Typen: Unterstützte Formate unterscheiden sich (Chrome/Firefox: WebM; Safari: MP4). Mit
MediaRecorder.isTypeSupported()prüfen undrecorder.mimeTypefür den Blob verwenden. - Speicher: Lange Aufnahmen ohne Upload sammeln viele Daten im Arbeitsspeicher; Object-URLs mit
URL.revokeObjectURL()freigeben. - Kompatibilität: In allen modernen Browsern verfügbar, Safari ab 14.1.
getUserMediaerfordert einen sicheren Kontext (HTTPS) und Nutzerzustimmung.