Start · Sprachen · JavaScript · Referenz · EncodedVideoChunk.timestamp

EncodedVideoChunk.timestamp

Eigenschaft

Liefert als schreibgeschützte Ganzzahl den Präsentationszeitstempel eines kodierten Video-Chunks in Mikrosekunden.

seit JavaScript WebCodecs API – Chrome/Edge 94+, Safari 16.4+ (Vid Kategorie: webapi

Signatur

get EncodedVideoChunk.timestamp

Beschreibung

Die schreibgeschützte Eigenschaft timestamp eines EncodedVideoChunk-Objekts gibt den Präsentationszeitstempel des Chunks in Mikrosekunden an. Der Wert wird beim Aufruf des Konstruktors new EncodedVideoChunk({ timestamp, ... }) festgelegt oder vom VideoEncoder gesetzt. Er stammt aus dem timestamp des zugehörigen VideoFrame.

Der Zeitstempel wird gebraucht, um kodierte Daten richtig anzuordnen und zu synchronisieren. Das gilt etwa beim Muxen in einen Container (MP4, WebM), beim Übertragen über WebTransport oder WebRTC-ähnliche Pipelines und beim Abgleich mit Audiospuren (EncodedAudioChunk.timestamp). Beim Dekodieren gibt der VideoDecoder den Wert unverändert an das erzeugte VideoFrame weiter.

Wichtig: timestamp ist ein Präsentationszeitstempel, keine Dekodierreihenfolge. Bei Codecs mit B-Frames (z. B. H.264 oder HEVC) kann die Ausgabereihenfolge des Encoders von der zeitlichen Reihenfolge abweichen. Der Wert kann auch negativ sein, etwa bei Vorlauf-Frames oder Edit-Lists.

Beispiele

Chunk erzeugen und Zeitstempel auslesen

// Rohdaten eines bereits kodierten Keyframes (Platzhalter)
const data = new Uint8Array([0x00, 0x00, 0x00, 0x01, 0x65]);

const chunk = new EncodedVideoChunk({
  type: 'key',
  timestamp: 33_333, // 33,333 ms = zweiter Frame bei 30 fps
  duration: 33_333,
  data
});

console.log(chunk.timestamp);
console.log(`${(chunk.timestamp / 1_000_000).toFixed(3)} s`);
33333 0.033 s

Zeitstempel im VideoEncoder-Output protokollieren

const encoder = new VideoEncoder({
  output: (chunk, metadata) => {
    console.log(`${chunk.type}-Chunk @ ${chunk.timestamp} µs, ${chunk.byteLength} Bytes`);
  },
  error: (e) => console.error('Encoder-Fehler:', e)
});

encoder.configure({ codec: 'vp8', width: 640, height: 480, bitrate: 1_000_000, framerate: 30 });

const canvas = new OffscreenCanvas(640, 480);
const ctx = canvas.getContext('2d');

for (let i = 0; i < 3; i++) {
  ctx.fillStyle = `hsl(${i * 120}, 80%, 50%)`;
  ctx.fillRect(0, 0, 640, 480);
  // Zeitstempel des Frames landet später im Chunk
  const frame = new VideoFrame(canvas, { timestamp: i * 33_333 });
  encoder.encode(frame, { keyFrame: i === 0 });
  frame.close();
}

await encoder.flush();
key-Chunk @ 0 µs, … Bytes delta-Chunk @ 33333 µs, … Bytes delta-Chunk @ 66666 µs, … Bytes

Chunks vor dem Muxen nach Präsentationszeit sortieren

const chunks = [];

const encoder = new VideoEncoder({
  output: (chunk) => chunks.push(chunk),
  error: console.error
});

// ... configure() und encode() wie gewohnt ...

const sortByPresentation = (list) =>
  [...list].sort((a, b) => a.timestamp - b.timestamp);

const ordered = sortByPresentation(chunks);
const totalDurationUs = ordered.length
  ? ordered.at(-1).timestamp + (ordered.at(-1).duration ?? 0) - ordered[0].timestamp
  : 0;

console.log(`Gesamtdauer: ${totalDurationUs / 1000} ms`);
Gesamtdauer: … ms

// Wichtig · Fallstricke

  • Einheit Mikrosekunden: Die Einheit ist nicht Millisekunden wie bei performance.now() und nicht Sekunden wie bei HTMLMediaElement.currentTime. Für Container wie MP4 musst du den Wert in die Timescale des Tracks umrechnen, z. B. mit Math.round(ts * timescale / 1e6).
  • Schreibgeschützt: Eine Zuweisung wie chunk.timestamp = 0 wird stillschweigend ignoriert, im Strict Mode wirft sie einen TypeError. Um einen anderen Zeitstempel zu setzen, erzeugst du einen neuen Chunk: Die Daten kopierst du mit copyTo() heraus und übergibst sie an new EncodedVideoChunk().
  • Keine Dekodierreihenfolge: Bei B-Frames sind die Zeitstempel in der Ausgabereihenfolge des Encoders nicht zwingend aufsteigend. Einen separaten DTS gibt es nicht. Beim Muxen musst du ihn gegebenenfalls selbst ableiten.
  • Genauigkeit: Werte jenseits von Number.MAX_SAFE_INTEGER sind in der Praxis kein Thema. Bei 30 fps entstehen aber Rundungsfehler (33 333,33… µs pro Frame). Berechne die Zeitstempel deshalb aus der Frame-Nummer (Math.round(i * 1e6 / fps)), statt sie aufzusummieren.
  • Kompatibilität: Die WebCodecs-API ist nur in sicheren Kontexten (HTTPS) verfügbar. Sie läuft im Hauptthread und in Workern. Chromium unterstützt sie seit Version 94, Firefox seit 130. Safari unterstützt die Video-Teile ab 16.4. Prüfe die Verfügbarkeit mit 'EncodedVideoChunk' in globalThis.