Start · Sprachen · JavaScript · Referenz · ImageTrackList.ready

ImageTrackList.ready

Eigenschaft

Liefert ein <code>Promise</code>, das erfüllt wird, sobald die <code>ImageTrackList</code> eines <code>ImageDecoder</code> mit ihren Spuren (<code>ImageTrack</code>) gefüllt ist.

seit JavaScript WebCodecs API: Chrome/Edge 94+, Opera 80+, Firefox Kategorie: webapi

Signatur

ImageTrackList.ready

Beschreibung

Die schreibgeschützte Eigenschaft ready der Schnittstelle ImageTrackList gehört zur WebCodecs API. Eine ImageTrackList bekommt man über ImageDecoder.tracks. Sie enthält alle Spuren eines Bildes. Die meisten Formate haben nur eine Spur. Bei animierten Formaten wie AVIF kann es aber zum Beispiel eine statische und eine animierte Spur geben.

Beim Anlegen eines ImageDecoder muss der Browser erst die Kopfdaten (Header) des Bildes lesen. Erst danach weiß er, wie viele Spuren es gibt. Bis dahin ist die Liste leer: length ist 0 und selectedTrack ist null. Mit await decoder.tracks.ready wartet man genau auf diesen Zeitpunkt. Danach kann man Spuren auswählen, frameCount und animated auslesen und decode() gezielt aufrufen.

Das Promise wird mit undefined erfüllt. Die eigentlichen Daten liest man anschließend über die Liste selbst aus, per Index (tracks[0]), selectedIndex oder selectedTrack. Das Promise wird abgelehnt, wenn das Bild nicht dekodiert werden kann (etwa bei beschädigten Daten oder einem falschen MIME-Typ) oder wenn der Decoder vorher mit close() geschlossen wird.

Rückgabewert

Typ
Promise<undefined>
Beschreibung
Ein Promise, das mit undefined erfüllt wird, sobald die Spurliste gefüllt ist. Es wird abgelehnt (meist mit einer DOMException), wenn die Dekodierung fehlschlägt oder der Decoder geschlossen wird.

Beispiele

Auf die Spuren eines GIFs warten und Metadaten auslesen

const response = await fetch('/bilder/animation.gif');
const decoder = new ImageDecoder({
  data: response.body,
  type: 'image/gif'
});

// Vorher ist die Liste noch leer
console.log('Vorher:', decoder.tracks.length);

await decoder.tracks.ready;

const track = decoder.tracks.selectedTrack;
console.log('Nachher:', decoder.tracks.length);
console.log('Animiert:', track.animated);
console.log('Wiederholungen:', track.repetitionCount);
Vorher: 0 Nachher: 1 Animiert: true Wiederholungen: Infinity

Alle Frames einer Animation in ein Canvas zeichnen

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

const response = await fetch('/bilder/lader.webp');
const decoder = new ImageDecoder({ data: response.body, type: 'image/webp' });

await decoder.tracks.ready;
// Bei gestreamten Daten ist frameCount erst nach completed endgültig
await decoder.completed;

const { frameCount } = decoder.tracks.selectedTrack;

for (let i = 0; i < frameCount; i++) {
  const { image } = await decoder.decode({ frameIndex: i });
  ctx.drawImage(image, 0, 0);
  const dauerMs = (image.duration ?? 100000) / 1000; // Mikrosekunden -> ms
  image.close(); // VideoFrame sofort freigeben
  await new Promise((r) => setTimeout(r, dauerMs));
}

Fehlerbehandlung und Funktionserkennung

const ladeSpuren = async (url, type) => {
  if (!('ImageDecoder' in window) || !(await ImageDecoder.isTypeSupported(type))) {
    console.warn('ImageDecoder oder Format nicht unterstützt');
    return null;
  }
  const data = await (await fetch(url)).arrayBuffer();
  const decoder = new ImageDecoder({ data, type });
  try {
    await decoder.tracks.ready;
    return Array.from({ length: decoder.tracks.length }, (_, i) => ({
      index: i,
      animated: decoder.tracks[i].animated,
      frames: decoder.tracks[i].frameCount
    }));
  } catch (err) {
    console.error('Bild konnte nicht gelesen werden:', err.name);
    return null;
  } finally {
    decoder.close();
  }
};

console.log(await ladeSpuren('/bilder/foto.avif', 'image/avif'));
[{ index: 0, animated: false, frames: 1 }]

// Wichtig · Fallstricke

  • Browser-Unterstützung: ImageDecoder gibt es in Chromium-Browsern ab Version 94 und in Firefox ab Version 133. Safari unterstützt es nicht. Die API funktioniert nur in sicheren Kontexten (HTTPS) und steht auch in Web Workern zur Verfügung. Deshalb vorher auf 'ImageDecoder' in self prüfen.
  • ready garantiert nur, dass die Spuren bekannt sind. Werden die Daten als ReadableStream geliefert, kann frameCount zu diesem Zeitpunkt noch zu klein sein. Den endgültigen Wert gibt es erst nach await decoder.completed.
  • Das Promise wird mit undefined erfüllt, nicht mit der Liste. Also nicht const tracks = await decoder.tracks.ready schreiben.
  • Wird decoder.close() aufgerufen, bevor das Promise erfüllt ist, wird es abgelehnt. Ohne try/catch führt das zu einer unbehandelten Ablehnung.
  • Von decode() gelieferte VideoFrame-Objekte belegen GPU- bzw. Arbeitsspeicher. Sie sollten immer mit close() freigegeben werden.