Signatur
Beschreibung
Ein ImageTrack beschreibt eine einzelne Spur innerhalb einer Bilddatei, die ein ImageDecoder dekodiert. Die meisten Formate (JPEG, PNG, GIF) haben genau eine Spur. Container-Formate wie AVIF können aber mehrere Spuren enthalten, etwa ein Standbild und eine animierte Sequenz.
Einen ImageTrack erzeugt man nicht selbst, es gibt also keinen öffentlichen Konstruktor. Man bekommt ihn über die ImageTrackList in decoder.tracks, entweder per Index (tracks[0]) oder über tracks.selectedTrack. Bevor man zugreift, sollte man auf das Promise tracks.ready warten.
Eigenschaften:
animated(boolean, nur lesbar):true, wenn die Spur mehr als einen Frame zur Animation enthält.frameCount(number, nur lesbar): Anzahl der Frames in der Spur. Bei gestreamten Daten kann der Wert zunächst zu niedrig sein und später steigen.repetitionCount(number, nur lesbar): Wie oft die Animation wiederholt wird.0heißt: einmal abspielen,Infinityheißt: Endlosschleife.selected(boolean, les- und schreibbar): Gibt an, ob die Spur gerade zum Dekodieren ausgewählt ist. Setzt man den Wert auftrue, wird diese Spur aktiv und die bisher gewählte abgewählt.
Man nutzt ImageTrack vor allem, um animierte Bilder (GIF, animiertes WebP/PNG, AVIF) Frame für Frame zu verarbeiten, z. B. um sie selbst auf einem <canvas> abzuspielen, Vorschaubilder zu erzeugen oder Frames in einem Worker zu verarbeiten.
Rückgabewert
ImageDecoder.tracks (eine ImageTrackList), z. B. decoder.tracks.selectedTrack oder decoder.tracks[i].Beispiele
Spur-Informationen eines animierten GIFs auslesen
const response = await fetch('/img/animation.gif');
const decoder = new ImageDecoder({
data: response.body,
type: 'image/gif'
});
// Warten, bis die Spuren bekannt sind
await decoder.tracks.ready;
const track = decoder.tracks.selectedTrack;
// Bei Streams erst nach vollständigem Laden die endgültige Frame-Anzahl
await decoder.completed;
console.log('Animiert:', track.animated);
console.log('Frames:', track.frameCount);
console.log('Wiederholungen:', track.repetitionCount);
Animation Frame für Frame auf ein Canvas zeichnen
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const playAnimation = async (url) => {
const res = await fetch(url);
const decoder = new ImageDecoder({ data: res.body, type: res.headers.get('Content-Type') });
await decoder.completed;
const track = decoder.tracks.selectedTrack;
const loops = track.repetitionCount === Infinity ? 3 : track.repetitionCount + 1;
for (let loop = 0; loop < loops; loop++) {
for (let i = 0; i < track.frameCount; i++) {
const { image } = await decoder.decode({ frameIndex: i });
ctx.drawImage(image, 0, 0);
// duration ist in Mikrosekunden angegeben
await new Promise((r) => setTimeout(r, (image.duration ?? 100000) / 1000));
image.close(); // Speicher freigeben!
}
}
decoder.close();
};
playAnimation('/img/animation.webp');
Zwischen mehreren Spuren wählen (z. B. AVIF)
if (!('ImageDecoder' in window)) {
console.warn('WebCodecs ImageDecoder wird nicht unterstützt');
} else {
const res = await fetch('/img/multi-track.avif');
const decoder = new ImageDecoder({ data: res.body, type: 'image/avif' });
await decoder.tracks.ready;
// Erste animierte Spur suchen und auswählen
const animatedTrack = Array.from(decoder.tracks).find((t) => t.animated);
if (animatedTrack && !animatedTrack.selected) {
animatedTrack.selected = true;
}
console.log('Spuren:', decoder.tracks.length);
console.log('Gewählter Index:', decoder.tracks.selectedIndex);
}
// Wichtig · Fallstricke
- Browser-Unterstützung:
ImageDecoder/ImageTrackgibt es in Chromium-Browsern ab Version 94 und in Firefox ab 133. Safari unterstützt sie bislang nicht. Deshalb vorher mit'ImageDecoder' in windowprüfen und eine Alternative vorsehen, etwa<img>odercreateImageBitmap(). - Nur in einem sicheren Kontext (HTTPS) verfügbar, auch in Dedicated Workern.
frameCountist bei Streams (ReadableStreamalsdata) anfangs unter Umständen unvollständig. Erst nachawait decoder.completedist der Wert endgültig.- Wer
selectedändert, setzt den Decoder für die neue Spur zurück. Laufendedecode()-Aufrufe können dann mit einem Fehler abgelehnt werden. - Es ist immer nur eine Spur gleichzeitig ausgewählt.
selected = falseauf der aktiven Spur hebt die Auswahl ganz auf (selectedIndexwird-1). - Die dekodierten
VideoFrame-Objekte immer mitclose()freigeben, sonst drohen Speicherlecks. - Ob ein Format unterstützt wird, lässt sich vorab mit
ImageDecoder.isTypeSupported(type)prüfen.