Signatur
Beschreibung
Die Methode clone() des VideoFrame-Interfaces aus der WebCodecs API gibt ein neues VideoFrame zurück, das auf dieselbe zugrunde liegende Medienressource zeigt. Die Pixeldaten werden dabei nicht kopiert. Intern wird nur ein Referenzzähler erhöht, deshalb ist der Aufruf sehr günstig.
Gebraucht wird clone(), wenn mehrere unabhängige Verbraucher dasselbe Bild nutzen sollen. Beispiele: Ein Frame wird gleichzeitig an einen VideoEncoder übergeben und auf einem Canvas angezeigt, oder er wird an einen Worker geschickt, während der Haupt-Thread weiter damit arbeitet. Jeder Klon hat einen eigenen Lebenszyklus und muss eigenständig mit close() freigegeben werden. Die Ressource selbst wird erst freigegeben, wenn alle Referenzen geschlossen sind.
Wurde das Original-Frame bereits mit close() geschlossen, wirft clone() eine InvalidStateError-DOMException. Der Klon übernimmt alle Metadaten wie timestamp, duration, codedWidth, displayWidth, format und colorSpace.
Rückgabewert
VideoFrame-Objekt, das auf dieselbe Medienressource wie das Original verweist. Es muss separat mit close() freigegeben werden.Beispiele
Frame klonen und beide Referenzen schließen
const canvas = new OffscreenCanvas(320, 240);
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'teal';
ctx.fillRect(0, 0, 320, 240);
const frame = new VideoFrame(canvas, { timestamp: 0 });
const copy = frame.clone();
console.log(copy.timestamp, copy.displayWidth, copy.displayHeight);
// Beide Referenzen müssen einzeln freigegeben werden
frame.close();
console.log(copy.displayWidth); // Klon ist weiterhin gültig
copy.close();
Ein Frame gleichzeitig anzeigen und kodieren
const encoder = new VideoEncoder({
output: (chunk) => console.log('Chunk:', chunk.byteLength, 'Bytes'),
error: (e) => console.error(e)
});
encoder.configure({ codec: 'vp8', width: 640, height: 480 });
const display = document.querySelector('canvas').getContext('2d');
const handleFrame = (frame) => {
// Klon an den Encoder: encode() übernimmt nicht das Schließen
const forEncoder = frame.clone();
encoder.encode(forEncoder);
forEncoder.close();
// Original für die Anzeige verwenden und danach freigeben
display.drawImage(frame, 0, 0);
frame.close();
};
Frame an einen Worker übertragen und lokal behalten
const worker = new Worker('analyse-worker.js');
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const [track] = stream.getVideoTracks();
const reader = new MediaStreamTrackProcessor({ track }).readable.getReader();
const { value: frame } = await reader.read();
// Klon wird übertragen (transfer), Original bleibt im Haupt-Thread
const forWorker = frame.clone();
worker.postMessage({ frame: forWorker }, [forWorker]);
console.log('Lokal:', frame.codedWidth, 'x', frame.codedHeight);
frame.close();
Fehler beim Klonen eines geschlossenen Frames
const frame = new VideoFrame(new OffscreenCanvas(10, 10), { timestamp: 0 });
frame.close();
try {
frame.clone();
} catch (err) {
console.log(err.name);
}
// Wichtig · Fallstricke
- Speicherlecks: Jeder Klon hält die Medienressource fest, oft GPU- oder Decoder-Puffer. Klone, die nie geschlossen werden, können den Decoder blockieren, sodass keine neuen Frames mehr kommen. Rufen Sie immer
close()auf und verlassen Sie sich nicht auf die Garbage Collection. - Keine tiefe Kopie:
clone()kopiert keine Pixeldaten. Für eine echte Kopie der Rohdaten verwenden SiecopyTo()oder erzeugen mitnew VideoFrame(frame, init)ein Frame mit geänderten Metadaten. - Geschlossene Frames: Der Aufruf auf einem bereits geschlossenen Frame wirft eine
InvalidStateError-DOMException. - Transfer vs. Klon: Wird ein Frame per
postMessageübertragen, wird das Original im Sender getrennt (detached). Wenn der Sender das Frame weiter braucht, übertragen Sie vorher einen Klon. - Kompatibilität: Die WebCodecs API gibt es nur in sicheren Kontexten (HTTPS). In Chromium-Browsern ist sie vollständig verfügbar, in Firefox ab Version 130, in Safari teilweise. Prüfen Sie die Unterstützung vorher mit
'VideoFrame' in globalThis.