Start · Sprachen · JavaScript · Referenz · CanvasCaptureMediaStreamTrack.requestFrame()

CanvasCaptureMediaStreamTrack.requestFrame()

Methode

Fordert manuell an, dass der aktuelle Inhalt des Canvas als einzelner Frame aufgenommen und an den zugehörigen <code>MediaStream</code> gesendet wird.

seit JavaScript Baseline: Chrome 51+, Firefox 41+, Safari 15+ (Edg Kategorie: webapi

Signatur

CanvasCaptureMediaStreamTrack.prototype.requestFrame()

Beschreibung

Die Methode requestFrame() gehört zur Schnittstelle CanvasCaptureMediaStreamTrack. Diesen Track erhält man über HTMLCanvasElement.captureStream(). Sie weist den Browser an, den aktuellen Inhalt des Canvas als nächsten Video-Frame in den Stream zu übernehmen.

Richtig nützlich wird die Methode, wenn der Stream mit canvas.captureStream(0) erzeugt wurde. Mit einer Bildrate von 0 nimmt der Browser keine Frames mehr von selbst auf, sondern nur noch auf ausdrücklichen Aufruf von requestFrame(). So legst du genau fest, wann ein Frame übertragen wird, etwa nur nach einer Zeichenoperation, bei Präsentationsfolien, Whiteboards oder Aufnahmen in festem Takt über MediaRecorder.

Ohne Argument (also bei captureStream()) wird bei jeder Canvas-Änderung automatisch ein Frame erzeugt. Mit fester Bildrate wird höchstens diese Rate genutzt. In beiden Fällen kann requestFrame() zusätzlich einen Frame erzwingen. Der Frame wird nicht sofort beim Aufruf aufgenommen, sondern beim nächsten Rendering-Schritt des Browsers.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined).

Beispiele

Frames manuell nach jedem Zeichnen senden

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

// Bildrate 0: keine automatische Aufnahme
const stream = canvas.captureStream(0);
const [track] = stream.getVideoTracks();

const video = document.querySelector('video');
video.srcObject = stream;

const zeichneKreis = (x, y) => {
  ctx.fillStyle = 'tomato';
  ctx.beginPath();
  ctx.arc(x, y, 20, 0, Math.PI * 2);
  ctx.fill();
  // Erst jetzt wird der neue Zustand übertragen
  track.requestFrame();
};

canvas.addEventListener('click', (e) => zeichneKreis(e.offsetX, e.offsetY));

Aufnahme mit MediaRecorder in eigenem Takt

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const stream = canvas.captureStream(0);
const [track] = stream.getVideoTracks();

const recorder = new MediaRecorder(stream, { mimeType: 'video/webm' });
const chunks = [];
recorder.ondataavailable = (e) => chunks.push(e.data);
recorder.onstop = () => {
  const blob = new Blob(chunks, { type: 'video/webm' });
  console.log('Video-Größe:', blob.size, 'Bytes');
};

recorder.start();
let frame = 0;
const timer = setInterval(() => {
  ctx.fillStyle = `hsl(${frame * 10}, 70%, 50%)`;
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  track.requestFrame(); // genau ein Frame pro Intervall
  if (++frame >= 30) {
    clearInterval(timer);
    recorder.stop();
  }
}, 100);
Video-Größe: 48213 Bytes

Funktionsprüfung vor der Nutzung

const canvas = document.createElement('canvas');
const stream = canvas.captureStream?.(0);
const track = stream?.getVideoTracks()[0];

if (track && typeof track.requestFrame === 'function') {
  track.requestFrame();
  console.log('requestFrame() wird unterstützt');
} else {
  console.log('Manuelle Frame-Anforderung nicht verfügbar');
}
requestFrame() wird unterstützt

// Wichtig · Fallstricke

  • Nur sinnvoll mit captureStream(0): Bei automatischer Aufnahme bringt ein zusätzlicher Aufruf meist nichts, weil der Browser Änderungen ohnehin erfasst.
  • Asynchron: Der Frame wird erst beim nächsten Rendering-Schritt aufgenommen. Mehrere Aufrufe innerhalb desselben Tasks ergeben in der Regel nur einen Frame.
  • Canvas mit fremden Inhalten: Ist das Canvas durch ursprungsfremde Bilder ohne CORS verunreinigt („origin-clean“ = false), wirft schon captureStream() einen SecurityError.
  • Beendete Tracks: Nach track.stop() (readyState === 'ended') hat der Aufruf keine Wirkung mehr.
  • Kompatibilität: Wird in aktuellen Chromium-Browsern, in Firefox und ab Safari 15 unterstützt. In älteren Browsern gibt es die Methode nicht, daher vorher mit einer Funktionsprüfung absichern.
  • Hintergrund-Tabs: Browser drosseln Timer wie setInterval in inaktiven Tabs. Dadurch können Aufnahmen ruckeln oder Lücken haben.