Signatur
Beschreibung
CanvasCaptureMediaStreamTrack gehört zur Media Capture and Streams API und erweitert MediaStreamTrack. Man erstellt die Schnittstelle nicht selbst über einen Konstruktor. Sie entsteht automatisch, wenn man canvas.captureStream() aufruft. Der zurückgegebene MediaStream enthält genau eine Videospur dieses Typs. Sie liefert fortlaufend das, was auf das Canvas gezeichnet wird.
Typische Einsatzzwecke:
- Canvas-Animationen, Spiele oder Visualisierungen mit
MediaRecorderals Video aufnehmen - Bearbeitete Kamerabilder (Filter, Overlays, Wasserzeichen) über WebRTC mit
RTCPeerConnection.addTrack()versenden - Canvas-Inhalte in einem
<video>-Element als Vorschau wiedergeben
Zusätzlich zu allen Mitgliedern von MediaStreamTrack (z. B. stop(), enabled, readyState) bietet die Schnittstelle Folgendes:
canvas(schreibgeschützt): dasHTMLCanvasElement, aus dem die Spur ihre Bilder beziehtrequestFrame(): erfasst manuell ein einzelnes Bild. Das ist vor allem sinnvoll, wenncaptureStream(0)aufgerufen wurde und deshalb keine Bilder automatisch erfasst werden.
Welche Bildrate die Spur hat, legt das optionale Argument frameRate von captureStream() fest. Ohne Argument wird jedes Mal ein neues Bild erfasst, wenn sich das Canvas ändert. Mit einer Zahl ist das die Obergrenze an Bildern pro Sekunde. Mit 0 wird nur beim Aufruf von requestFrame() erfasst.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $frameRate | number | (nicht gesetzt = Bild bei jeder Änderung) | Argument von HTMLCanvasElement.captureStream(frameRate), mit dem die Spur entsteht. Legt die höchste Bildrate fest. 0 schaltet die automatische Erfassung ab, dann kommen Bilder nur über requestFrame(). |
Rückgabewert
canvas.captureStream().getVideoTracks()[0]. Sie stellt die Eigenschaft canvas und die Methode requestFrame() bereit (Rückgabewert void).Beispiele
Spur erzeugen und Eigenschaften prüfen
const canvas = document.querySelector('canvas');
const stream = canvas.captureStream(30); // höchstens 30 fps
const [track] = stream.getVideoTracks();
console.log(track.constructor.name);
console.log(track.kind);
console.log(track.canvas === canvas);
Canvas-Animation mit MediaRecorder als WebM aufnehmen
const canvas = document.querySelector('#scene');
const ctx = canvas.getContext('2d');
const stream = canvas.captureStream(60);
const recorder = new MediaRecorder(stream, { mimeType: 'video/webm' });
const chunks = [];
recorder.addEventListener('dataavailable', (e) => chunks.push(e.data));
recorder.addEventListener('stop', () => {
const blob = new Blob(chunks, { type: 'video/webm' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'animation.webm';
a.click();
});
let x = 0;
const draw = () => {
ctx.fillStyle = '#111';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'tomato';
ctx.fillRect(x, 50, 40, 40);
x = (x + 3) % canvas.width;
requestAnimationFrame(draw);
};
draw();
recorder.start();
setTimeout(() => {
recorder.stop();
stream.getTracks().forEach((t) => t.stop());
}, 5000);
Bilder manuell mit requestFrame() erfassen
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const stream = canvas.captureStream(0); // keine automatische Erfassung
const [track] = stream.getVideoTracks();
document.querySelector('video').srcObject = stream;
const renderSlide = (text) => {
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'black';
ctx.font = '32px sans-serif';
ctx.fillText(text, 20, 60);
// Nur jetzt ein Bild in die Spur schicken
if (typeof track.requestFrame === 'function') {
track.requestFrame();
} else if (typeof stream.requestFrame === 'function') {
stream.requestFrame(); // Firefox-Variante
}
};
renderSlide('Folie 1');
Bearbeitetes Canvas-Video per WebRTC senden
const pc = new RTCPeerConnection();
const canvas = document.querySelector('#overlay');
const stream = canvas.captureStream(25);
for (const track of stream.getVideoTracks()) {
pc.addTrack(track, stream);
}
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
console.log(pc.getSenders()[0].track.canvas.id);
// Wichtig · Fallstricke
- Browser-Kompatibilität: Chromium-Browser und Safari haben die Schnittstelle
CanvasCaptureMediaStreamTrackmitcanvasundrequestFrame(). Firefox kenntcaptureStream()zwar, legtcanvasundrequestFrame()aber auf den Stream (CanvasCaptureMediaStream) statt auf die Spur. Deshalb vorher mit einer Funktionsprüfung testen (siehe Beispiel 3). - Sicherheit / CORS: Ist das Canvas „tainted“, weil Bilder oder Videos von einer anderen Herkunft ohne CORS-Freigabe gezeichnet wurden, löst
captureStream()einenSecurityErroraus. Wird das Canvas erst nach dem Aufruf tainted, liefert die Spur keine brauchbaren Inhalte mehr. Fremde Ressourcen deshalb mitcrossOrigin = 'anonymous'und passenden CORS-Headern laden. - Ohne Zeichenvorgänge entstehen keine neuen Bilder. Ein statisches Canvas ergibt ein „eingefrorenes“ Video. Manche Empfänger (z. B. WebRTC) zeigen dann schwarz oder brechen ab.
- In Hintergrund-Tabs drosselt der Browser
requestAnimationFrame. Die Aufnahme ruckelt dann oder bleibt stehen. - Ein
<canvas>mit Breite oder Höhe 0 erzeugt keine gültigen Bilder. FürOffscreenCanvasgibt es keincaptureStream(). - Nach der Nutzung
track.stop()aufrufen, damit Ressourcen freigegeben werden.