Signatur
Beschreibung
Die schreibgeschützte Eigenschaft timestamp eines VideoFrame gibt an, wann das Einzelbild innerhalb des Medienstroms angezeigt werden soll. Die Angabe erfolgt als ganze Zahl in Mikrosekunden (1 s = 1 000 000 µs). Sie ist Teil der WebCodecs API.
Den Wert legt man beim Erzeugen eines Frames über die Option timestamp im Konstruktor new VideoFrame(source, { timestamp }) fest. Bei Frames aus einem VideoDecoder übernimmt der Decoder den Zeitstempel aus dem zugehörigen EncodedVideoChunk. Kommen die Frames von einem MediaStreamTrackProcessor (etwa einer Kamera), setzt der Browser den Wert.
Gebraucht wird der Zeitstempel vor allem, um Audio und Video zu synchronisieren, Frames im richtigen Takt auf ein Canvas zu zeichnen, beim Kodieren die Reihenfolge und die Keyframe-Abstände zu steuern und beim Muxen in Container wie MP4 oder WebM die richtige Zeitbasis zu setzen. Zusammen mit VideoFrame.duration ergibt sich das Zeitfenster, in dem der Frame sichtbar ist.
Rückgabewert
close() ist der Frame nicht mehr nutzbar, der Wert ist dann nicht mehr aussagekräftig.Beispiele
Zeitstempel beim Erzeugen setzen und auslesen
const canvas = new OffscreenCanvas(640, 360);
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'tomato';
ctx.fillRect(0, 0, 640, 360);
// Frame bei 2,5 Sekunden, 1/30 s lang
const frame = new VideoFrame(canvas, {
timestamp: 2_500_000,
duration: Math.round(1_000_000 / 30)
});
console.log(frame.timestamp); // Mikrosekunden
console.log(frame.timestamp / 1e6, 's'); // Sekunden
frame.close();
Frames für einen Encoder mit fester Bildrate erzeugen
const fps = 30;
const canvas = new OffscreenCanvas(320, 240);
const ctx = canvas.getContext('2d');
const encoder = new VideoEncoder({
output: (chunk) => console.log('Chunk', chunk.timestamp, chunk.type),
error: (e) => console.error(e)
});
encoder.configure({ codec: 'vp8', width: 320, height: 240, bitrate: 1_000_000, framerate: fps });
for (let i = 0; i < 3; i++) {
ctx.fillStyle = `hsl(${i * 120}, 80%, 50%)`;
ctx.fillRect(0, 0, 320, 240);
const frame = new VideoFrame(canvas, {
timestamp: Math.round((i * 1_000_000) / fps)
});
encoder.encode(frame, { keyFrame: i === 0 });
frame.close(); // Speicher sofort freigeben
}
await encoder.flush();
Kamera-Frames auswerten (Abstand zwischen Frames)
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const [track] = stream.getVideoTracks();
const processor = new MediaStreamTrackProcessor({ track });
const reader = processor.readable.getReader();
let last = null;
for (let n = 0; n < 5; n++) {
const { value: frame, done } = await reader.read();
if (done) break;
if (last !== null) {
const deltaMs = (frame.timestamp - last) / 1000;
console.log(`Abstand: ${deltaMs.toFixed(1)} ms`);
}
last = frame.timestamp;
frame.close();
}
track.stop();
// Wichtig · Fallstricke
- Einheit: Der Wert ist in Mikrosekunden angegeben, nicht in Millisekunden wie
performance.now()und nicht in Sekunden wieHTMLMediaElement.currentTime. Wer das verwechselt, bekommt schnell Synchronisationsfehler um den Faktor 1000. - Pflichtangabe: Wird ein
VideoFrameaus einemBufferSource(Rohpixeldaten) erzeugt, musstimestampangegeben werden, sonst wirft der Konstruktor einenTypeError. Bei Bildquellen wie Canvas oderImageBitmapist der Wert optional. Ohne Angabe übernimmt der Browser den Zeitstempel der Quelle, falls es einen gibt, sonst 0. - Kein fester Nullpunkt: Bei Kamera-Frames beginnt der Zeitstempel oft nicht bei 0. Für Aufnahmen sollte man ihn auf den ersten Frame beziehen (
frame.timestamp - startTimestamp). - Rundung: Bei Bildraten wie 30 oder 29,97 fps die Werte mit
Math.round()berechnen, damit sich keine Rundungsfehler aufsummieren. - Frames immer mit
close()freigeben, sonst läuft der Grafikspeicher voll. - Kompatibilität: WebCodecs gibt es nur in sicheren Kontexten (HTTPS). Die Unterstützung ist gut in Chromium-Browsern, in Safari ab 16.4 und in Firefox ab 130.
MediaStreamTrackProcessorgibt es derzeit nur in Chromium-Browsern.