Signatur
Beschreibung
Die Methode metadata() der WebCodecs-Schnittstelle VideoFrame gibt ein einfaches Objekt (Dictionary vom Typ VideoFrameMetadata) mit Zusatzinformationen zum Frame zurück. Welche Felder es gibt, legt nicht die WebCodecs-Spezifikation selbst fest, sondern die separate VideoFrame Metadata Registry des W3C. Deshalb kann das Objekt je nach Quelle des Frames und je nach Browser leer sein oder unterschiedliche Felder enthalten.
In der Praxis sind die Metadaten vor allem bei Frames aus WebRTC- oder Kamera-Quellen interessant, z. B. beim Lesen von Frames über MediaStreamTrackProcessor oder HTMLVideoElement.requestVideoFrameCallback(). Typische Felder, die Browser hier bereitstellen, sind captureTime, receiveTime und rtpTimestamp. Damit lässt sich etwa die Ende-zu-Ende-Latenz messen oder Frames einem RTP-Paket zuordnen.
Jeder Aufruf liefert eine Kopie der Metadaten. Wenn du das zurückgegebene Objekt änderst, bleibt der Frame davon unberührt. Beim Klonen mit clone() oder beim Erzeugen eines neuen VideoFrame aus einem bestehenden Frame werden die Metadaten übernommen.
Rückgabewert
{}), wenn die Quelle keine Metadaten liefert. Mögliche Felder laut Registry bzw. Browser sind z. B. rtpTimestamp, captureTime und receiveTime.Beispiele
Metadaten eines Kamera-Frames auslesen (MediaStreamTrackProcessor)
// Nur in Chromium-Browsern: MediaStreamTrackProcessor
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const [track] = stream.getVideoTracks();
const processor = new MediaStreamTrackProcessor({ track });
const reader = processor.readable.getReader();
const { value: frame, done } = await reader.read();
if (!done) {
const meta = frame.metadata();
console.log('Metadaten:', meta);
if ('captureTime' in meta) {
console.log(`Aufgenommen bei ${meta.captureTime.toFixed(1)} ms`);
}
frame.close(); // Speicher sofort freigeben
}
track.stop();
Latenz bei WebRTC-Empfang messen
// Voraussetzung: remoteTrack ist ein eingehender Video-Track einer RTCPeerConnection
const measureLatency = async (remoteTrack) => {
const processor = new MediaStreamTrackProcessor({ track: remoteTrack });
const reader = processor.readable.getReader();
for (let i = 0; i < 30; i++) {
const { value: frame, done } = await reader.read();
if (done) break;
const { captureTime, receiveTime, rtpTimestamp } = frame.metadata();
if (captureTime !== undefined && receiveTime !== undefined) {
console.log(`RTP ${rtpTimestamp}: Latenz ${(receiveTime - captureTime).toFixed(1)} ms`);
}
frame.close();
}
reader.releaseLock();
};
Frame aus einem Canvas: leere Metadaten und Kopier-Verhalten
const canvas = new OffscreenCanvas(320, 240);
canvas.getContext('2d').fillRect(0, 0, 320, 240);
const frame = new VideoFrame(canvas, { timestamp: 0 });
const meta = frame.metadata();
console.log(meta); // Canvas-Quelle liefert keine Metadaten
meta.foo = 'bar'; // Ändert nur die Kopie
console.log(frame.metadata().foo);
frame.close();
try {
frame.metadata();
} catch (err) {
console.log(err.name);
}
// Wichtig · Fallstricke
- Geschlossene Frames: Wenn du
metadata()nachclose()aufrufst, wird eineDOMExceptionvom TypInvalidStateErrorgeworfen. - Felder nicht garantiert: Welche Felder vorhanden sind, hängt von Quelle und Browser ab. Prüfe jedes Feld (z. B. mit
'captureTime' in metaoder!== undefined), bevor du damit arbeitest. Frames aus Canvas, Bildern oder Decodern haben meist keine Metadaten. - Kompatibilität: WebCodecs gibt es nur in sicheren Kontexten (HTTPS).
metadata()ist noch nicht Baseline: Chromium-Browser unterstützen die Methode samt WebRTC-Feldern, andere Browser nur teilweise oder gar nicht. Führe vorher eine Funktionsprüfung durch:typeof VideoFrame !== 'undefined' && 'metadata' in VideoFrame.prototype.MediaStreamTrackProcessorgibt es im Hauptthread nur in Chromium. - Speicher:
VideoFrame-Objekte belegen oft GPU- bzw. Decoder-Ressourcen. Lies die Metadaten, die du brauchst, und rufe danach möglichst schnellclose()auf. - Die Zeitwerte (
captureTime,receiveTime) sindDOMHighResTimeStamp-Werte in Millisekunden. Sie beziehen sich auf die Zeitbasis vonperformance.now(), nicht aufVideoFrame.timestamp(Mikrosekunden).