Signatur
Beschreibung
Das stop-Ereignis signalisiert, dass eine Aufnahme mit MediaRecorder endgültig beendet ist. Es tritt ein, wenn MediaRecorder.prototype.stop() aufgerufen wird, wenn alle Spuren des aufgenommenen MediaStream enden (z. B. weil der Nutzer die Bildschirmfreigabe beendet oder die Kamera getrennt wird) oder wenn bei der Aufnahme ein Fehler auftritt.
Wichtig ist die Reihenfolge: Beim Stoppen feuert der Recorder zuerst ein letztes dataavailable-Ereignis mit den restlichen gepufferten Daten und erst danach stop. Deshalb ist der stop-Handler die richtige Stelle, um die gesammelten Blob-Stücke zu einer Datei zusammenzufügen, eine Vorschau anzuzeigen, einen Upload zu starten oder die Oberfläche zurückzusetzen.
Registrieren lässt sich der Handler per addEventListener("stop", handler) oder über die Eigenschaft onstop. Das übergebene Objekt ist ein einfaches Event ohne zusätzliche Eigenschaften; es ist nicht abbrechbar und steigt nicht auf (kein Bubbling). Zum Zeitpunkt des Ereignisses hat recorder.state bereits den Wert "inactive".
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $type Pflicht | string | Der Ereignistyp, hier immer "stop". |
|
| $handler Pflicht | (event: Event) => void | Rückruffunktion, die beim Ende der Aufnahme aufgerufen wird. Erhält ein einfaches Event-Objekt; event.target ist der MediaRecorder. |
|
| $options | boolean | AddEventListenerOptions | false | Optionen wie { once: true } oder { signal } zum späteren Entfernen über einen AbortController. |
Rückgabewert
addEventListener gibt nichts zurück. Der Rückgabewert des Handlers wird ignoriert.Beispiele
Mikrofon aufnehmen und bei stop als Datei bereitstellen
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const recorder = new MediaRecorder(stream);
const chunks = [];
recorder.addEventListener("dataavailable", (e) => {
if (e.data.size > 0) chunks.push(e.data);
});
recorder.addEventListener("stop", () => {
// Letztes dataavailable ist bereits eingetroffen
const blob = new Blob(chunks, { type: recorder.mimeType });
const audio = document.querySelector("audio");
audio.src = URL.createObjectURL(blob);
console.log("Aufnahme fertig:", blob.size, "Bytes, Status:", recorder.state);
// Mikrofon freigeben
stream.getTracks().forEach((t) => t.stop());
});
recorder.start();
setTimeout(() => recorder.stop(), 5000); // nach 5 Sekunden stoppen
onstop-Eigenschaft: Bildschirmaufnahme, die vom Nutzer beendet wird
const stream = await navigator.mediaDevices.getDisplayMedia({ video: true });
const recorder = new MediaRecorder(stream, { mimeType: "video/webm" });
const chunks = [];
recorder.ondataavailable = (e) => chunks.push(e.data);
// Feuert auch, wenn der Nutzer im Browser "Freigabe beenden" klickt
recorder.onstop = () => {
const blob = new Blob(chunks, { type: "video/webm" });
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = "bildschirm.webm";
link.click();
console.log("Download gestartet");
};
recorder.start(1000); // alle 1000 ms ein Datenstück
Aufnahme als Promise kapseln und Listener wieder entfernen
const recordFor = (stream, ms) => new Promise((resolve, reject) => {
const recorder = new MediaRecorder(stream);
const chunks = [];
const onData = (e) => chunks.push(e.data);
const onStop = () => {
recorder.removeEventListener("dataavailable", onData);
recorder.removeEventListener("stop", onStop);
resolve(new Blob(chunks, { type: recorder.mimeType }));
};
recorder.addEventListener("dataavailable", onData);
recorder.addEventListener("stop", onStop);
recorder.addEventListener("error", (e) => reject(e.error ?? e), { once: true });
recorder.start();
setTimeout(() => recorder.state !== "inactive" && recorder.stop(), ms);
});
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const blob = await recordFor(stream, 3000);
console.log(blob.type, blob.size);
// Wichtig · Fallstricke
- Reihenfolge beachten: Den
Blobnicht direkt nachrecorder.stop()bauen – der Aufruf ist asynchron, das letztedataavailablekommt erst später. Immer imstop-Handler zusammensetzen. stop()auf einem Recorder im Zustand"inactive"wirft je nach Browser einenInvalidStateErrorbzw. tut nichts; vorherrecorder.stateprüfen.- Das Ereignis feuert auch, wenn der Stream von außen endet (Gerät getrennt, Bildschirmfreigabe beendet) – Aufräumlogik also nicht nur an den eigenen Stopp-Button koppeln.
- Bei einem Fehler feuert zuerst
error, danach ebenfallsstop. Imstop-Handler ggf. prüfen, ob die Aufnahme vollständig ist. - Speicher freigeben: mit
URL.createObjectURL()erzeugte URLs später perURL.revokeObjectURL()wieder freigeben und Stream-Spuren mittrack.stop()beenden, sonst bleibt die Kamera- bzw. Mikrofonanzeige aktiv. - Kompatibilität: In allen modernen Browsern verfügbar, in Safari erst ab 14.1. Unterstützte Formate unterscheiden sich (Safari: meist
video/mp4, Chrome/Firefox:webm) – mitMediaRecorder.isTypeSupported()prüfen.getUserMediafunktioniert nur in sicheren Kontexten (HTTPS).