Start · Sprachen · JavaScript · Referenz · ImageTrack.repetitionCount

ImageTrack.repetitionCount

Eigenschaft

Nur lesbare Eigenschaft, die angibt, wie oft die Animation eines <code>ImageTrack</code> wiederholt werden soll. Bei Endlosschleifen ist der Wert <code>Infinity</code>.

seit JavaScript WebCodecs API: Chrome/Edge 94+, Firefox 133+; Safa Kategorie: webapi

Signatur

ImageTrack.repetitionCount

Beschreibung

Die Eigenschaft repetitionCount des Interfaces ImageTrack gehört zur WebCodecs API. Sie gibt an, wie oft die Animation eines Bild-Tracks nach dem ersten Durchlauf wiederholt werden soll. Der Wert kommt direkt aus den Metadaten der Bilddatei, bei animierten GIFs zum Beispiel aus der Loop-Angabe der NETSCAPE2.0-Erweiterung, bei animierten WebP- oder APNG-Dateien aus dem jeweiligen Loop-Feld.

Die Werte bedeuten Folgendes:

  • 0: Die Animation läuft genau einmal. Das gilt auch für Standbilder ohne Animation.
  • n > 0: Die Animation wird n-mal wiederholt. Insgesamt läuft sie also n + 1-mal.
  • Infinity: Die Animation läuft in einer Endlosschleife.

Die Eigenschaft ist nützlich, wenn du Animationen selbst abspielst: Du dekodierst die einzelnen Bilder mit ImageDecoder.decode() und zeichnest sie zum Beispiel auf ein <canvas>. Damit dein eigener Player sich wie der Browser verhält, musst du die Wiederholungsangabe der Datei beachten. Den Track erhältst du über decoder.tracks.selectedTrack oder über einen Index in der ImageTrackList. Die Werte stehen erst sicher fest, wenn das Promise decoder.tracks.ready erfüllt ist.

Rückgabewert

Typ
number
Beschreibung
Anzahl der Wiederholungen nach dem ersten Durchlauf. 0 steht für einen einzigen Durchlauf, Infinity für eine Endlosschleife. Die Eigenschaft ist nur lesbar.

Beispiele

Wiederholungsanzahl eines animierten GIFs auslesen

const response = await fetch('/bilder/lade-animation.gif');

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

// Warten, bis die Track-Informationen vorliegen
await decoder.tracks.ready;
const track = decoder.tracks.selectedTrack;

console.log('Animiert:', track.animated);
console.log('Wiederholungen:', track.repetitionCount);

if (track.repetitionCount === Infinity) {
  console.log('Endlosschleife');
} else {
  console.log(`Läuft insgesamt ${track.repetitionCount + 1}-mal`);
}
Animiert: true Wiederholungen: Infinity Endlosschleife

Eigener Canvas-Player, der repetitionCount beachtet

const playAnimation = async (url, canvas) => {
  const ctx = canvas.getContext('2d');
  const response = await fetch(url);
  const decoder = new ImageDecoder({
    data: response.body,
    type: response.headers.get('Content-Type') ?? 'image/gif'
  });

  await decoder.tracks.ready;
  const track = decoder.tracks.selectedTrack;
  await decoder.completed; // frameCount steht erst jetzt sicher fest

  const totalRuns = track.repetitionCount + 1; // Infinity + 1 === Infinity

  for (let run = 0; run < totalRuns; run++) {
    for (let i = 0; i < track.frameCount; i++) {
      const { image } = await decoder.decode({ frameIndex: i });
      ctx.drawImage(image, 0, 0);
      const delayMs = (image.duration ?? 100_000) / 1000; // Mikrosekunden -> ms
      image.close(); // VideoFrame sofort freigeben
      await new Promise((r) => setTimeout(r, delayMs));
    }
  }
  decoder.close();
  console.log('Animation beendet');
};

playAnimation('/bilder/banner.webp', document.querySelector('canvas'));
Animation beendet (nur bei endlicher Wiederholungsanzahl)

Alle Tracks einer Datei auflisten

const inspectTracks = async (blob) => {
  const decoder = new ImageDecoder({ data: blob, type: blob.type });
  await decoder.tracks.ready;

  for (let i = 0; i < decoder.tracks.length; i++) {
    const t = decoder.tracks[i];
    console.log(`Track ${i}: animiert=${t.animated}, Frames=${t.frameCount}, Wiederholungen=${t.repetitionCount}`);
  }
  decoder.close();
};

const input = document.querySelector('input[type=file]');
input.addEventListener('change', () => inspectTracks(input.files[0]));
Track 0: animiert=true, Frames=24, Wiederholungen=3

// Wichtig · Fallstricke

  • Zählweise: Der Wert zählt die Wiederholungen, nicht die Durchläufe insgesamt. Bei repetitionCount === 2 wird die Animation dreimal abgespielt.
  • Endlosschleife: Eine Endlosschleife wird als Infinity gemeldet, nicht als 0 wie im GIF-Dateiformat. Wenn du den Wert mit JSON.stringify() serialisierst, wird aus Infinity null.
  • Zeitpunkt: Lies die Eigenschaft erst, nachdem decoder.tracks.ready erfüllt ist. Bei gestreamten Daten ist eventuell auch erst nach decoder.completed alles endgültig bekannt.
  • Standbilder: Bei Standbildern wie JPEG oder PNG ohne Animation ist der Wert 0. Ob eine Datei animiert ist, prüfst du zusätzlich über ImageTrack.animated.
  • Kompatibilität: ImageDecoder und ImageTrack gibt es in Chromium-basierten Browsern ab Version 94 und in neueren Firefox-Versionen, in Safari aber nicht. Die API funktioniert nur in sicheren Kontexten (HTTPS) und ist auch in Web Workern verfügbar. Prüfe vor der Nutzung mit 'ImageDecoder' in globalThis, ob sie vorhanden ist, und frage mit ImageDecoder.isTypeSupported() ab, welche Bildformate unterstützt werden.
  • Speicher: Rufe bei eigenen Playern image.close() für jeden dekodierten VideoFrame auf. Sonst wächst bei Endlosschleifen der Speicherverbrauch.