Signatur
Beschreibung
EncodedVideoChunk gehört zur WebCodecs API und kapselt genau einen kodierten Videoframe samt Metadaten. Ein VideoEncoder übergibt solche Chunks an seinen output-Callback, und ein VideoDecoder erwartet sie als Eingabe für decode(). So bekommen Sie einen direkten, sehr hardwarenahen Zugriff auf Video-Codecs, ohne den Umweg über <video> oder MediaRecorder.
Einen Chunk erzeugen Sie mit new EncodedVideoChunk(init). Das Init-Objekt enthält den Typ ("key" für Schlüsselbilder oder "delta" für abhängige Bilder), einen Zeitstempel in Mikrosekunden, optional eine Dauer und die eigentlichen Bytes. Die Daten werden beim Erzeugen kopiert. Der Chunk ist danach unveränderlich.
Wichtige Eigenschaften und Methoden:
type:"key"oder"delta"(nur lesbar)timestamp: Präsentationszeitpunkt in Mikrosekunden (nur lesbar)duration: Dauer in Mikrosekunden odernull(nur lesbar)byteLength: Größe der kodierten Daten in Bytes (nur lesbar)copyTo(destination): kopiert die Bytes in einenArrayBuffer, eineTypedArrayoder eineDataView
Typische Einsatzgebiete sind Demuxing von MP4/WebM-Dateien (z. B. mit mp4box.js), Echtzeit-Streaming über WebTransport oder WebSocket, Videobearbeitung im Browser und das eigene Muxen aufgenommener Kamerabilder.
Rückgabewert
EncodedVideoChunk-Objekt.Beispiele
Chunk aus demuxten Daten erzeugen und dekodieren
const decoder = new VideoDecoder({
output: (frame) => {
console.log(`Frame ${frame.timestamp} µs, ${frame.displayWidth}x${frame.displayHeight}`);
frame.close(); // Speicher sofort freigeben
},
error: (e) => console.error('Decoder-Fehler:', e)
});
decoder.configure({
codec: 'vp8',
codedWidth: 640,
codedHeight: 480
});
// sampleBytes: Uint8Array aus einem Demuxer (z. B. WebM-Parser)
const feedSample = (sampleBytes, isKeyframe, timestampUs) => {
const chunk = new EncodedVideoChunk({
type: isKeyframe ? 'key' : 'delta',
timestamp: timestampUs,
duration: 33_333, // ca. 30 fps
data: sampleBytes
});
decoder.decode(chunk);
};
Chunks aus dem VideoEncoder empfangen und übertragen
const socket = new WebSocket('wss://example.com/stream');
socket.binaryType = 'arraybuffer';
const encoder = new VideoEncoder({
output: (chunk, metadata) => {
// Bytes aus dem Chunk in einen eigenen Puffer kopieren
const buffer = new Uint8Array(chunk.byteLength);
chunk.copyTo(buffer);
console.log(chunk.type, chunk.timestamp, chunk.byteLength);
// Einfacher Header: 1 Byte Typ + 8 Byte Zeitstempel
const packet = new Uint8Array(9 + buffer.byteLength);
const view = new DataView(packet.buffer);
view.setUint8(0, chunk.type === 'key' ? 1 : 0);
view.setBigInt64(1, BigInt(chunk.timestamp));
packet.set(buffer, 9);
socket.send(packet);
},
error: (e) => console.error(e)
});
encoder.configure({ codec: 'vp8', width: 640, height: 480, bitrate: 1_000_000 });
Empfangenes Paket wieder in einen Chunk umwandeln
const packetToChunk = (arrayBuffer) => {
const view = new DataView(arrayBuffer);
const isKey = view.getUint8(0) === 1;
const timestamp = Number(view.getBigInt64(1));
return new EncodedVideoChunk({
type: isKey ? 'key' : 'delta',
timestamp,
data: new Uint8Array(arrayBuffer, 9)
});
};
// Test mit einem künstlichen Paket
const raw = new Uint8Array(12);
new DataView(raw.buffer).setUint8(0, 1);
const chunk = packetToChunk(raw.buffer);
console.log(chunk.type, chunk.timestamp, chunk.byteLength, chunk.duration);
// Wichtig · Fallstricke
- Erster Chunk muss ein Schlüsselbild sein: Nach
configure()oderflush()erwartet derVideoDecoderals Erstes einen Chunk vom Typ"key". Sonst wirftdecode()einenDataError. - Zeiteinheit:
timestampunddurationsind in Mikrosekunden angegeben, nicht in Millisekunden. Zeitstempel aus Containern (z. B. MP4-Timescale) müssen Sie also umrechnen. - Daten sind nicht direkt lesbar: Es gibt keine
data-Eigenschaft. Auf die Bytes kommen Sie nur übercopyTo(). Ist der Zielpuffer kleiner alsbyteLength, wird einTypeErrorausgelöst. - Bitstream-Format: Bei H.264/H.265 hängt das erwartete Format (Annex B oder AVC/length-prefixed) davon ab, ob in
configure()einedescriptionübergeben wird. - Kompatibilität: WebCodecs ist nur in sicheren Kontexten (HTTPS) verfügbar, auch in Workern. Chrome/Edge unterstützen es seit Version 94, Safari seit 16.4 und Firefox seit 130 (Desktop). Prüfen Sie die Unterstützung vorher mit
'EncodedVideoChunk' in globalThis. Die Optiontransferist neuer und wird noch nicht überall unterstützt. - Speicher: Anders als
VideoFramehat ein Chunk keineclose()-Methode. Er wird vom Garbage Collector freigegeben. Große Warteschlangen sollten Sie trotzdem begrenzen, z. B. überdecoder.decodeQueueSize.