Start · Sprachen · JavaScript · Referenz · VideoDecoder.close()

VideoDecoder.close()

Methode

Beendet einen <code>VideoDecoder</code> endgültig: bricht alle ausstehenden Dekodierungen ab, gibt Systemressourcen frei und setzt <code>state</code> auf <code>"closed"</code>.

seit JavaScript WebCodecs: Chrome/Edge 94+, Safari 16.4+, Firefox Kategorie: webapi

Signatur

VideoDecoder.prototype.close()

Beschreibung

Die Methode close() der VideoDecoder-Schnittstelle beendet den Decoder sofort und dauerhaft. Alle Aufträge in der Dekodier-Warteschlange werden verworfen, Callbacks werden nicht mehr aufgerufen, und die belegten Ressourcen (häufig Hardware-Decoder oder GPU-Speicher) werden freigegeben. Danach hat decoder.state den Wert "closed".

Verwenden Sie close(), sobald Sie einen Decoder nicht mehr brauchen, etwa am Ende einer Wiedergabe, beim Wechsel zu einem anderen Video, beim Verlassen einer Seite oder wenn ein Worker beendet wird. Hardware-Decoder sind oft knapp. Wenn Sie Decoder nicht schließen, kann das Anlegen neuer Instanzen fehlschlagen oder auf langsamere Software-Dekodierung ausweichen.

Ein geschlossener Decoder lässt sich nicht wieder öffnen. Aufrufe von configure(), decode(), flush() oder reset() lösen danach einen InvalidStateError aus. Für einen neuen Durchlauf mit derselben Instanz verwenden Sie reset(). close() ist nur für das endgültige Aufräumen gedacht.

Möchten Sie alle bereits übergebenen Chunks noch ausgeben, bevor Sie schließen, warten Sie zuerst auf await decoder.flush() und rufen Sie erst danach close() auf.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined). Die Methode arbeitet synchron. Die Ressourcen werden sofort freigegeben, eine Promise gibt es nicht.

Beispiele

Decoder nach dem Dekodieren sauber schließen

const decoder = new VideoDecoder({
  output: (frame) => {
    // Frame zeichnen und danach sofort freigeben
    ctx.drawImage(frame, 0, 0);
    frame.close();
  },
  error: (e) => console.error('Decoder-Fehler:', e),
});

decoder.configure({ codec: 'avc1.42E01E', codedWidth: 1280, codedHeight: 720 });

for (const chunk of encodedChunks) {
  decoder.decode(chunk);
}

// Erst alle ausstehenden Frames ausgeben, dann schließen
await decoder.flush();
decoder.close();
console.log(decoder.state);
closed

Wiedergabe abbrechen: laufender flush() wird abgewiesen

const decoder = new VideoDecoder({
  output: (frame) => frame.close(),
  error: (e) => console.error(e),
});
decoder.configure({ codec: 'vp8', codedWidth: 640, codedHeight: 360 });
encodedChunks.forEach((c) => decoder.decode(c));

const pending = decoder.flush().catch((err) => {
  console.log('flush abgebrochen:', err.name);
});

// Benutzer klickt auf "Stopp" – sofort alles verwerfen
decoder.close();
await pending;
flush abgebrochen: AbortError

Sicheres Aufräumen mit Zustandsprüfung

const disposeDecoder = (decoder) => {
  // close() auf einem bereits geschlossenen Decoder wirft InvalidStateError
  if (decoder && decoder.state !== 'closed') {
    decoder.close();
  }
};

const decoder = new VideoDecoder({
  output: (frame) => frame.close(),
  error: () => disposeDecoder(decoder),
});

disposeDecoder(decoder);
disposeDecoder(decoder); // kein Fehler beim zweiten Aufruf
console.log(decoder.state);
closed

Decoder beim Beenden eines Workers freigeben

// worker.js
let decoder = null;

self.onmessage = ({ data }) => {
  if (data.type === 'start') {
    decoder = new VideoDecoder({
      output: (frame) => self.postMessage({ frame }, [frame]),
      error: (e) => self.postMessage({ error: e.message }),
    });
    decoder.configure(data.config);
  } else if (data.type === 'chunk') {
    decoder.decode(new EncodedVideoChunk(data.chunk));
  } else if (data.type === 'stop') {
    if (decoder?.state !== 'closed') decoder?.close();
    decoder = null;
    self.close();
  }
};

// Wichtig · Fallstricke

  • Endgültig: Einen geschlossenen Decoder können Sie nicht wiederverwenden. Jeder weitere Methodenaufruf, auch ein zweites close(), löst einen DOMException vom Typ InvalidStateError aus. Prüfen Sie deshalb vorher decoder.state !== "closed".
  • Ausstehende Arbeit geht verloren: Chunks in der Warteschlange werden nicht mehr dekodiert. Offene flush()-Promises werden mit AbortError abgewiesen. Wenn Sie alle Frames brauchen, warten Sie vorher auf await decoder.flush().
  • Kein Aufruf des Fehler-Callbacks: Schließen Sie den Decoder selbst, wird der error-Callback nicht ausgelöst. Tritt dagegen intern ein Fehler auf, schließt der Browser den Decoder automatisch und ruft error auf.
  • Ausgegebene Frames bleiben bestehen: close() gibt nur die Ressourcen des Decoders frei. VideoFrame-Objekte, die bereits ausgegeben wurden, müssen Sie selbst mit frame.close() freigeben. Sonst kann der Decoder ins Stocken geraten und GPU-Speicher knapp werden.
  • reset() oder close()? Beim Springen im Video (Seeking) oder bei einer neuen Konfiguration reicht reset(). Nehmen Sie close() nur, wenn Sie die Instanz nicht mehr brauchen.
  • Kompatibilität: WebCodecs steht nur in sicheren Kontexten (HTTPS) zur Verfügung, im Fenster und in dedizierten Workern. Prüfen Sie die Verfügbarkeit mit 'VideoDecoder' in self. Ältere Safari- und Firefox-Versionen unterstützen die API nicht.