Start · Sprachen · JavaScript · Referenz · new VideoDecoder()

new VideoDecoder()

Methode

Erstellt ein neues <code>VideoDecoder</code>-Objekt, das kodierte Videoblöcke dekodiert und die Frames über <code>init.output</code> zurückliefert. Fehler meldet es über <code>init.error</code>.

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

Signatur

new VideoDecoder(init)

Beschreibung

Der Konstruktor VideoDecoder() gehört zur WebCodecs API und erzeugt einen Decoder mit Low-Level-Zugriff auf die Video-Codecs des Browsers (H.264/AVC, H.265/HEVC, VP8, VP9, AV1). Anders als beim <video>-Element steuerst du selbst, welche kodierten Daten (EncodedVideoChunk) wann dekodiert werden, und bekommst jedes Bild als VideoFrame zurück.

Nach dem Konstruktor-Aufruf ist der Decoder im Zustand "unconfigured". Bevor du mit decode() dekodieren kannst, musst du configure() mit einer passenden Codec-Konfiguration aufrufen. Die Ausgabe läuft asynchron: Jeder fertig dekodierte Frame wird an den output-Callback übergeben, jeder schwere Fehler an den error-Callback. Danach wechselt der Decoder in den Zustand "closed".

Typische Einsatzfälle sind eigene Videoplayer (z. B. mit WebTransport oder WebSocket als Transportweg), Cloud-Gaming, Videobearbeitung im Browser, Frame-genaues Scrubbing sowie das Weiterverarbeiten einzelner Frames in Canvas, WebGL oder WebGPU. Der Decoder funktioniert auch in Dedicated Workern. Das ist empfehlenswert, damit der Haupt-Thread entlastet wird.

Parameter

Name Typ Default Beschreibung
$init Pflicht Object Initialisierungsobjekt mit den beiden Pflicht-Callbacks output und error.
$init.output Pflicht (frame: VideoFrame) => void Wird für jeden dekodierten Frame mit einem VideoFrame aufgerufen. Wenn du den Frame nicht mehr brauchst, musst du frame.close() aufrufen.
$init.error Pflicht (error: DOMException) => void Wird bei einem schweren Fehler aufgerufen, z. B. EncodingError bei beschädigten Daten oder NotSupportedError bei einer nicht unterstützten Konfiguration. Danach ist der Decoder geschlossen.

Rückgabewert

Typ
VideoDecoder
Beschreibung
Eine neue VideoDecoder-Instanz im Zustand "unconfigured".

Beispiele

Decoder erzeugen und konfigurieren

const decoder = new VideoDecoder({
  output: (frame) => {
    console.log(`Frame: ${frame.codedWidth}x${frame.codedHeight} @ ${frame.timestamp}µs`);
    frame.close(); // Speicher sofort freigeben
  },
  error: (e) => console.error('Decoder-Fehler:', e.name, e.message),
});

console.log(decoder.state);

decoder.configure({
  codec: 'vp8',
  codedWidth: 640,
  codedHeight: 480,
});

console.log(decoder.state);
unconfigured configured

Unterstützung prüfen und Frames auf ein Canvas zeichnen

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

const config = {
  codec: 'avc1.42E01E', // H.264 Baseline
  codedWidth: 1280,
  codedHeight: 720,
  hardwareAcceleration: 'prefer-hardware',
};

const setupDecoder = async () => {
  if (!('VideoDecoder' in window)) {
    throw new Error('WebCodecs wird nicht unterstützt');
  }
  const { supported } = await VideoDecoder.isConfigSupported(config);
  if (!supported) throw new Error(`Codec ${config.codec} nicht unterstützt`);

  const decoder = new VideoDecoder({
    output: (frame) => {
      ctx.drawImage(frame, 0, 0, canvas.width, canvas.height);
      frame.close();
    },
    error: (e) => console.error(e),
  });
  decoder.configure(config);
  return decoder;
};

const decoder = await setupDecoder();
console.log('Bereit:', decoder.state);
Bereit: configured

Kodierte Chunks dekodieren und am Ende leeren

// chunks: Array aus { data: ArrayBuffer, timestamp: number, key: boolean },
// z. B. aus einem MP4-Demuxer wie mp4box.js
const decodeAll = async (chunks, config) => {
  let count = 0;
  const decoder = new VideoDecoder({
    output: (frame) => { count++; frame.close(); },
    error: (e) => console.error('Abbruch:', e),
  });
  decoder.configure(config);

  for (const c of chunks) {
    // Staudruck begrenzen: nicht zu viele Chunks in die Warteschlange
    while (decoder.decodeQueueSize > 10) {
      await new Promise((r) => decoder.addEventListener('dequeue', r, { once: true }));
    }
    decoder.decode(new EncodedVideoChunk({
      type: c.key ? 'key' : 'delta',
      timestamp: c.timestamp,
      data: c.data,
    }));
  }

  await decoder.flush(); // wartet, bis alle Frames ausgegeben wurden
  decoder.close();
  console.log(`${count} Frames dekodiert`);
};
z. B. "300 Frames dekodiert"

// Wichtig · Fallstricke

  • Beide Callbacks sind Pflicht: Fehlt output oder error oder ist einer davon keine Funktion, wirft der Konstruktor einen TypeError.
  • frame.close() nicht vergessen: VideoFrame-Objekte belegen oft GPU- oder Hardware-Puffer. Werden sie nicht geschlossen, kann der Decoder ins Stocken geraten, weil sein Frame-Pool erschöpft ist, und es gibt Speicherlecks.
  • Der erste Chunk muss ein Keyframe sein (type: 'key'), auch nach configure() oder reset(). Sonst wird ein DataError geworfen.
  • Bei H.264/HEVC im AVC-Format (MP4) musst du in configure() das description-Feld (avcC-Box) mitgeben. Ohne dieses Feld erwartet der Decoder Annex-B-Daten.
  • Prüfe die Konfiguration vorher mit VideoDecoder.isConfigSupported(). Welche Codecs verfügbar sind, hängt von Browser, Betriebssystem und Hardware ab.
  • Kompatibilität: Nur in sicheren Kontexten (HTTPS) verfügbar, im Window und in Dedicated Workern. Chromium-Browser ab 94, Safari ab 16.4 (nur Video), Firefox ab 130. Vorher per Feature-Erkennung prüfen ('VideoDecoder' in globalThis).
  • Die WebCodecs API enthält keinen Demuxer. Container wie MP4 oder WebM musst du selbst oder mit einer Bibliothek zerlegen.