Signatur
Beschreibung
captureStream() macht aus einem <video>- oder <audio>-Element eine Live-Quelle. Die Methode gibt ein MediaStream-Objekt zurück, dessen Spuren (MediaStreamTrack) genau das enthalten, was das Element gerade wiedergibt. Wie die Medien ins Element gelangt sind, spielt keine Rolle: Das kann eine Datei-URL sein, ein MediaSource-Puffer oder ein anderer MediaStream über srcObject.
Typische Einsatzfälle:
- Aufnehmen einer laufenden Wiedergabe mit
MediaRecorder, z. B. um einen Ausschnitt als WebM zu speichern. - Weitergeben eines Videos an eine WebRTC-Verbindung (
RTCPeerConnection.addTrack()), etwa um gemeinsam einen Film zu schauen oder eine Datei in ein Gespräch einzuspielen. - Weiterverarbeiten des Tons über die Web Audio API (
AudioContext.createMediaStreamSource()) oder des Bildes über ein weiteres<video>- oder Canvas-Element.
Der Stream ist an den Zustand des Elements gekoppelt. Pausiert das Element, kommen keine neuen Bilder und kein Ton mehr an. Wechselt die Quelle (src) oder ändern sich die verfügbaren Spuren, werden Spuren im Stream hinzugefügt oder entfernt. Diese Änderungen lassen sich mit den Ereignissen addtrack und removetrack am MediaStream verfolgen. Direkt nach dem Aufruf kann der Stream noch leer sein, wenn die Metadaten des Mediums noch nicht geladen sind.
Rückgabewert
MediaStream mit je einer Video- und/oder Audiospur, passend zu den Spuren, die das Element gerade abspielt. Bei mehreren Aufrufen entstehen jeweils neue, voneinander unabhängige Streams.Beispiele
Wiedergabe mit MediaRecorder aufnehmen
const video = document.querySelector('#player');
const recordClip = async (durationMs = 5000) => {
await video.play();
const stream = video.captureStream();
const recorder = new MediaRecorder(stream, { mimeType: 'video/webm' });
const chunks = [];
recorder.addEventListener('dataavailable', (e) => chunks.push(e.data));
const stopped = new Promise((resolve) =>
recorder.addEventListener('stop', resolve, { once: true })
);
recorder.start();
setTimeout(() => recorder.stop(), durationMs);
await stopped;
const blob = new Blob(chunks, { type: 'video/webm' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'ausschnitt.webm';
a.click();
console.log(`Aufnahme fertig: ${blob.size} Bytes`);
};
document.querySelector('#rec').addEventListener('click', () => recordClip());
Unterstützung prüfen, Firefox-Präfix als Ersatz
const getElementStream = (media) => {
if (typeof media.captureStream === 'function') {
return media.captureStream();
}
if (typeof media.mozCaptureStream === 'function') {
// Firefox: Präfix-Variante
return media.mozCaptureStream();
}
throw new Error('captureStream() wird in diesem Browser nicht unterstützt');
};
const video = document.querySelector('video');
video.addEventListener('loadedmetadata', () => {
const stream = getElementStream(video);
console.log(stream.getTracks().map((t) => t.kind));
}, { once: true });
Lokales Video an eine WebRTC-Verbindung senden
const video = document.querySelector('#film');
const pc = new RTCPeerConnection();
const shareVideo = async () => {
await video.play();
const stream = video.captureStream();
// Spuren, die schon da sind
stream.getTracks().forEach((track) => pc.addTrack(track, stream));
// Spuren, die später dazukommen (z. B. nach einem Quellwechsel)
stream.addEventListener('addtrack', ({ track }) => {
console.log('Neue Spur:', track.kind);
pc.addTrack(track, stream);
});
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// offer anschließend über den Signalisierungskanal verschicken
};
shareVideo();
Ton an die Web Audio API übergeben
const audio = document.querySelector('audio');
const ctx = new AudioContext();
audio.addEventListener('play', async () => {
await ctx.resume();
const source = ctx.createMediaStreamSource(audio.captureStream());
const analyser = ctx.createAnalyser();
source.connect(analyser);
const data = new Uint8Array(analyser.frequencyBinCount);
setInterval(() => {
analyser.getByteFrequencyData(data);
console.log('Pegel:', Math.max(...data));
}, 1000);
}, { once: true });
// Wichtig · Fallstricke
- Browser-Unterstützung: Chromium-Browser unterstützen die Methode ohne Präfix. Firefox bietet sie lange nur als
mozCaptureStream()(dazumozCaptureStreamUntilEnded()) an. Dort wird der Ton je nach Version in den Stream umgeleitet und nicht mehr über die Lautsprecher ausgegeben. Safari unterstütztcaptureStream()an Medienelementen nicht;HTMLCanvasElement.captureStream()funktioniert dort dagegen. Ob die Methode verfügbar ist, deshalb immer vorher prüfen. - Medien von fremden Ursprüngen (Cross-Origin): Stammt die Quelle von einem anderen Ursprung und ist sie nicht per CORS freigegeben (
crossorigin-Attribut plus passenderAccess-Control-Allow-Origin-Header), wirft Chrome einenNotSupportedError. Andere Browser liefern stumme oder schwarze Spuren. So wird verhindert, dass fremde Inhalte unbemerkt abgegriffen werden. - DRM-Inhalte (Encrypted Media Extensions) lassen sich nicht aufnehmen. Der Aufruf schlägt fehl oder liefert leere Spuren.
- Timing: Vor
loadedmetadatahat der Stream oft noch keine Spuren. Aufaddtrackreagieren oder erst nach dem Laden der Metadaten aufrufen. - Pausieren: Pausiert das Element, liefert der Stream keine neuen Bilder mehr. Ein laufender
MediaRecordernimmt dann ein stehendes Bild oder Stille auf. - Speicher und Ressourcen: Nicht mehr benötigte Spuren mit
track.stop()beenden. Erzeugte Objekt-URLs mitURL.revokeObjectURL()wieder freigeben.