Bildkompression, die sich an die tatsächliche Netzwerkgeschwindigkeit des Nutzers anpasst
Eine einzelne, fest gewählte AVIF-Qualitätsstufe für die gesamte Nutzerbasis ist immer ein Kompromiss zwischen zwei Extremen, die selten beide gut bedient werden. Nutzer mit schneller Standleitung bekommen unnötig komprimierte Bilder, während Nutzer im Mobilfunknetz mit aktivierter Datenspar-Funktion für eine Qualität bezahlen, die sie explizit nicht wollten. Mit Client Hints, dem Save-Data-Header und einer Anbindung an ein Bild-CDN lässt sich die Qualitätsstufe pro Anfrage dynamisch bestimmen, statt sie einmalig im Build-Prozess festzulegen.
Inhaltsverzeichnis
- 1. Warum eine feste AVIF-Qualitätsstufe für alle Nutzer suboptimal ist
- 2. Client Hints und der Save-Data-Header als Signal für Netzwerkqualität
- 3. Der Trade-off zwischen Dateigröße und wahrgenommener Bildqualität
- 4. Der Save-Data-Header im Detail: Nutzerpräferenz respektieren
- 5. Die Network Information API im Browser: effectiveType, downlink, saveData
- 6. Praktische Implementierung mit einem Bild-CDN
- 7. Serverseitige Entscheidung vs. clientseitige srcset-Varianten
- 8. Caching-Fallstricke: Vary-Header und CDN-Edge-Caching bei adaptiven Bildern
- 9. Qualität messtechnisch validieren statt nach Bauchgefühl zu entscheiden
- 10. Zusammenfassung
- 11. FAQ
1. Warum eine feste AVIF-Qualitätsstufe für alle Nutzer suboptimal ist
Wer AVIF im Build-Prozess einmalig mit einer festen Qualitätsstufe kodiert, etwa Quality 50 für alle Produktbilder, trifft eine Entscheidung, die für keinen einzelnen Nutzer wirklich optimal ist, sondern nur im Mittel ein akzeptabler Kompromiss bleibt. Ein Besucher im Büro mit Glasfaseranschluss könnte problemlos eine höhere Qualitätsstufe laden, ohne dass sich die Ladezeit spürbar verändert, bekommt aber dieselbe komprimierte Datei wie jemand, der gerade im Zug mit schwankendem LTE-Empfang unterwegs ist. Umgekehrt zahlt genau dieser mobile Nutzer trotzdem noch mehr Bytes, als er bei aktivierter Datenspar-Funktion eigentlich bereit wäre zu laden, weil die Qualitätsstufe nicht auf seine Situation reagiert.
Das eigentliche Problem ist die Annahme, Bildqualität sei eine globale Konstante, die einmal im Deployment festgelegt wird, statt eine Funktion des Kontexts, in dem ein einzelner Request stattfindet. Für einen Shop mit international gemischtem, teils stark mobil geprägtem Publikum bedeutet das konkret Umsatzverlust an zwei Stellen gleichzeitig: unnötig lange Ladezeiten für die schwächste Verbindungsgruppe und ungenutztes Qualitätspotenzial für die stärkste. Adaptive Qualität löst genau dieses Spannungsfeld auf, indem sie die Kompressionsstufe erst zur Laufzeit anhand tatsächlicher Signale bestimmt, statt sie im Vorfeld zu raten.
2. Client Hints und der Save-Data-Header als Signal für Netzwerkqualität
Client Hints sind HTTP-Header, über die der Browser dem Server strukturierte Informationen zur aktuellen Verbindung mitgeben kann, ohne dass JavaScript vorher etwas messen oder auswerten muss. Der Save-Data-Header gehört zu den sogenannten Low-Entropy Hints und wird automatisch mitgeschickt, sobald der Nutzer im Betriebssystem oder Browser eine Datenspar-Funktion aktiviert hat, ganz ohne dass die Website vorher per Accept-CH zustimmen muss. Ergänzend liefern die High-Entropy Hints Downlink und RTT eine grobe Bandbreiten- und Latenzschätzung, die der Browser selbst aus vergangenen Verbindungen ableitet und die der Server nach einmaligem Opt-in über den Response-Header Accept-CH fortlaufend erhält.
Der entscheidende Vorteil dieser Header gegenüber einer clientseitigen Messung ist, dass sie bereits bei der allerersten Anfrage vorliegen können, also bevor überhaupt JavaScript geladen und ausgeführt wurde. Für eine serverseitige oder CDN-seitige Entscheidung über die AVIF-Qualität ist das entscheidend, denn die Bildanfrage selbst ist oft die erste Anfrage nach dem initialen HTML-Dokument und muss die richtige Qualitätsstufe treffen, ohne auf eine spätere Korrektur per JavaScript warten zu können. Ein einfacher Middleware-Layer kann diese Header direkt auslesen und daraus eine Qualitätsstufe ableiten, wie das folgende Beispiel zeigt.
// Node/Express Middleware: Qualitaetsstufe aus Client Hints ableiten
function resolveAvifQuality(req) {
const saveData = req.headers['save-data'] === 'on';
const downlink = parseFloat(req.headers['downlink'] || '10'); // Mbps
const rtt = parseInt(req.headers['rtt'] || '50', 10); // ms
if (saveData) return 40; // explizite Nutzerpraeferenz zuerst
if (downlink < 1.5 || rtt > 400) return 45; // langsames Mobilfunknetz
if (downlink < 4) return 55; // mittlere Verbindung
return 72; // schnelle Verbindung, WLAN/Glasfaser
}
app.get('/img/:file.avif', (req, res) => {
const quality = resolveAvifQuality(req);
res.setHeader('Vary', 'Save-Data, Downlink, RTT');
res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');
return pipeAvifTranscode(req.params.file, quality, res);
});
3. Der Trade-off zwischen Dateigröße und wahrgenommener Bildqualität
AVIF komprimiert dank moderner Intra-Prediction und variabler Blockgrößen deutlich effizienter als ältere Formate, aber die Beziehung zwischen Qualitätsparameter und wahrgenommener Bildqualität ist nicht linear. Im oberen Bereich, etwa zwischen Quality 80 und 95, sinkt die Dateigröße kaum noch spürbar für das menschliche Auge, während im mittleren Bereich zwischen Quality 40 und 65 bereits deutliche Bytes eingespart werden, ohne dass ein durchschnittlicher Betrachter auf einem typischen Mobildisplay den Unterschied zuverlässig erkennt. Genau dieser mittlere Bereich ist deshalb der Zielkorridor für adaptive Systeme, die zwischen zwei bis drei Qualitätsstufen unterscheiden, statt einen kontinuierlichen Wertebereich anzubieten.
Wichtig ist, den Trade-off nicht pauschal für alle Bildinhalte gleich zu behandeln, denn Produktfotos mit viel Detailtextur reagieren empfindlicher auf Kompressionsartefakte als flächige Grafiken oder Icons. Ein System, das die Qualitätsstufe rein anhand der Netzwerkbedingung wählt, sollte deshalb pro Bildkategorie leicht unterschiedliche Untergrenzen definieren, etwa eine höhere Mindestqualität für Hero- und Produktbilder als für dekorative Hintergrundgrafiken, damit die Einsparung nicht ausgerechnet dort sichtbar wird, wo Bildschärfe kaufentscheidend ist.
4. Der Save-Data-Header im Detail: Nutzerpräferenz respektieren
Der Save-Data-Header unterscheidet sich konzeptionell von den bandbreitenbasierten Signalen, weil er eine explizite Entscheidung des Nutzers transportiert und nicht nur eine technische Messung. Wenn jemand die Datenspar-Funktion seines Geräts aktiviert hat, möchte er in der Regel bewusst weniger Datenvolumen verbrauchen, selbst wenn seine tatsächliche Verbindung im Moment schnell genug für hohe Qualität wäre, etwa im WLAN eines gedrosselten Tarifs. Diese Präferenz sollte deshalb in der Prioritätsreihenfolge über den gemessenen Bandbreitenwerten stehen, denn sie widerspricht sonst dem ausdrücklichen Wunsch des Nutzers, obwohl die Messung objektiv günstigere Werte liefert.
In der Praxis bedeutet das, Save-Data nicht nur für die Bildqualität, sondern konsistent für alle datenintensiven Entscheidungen einer Seite auszuwerten, etwa auch für das Nachladen von Video-Vorschauen oder hochauflösenden Retina-Varianten. Wird Save-Data ignoriert und stattdessen ausschließlich der gemessene Downlink-Wert herangezogen, verliert der Header seinen eigentlichen Zweck, nämlich Nutzern in Regionen mit teurem oder limitiertem Datenvolumen eine verlässliche Kontrolle über ihren Verbrauch zu geben, unabhängig davon, wie schnell ihre Verbindung technisch gemessen wird.
5. Die Network Information API im Browser: effectiveType, downlink, saveData
Neben den HTTP-Headern steht im Browser zusätzlich die navigator.connection-Schnittstelle zur Verfügung, die dieselben Signale clientseitig als JavaScript-Objekt bereitstellt, ergänzt um effectiveType, eine grobe Kategorisierung in slow-2g, 2g, 3g oder 4g. Diese API ist besonders nützlich, wenn die Qualitätsentscheidung nicht beim initialen Serverrequest, sondern erst beim Nachladen weiterer Bilder während des Scrollens getroffen werden muss, etwa in einer Lazy-Loading-Galerie, die neue Bild-URLs erst beim Erreichen des Viewports zusammensetzt.
Die Einschränkung dieser API ist ihre lücken hafte Browser-Unterstützung, denn Safari implementiert navigator.connection bis heute nicht, während Chromium-basierte Browser die Werte zuverlässig liefern. Ein robustes System darf sich deshalb nicht ausschließlich auf die clientseitige API verlassen, sondern sollte sie als Ergänzung zu den serverseitig ausgewerteten Client Hints behandeln, damit auch Safari-Nutzer zumindest über die im Request enthaltenen Header eine sinnvolle Qualitätsstufe erhalten, selbst wenn die feingranulare clientseitige Nachsteuerung dort fehlt.
6. Praktische Implementierung mit einem Bild-CDN
In der Praxis übernimmt selten die eigene Applikation die AVIF-Transkodierung, sondern ein spezialisiertes Bild-CDN, das Original-Assets einmalig speichert und Varianten erst bei der ersten Anfrage generiert und danach am Edge cached. Die meisten dieser Dienste akzeptieren Qualitäts- und Formatparameter direkt in der URL, sodass die Applikation lediglich die berechnete Qualitätsstufe als Parameter anhängen muss, ohne selbst Kodierungslogik zu implementieren oder Rechenlast für die Bildverarbeitung zu tragen. Die Auswertung der Client Hints findet dabei entweder in einer eigenen Middleware vor der Bildanfrage statt, die die URL entsprechend zusammensetzt, oder direkt in einer Edge-Function des CDN-Anbieters, die Zugriff auf dieselben Request-Header hat.
Wichtig ist, die Anzahl der resultierenden URL-Varianten bewusst klein zu halten, etwa drei bis vier feste Qualitätsstufen statt eines kontinuierlichen Wertebereichs, denn jede zusätzliche Variante verwässert die Trefferquote im Edge-Cache des CDN. Eine Konfiguration mit den Stufen 40, 55 und 72, wie im vorherigen Codebeispiel gezeigt, deckt die relevanten Netzwerksituationen ab und sorgt gleichzeitig dafür, dass viele Nutzer mit ähnlicher Verbindungsqualität dieselbe bereits generierte und gecachte Variante treffen, statt bei jeder Anfrage eine neue Transkodierung auszulösen.
7. Serverseitige Entscheidung vs. clientseitige srcset-Varianten
Alternativ zur serverseitigen Qualitätsentscheidung lässt sich adaptive Qualität auch über ein erweitertes srcset mit mehreren vorab generierten Qualitätsstufen abbilden, wobei der Browser anhand eigener Heuristiken zwischen den Kandidaten wählt. Dieser Ansatz hat den Vorteil, ganz ohne serverseitige Header-Auswertung auszukommen, aber den Nachteil, dass die Browser-Heuristik primär auf Displaygröße und Device-Pixel-Ratio optimiert ist und Bandbreitensignale nur eingeschränkt einbezieht, sodass die eigentliche Netzwerkadaption schwächer ausfällt als bei einer gezielten serverseitigen Entscheidung.
In der Praxis bewährt sich eine Kombination beider Ansätze: die serverseitige Qualitätsstufe bestimmt, welche Kompressionsstärke innerhalb einer bestimmten Größenvariante verwendet wird, während srcset weiterhin für die Größenauswahl je nach Viewport zuständig bleibt. So werden zwei unabhängige Dimensionen, Bildgröße und Kompressionsqualität, jeweils von dem Mechanismus gesteuert, der die dafür nötigen Signale am zuverlässigsten zur Verfügung hat.
8. Caching-Fallstricke: Vary-Header und CDN-Edge-Caching bei adaptiven Bildern
Sobald die Antwort von Request-Headern abhängt, muss ein korrekt gesetzter Vary-Header sicherstellen, dass ein Edge-Cache oder ein zwischengeschalteter Proxy nicht versehentlich die für eine schnelle Verbindung generierte Variante an einen Nutzer mit aktivem Save-Data ausliefert. Gleichzeitig ist genau dieser Vary-Header eine häufige Ursache für eine schlechte Cache-Trefferquote, denn jede zusätzliche Kombination aus Header-Werten erzeugt potenziell einen eigenen Cache-Eintrag, und bei kontinuierlichen Werten wie einem exakten Downlink-Messwert wäre die Anzahl möglicher Kombinationen praktisch unbegrenzt.
Die Lösung liegt darin, die Rohwerte der Client Hints niemals direkt als Cache-Key zu verwenden, sondern sie vor der Cache-Entscheidung auf die wenigen definierten Qualitätsstufen zu quantisieren, wie es die Middleware im obigen Beispiel bereits tut. Der Cache-Key basiert dann nicht auf dem exakten Downlink-Wert, sondern auf der daraus abgeleiteten Qualitätsstufe, wodurch die Anzahl der Varianten pro Bild auf die bewusst gewählte, kleine Menge begrenzt bleibt und die Trefferquote im Edge-Cache hoch bleibt, obwohl die Antwort weiterhin kontextabhängig ist.
9. Qualität messtechnisch validieren statt nach Bauchgefühl zu entscheiden
Welche Qualitätsstufe für welche Netzwerksituation noch akzeptabel ist, sollte nicht durch subjektives Betrachten einzelner Beispielbilder festgelegt werden, sondern durch objektive Metriken wie SSIM, DSSIM oder Butteraugli, die den wahrgenommenen Qualitätsverlust gegenüber dem Original quantifizieren. Diese Metriken lassen sich in die Build-Pipeline integrieren, um bei jeder neuen Qualitätsstufe automatisch zu prüfen, ob der Verlust innerhalb eines vorher definierten Toleranzbereichs bleibt, statt sich auf eine einmalige, manuelle Einschätzung zu verlassen, die bei anderen Bildmotiven möglicherweise nicht mehr zutrifft.
Ergänzend lohnt sich ein Blick auf reale Nutzerdaten aus dem Real User Monitoring, um zu prüfen, ob die gewählten Bandbreiten-Schwellenwerte tatsächlich zu den in der eigenen Nutzerbasis vorkommenden Verbindungstypen passen. Ein Shop mit überwiegend europäischem Festnetz-Publikum braucht andere Schwellenwerte als einer mit hohem Anteil an mobilen Nutzern in Regionen mit schwacher Netzabdeckung, und nur eine Auswertung der eigenen Daten zeigt zuverlässig, wo die drei bis vier Qualitätsstufen sinnvoll gesetzt werden sollten.
| Signal | Quelle | Wertebereich | Konsequenz für die Qualitätsstufe |
|---|---|---|---|
| Save-Data | HTTP-Header, Low-Entropy Client Hint | on / nicht gesetzt | Niedrigste Qualitätsstufe erzwingen, Nutzerpräferenz hat Vorrang |
| Downlink | HTTP-Header bzw. navigator.connection.downlink | Mbps-Schätzwert, z.B. 0.4 bis 10+ | Stufenweise Qualität nach Bandbreiten-Tier wählen |
| RTT | HTTP-Header bzw. navigator.connection.rtt | Millisekunden | Hohe Latenz zusätzlich zur Bandbreite als Signal für mobile Netze werten |
| effectiveType | navigator.connection.effectiveType, nur clientseitig | slow-2g / 2g / 3g / 4g | Grobe Kategorie als Fallback, wenn Downlink fehlt |
| Viewport-Breite | Sec-CH-Viewport-Width bzw. clientseitig gemessen | Pixelwert | Kombiniert mit Qualität: Größe und Kompression gemeinsam anpassen |
Mironsoft
Web Performance, Core Web Vitals und Ladezeit-Optimierung
Ladezeiten, die Nutzer nicht abspringen lassen, bevor die Seite überhaupt sichtbar ist?
Wir prüfen bestehende Webseiten auf langsame Core Web Vitals, aufgeblähte JavaScript-Bundles und ungenutzte Render-Blocker und bauen daraus eine Performance-Grundlage, die messbar bleibt statt nur einmalig gut auszusehen.
Performance-Audit
Core Web Vitals, Ladewasserfall und Render-Blocker systematisch messen und beheben.
Bundle-Optimierung
JavaScript- und CSS-Bundle-Größe sowie Code-Splitting gezielt reduzieren.
Monitoring-Aufbau
Kontinuierliches Performance-Monitoring statt einmaliger Momentaufnahme etablieren.
10. Zusammenfassung
AVIF adaptive Qualität: Das Wichtigste auf einen Blick
Kernidee
Die AVIF-Qualitätsstufe wird pro Request dynamisch bestimmt, nicht einmalig im Build-Prozess festgelegt.
Wichtigstes Signal
Save-Data hat Vorrang vor gemessener Bandbreite, weil es eine explizite Nutzerpräferenz transportiert.
Umsetzung
Ein Bild-CDN generiert Varianten anhand weniger, fest definierter Qualitätsstufen statt eines kontinuierlichen Werts.
Caching
Rohwerte der Client Hints vor der Cache-Entscheidung auf wenige Stufen quantisieren, sonst sinkt die Trefferquote.