Start · Sprachen · JavaScript · Referenz · EncodedVideoChunk.copyTo()

EncodedVideoChunk.copyTo()

Methode

Kopiert die kodierten Videodaten eines <code>EncodedVideoChunk</code> in einen vom Aufrufer bereitgestellten <code>ArrayBuffer</code>, <code>TypedArray</code> oder <code>DataView</code>.

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

Signatur

EncodedVideoChunk.prototype.copyTo(destination)

Beschreibung

Die Methode copyTo() gehört zum Interface EncodedVideoChunk der WebCodecs API. Ein EncodedVideoChunk ist ein Stück kodiertes Video, z. B. ein H.264-, VP8/VP9- oder AV1-Frame. Seine Nutzdaten sind nicht direkt zugänglich, weil das Objekt unveränderlich ist. Mit copyTo() holst du die Rohbytes synchron in einen eigenen Puffer.

Das brauchst du vor allem, wenn du kodierte Frames aus einem VideoEncoder weiterverarbeiten willst. Typische Fälle:

  • ein eigenes Container-Format schreiben (MP4, WebM, IVF)
  • Frames per WebSocket, WebTransport oder RTCDataChannel an einen Server oder eine Gegenstelle schicken
  • Frames in IndexedDB zwischenspeichern

Der Zielpuffer muss mindestens chunk.byteLength Bytes groß sein. Deshalb legst du ihn in der Regel mit genau dieser Größe an: new Uint8Array(chunk.byteLength). Die Methode gibt nichts zurück, sondern schreibt die Daten direkt in destination.

Parameter

Name Typ Default Beschreibung
$destination Pflicht ArrayBuffer | TypedArray | DataView Zielpuffer, in den die kodierten Bytes geschrieben werden. Er muss mindestens byteLength Bytes des Chunks fassen. Ein SharedArrayBuffer ist ebenfalls erlaubt.

Beispiele

Chunk aus dem VideoEncoder in ein Uint8Array kopieren

const encoder = new VideoEncoder({
  output: (chunk, metadata) => {
    // Puffer in exakt passender Größe anlegen
    const data = new Uint8Array(chunk.byteLength);
    chunk.copyTo(data);
    console.log(chunk.type, chunk.timestamp, data.byteLength);
  },
  error: (e) => console.error('Encoder-Fehler:', e)
});

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

const canvas = new OffscreenCanvas(640, 480);
canvas.getContext('2d').fillRect(0, 0, 640, 480);
const frame = new VideoFrame(canvas, { timestamp: 0 });
encoder.encode(frame, { keyFrame: true });
frame.close();
await encoder.flush();
key 0 1234 (Größe hängt vom Inhalt ab)

Kodierte Frames per WebSocket versenden

const socket = new WebSocket('wss://example.com/stream');
socket.binaryType = 'arraybuffer';

const sendChunk = (chunk) => {
  // 1 Byte Typ + 8 Byte Zeitstempel + Nutzdaten
  const buffer = new ArrayBuffer(9 + chunk.byteLength);
  const view = new DataView(buffer);
  view.setUint8(0, chunk.type === 'key' ? 1 : 0);
  view.setBigInt64(1, BigInt(chunk.timestamp));
  // Nur in den Nutzdaten-Bereich kopieren
  chunk.copyTo(new Uint8Array(buffer, 9));
  socket.send(buffer);
};

const encoder = new VideoEncoder({
  output: sendChunk,
  error: console.error
});

Chunk klonen bzw. auf Empfängerseite rekonstruieren

const cloneChunk = (chunk) => {
  const data = new Uint8Array(chunk.byteLength);
  chunk.copyTo(data);
  return new EncodedVideoChunk({
    type: chunk.type,
    timestamp: chunk.timestamp,
    duration: chunk.duration ?? undefined,
    data
  });
};

const original = new EncodedVideoChunk({
  type: 'key', timestamp: 0, data: new Uint8Array([1, 2, 3, 4])
});
const copy = cloneChunk(original);
console.log(copy.byteLength, copy.type);
4 key

// Wichtig · Fallstricke

  • Puffergröße: Ist destination kleiner als chunk.byteLength, wirft die Methode einen TypeError. Nimm deshalb immer byteLength als Maß.
  • Kein Offset-Parameter: Die Methode schreibt immer ab dem Anfang von destination. Soll an eine bestimmte Stelle geschrieben werden, übergib eine Sicht mit Offset, z. B. new Uint8Array(buffer, offset).
  • Abgelöste Puffer: Ein bereits übertragener (detached) ArrayBuffer führt zu einem Fehler.
  • Performance: Jeder Aufruf kopiert die Daten. Bei hohen Bildraten lohnt es sich, Puffer wiederzuverwenden, statt pro Frame neue anzulegen. Eine wiederverwendete Sicht muss dabei auf byteLength zugeschnitten werden, sonst bleiben alte Bytes am Ende stehen.
  • Metadaten: Codec-Konfiguration wie decoderConfig.description (z. B. avcC bei H.264) steckt nicht im Chunk. Sie kommt über das metadata-Argument des Encoder-Callbacks und muss getrennt übertragen werden.
  • Kompatibilität: WebCodecs gibt es nur in sicheren Kontexten (HTTPS). Unterstützt wird es in Chromium ab Version 94, in Safari ab 16.4 und in Firefox ab 130. Prüfe die Verfügbarkeit mit 'EncodedVideoChunk' in globalThis. Die API ist auch in Workern verfügbar.