WebP en AVIF instellen
Eerst nakijken wat je server kan
In het onderdeel ‘Afbeeldingen’ staat de kaart ‘Mogelijkheden van deze server’. Die laat niet zien wat er op papier staat, maar wat er aan de draaiende PHP is gemeten: GD-beeldbibliotheek inclusief versie, JPEG lezen, PNG lezen, WebP lezen, WebP schrijven, AVIF schrijven. Er wordt daarbij dubbel gevraagd — de functie moet bestaan en het formaat moet in imagetypes() staan. Dat is belangrijk, omdat sommige hosters GD zonder WebP of AVIF bouwen: imagewebp() is dan aanwezig en faalt pas bij de aanroep.
Ontbreekt een formaat, dan blijft de bijbehorende schakelaar wel zichtbaar, maar is hij uitgeschakeld en draagt hij de reden. Voor WebP luidt die: GD moet met libwebp gebouwd zijn. Voor AVIF: PHP 8.1 of nieuwer met libavif. Beide zijn een zaak van je hoster. Een omweg via de AJAX-aanroep helpt niet — de server weigert het inschakelen van een niet-beschikbaar formaat uitdrukkelijk.
De regel ‘Imagick’ is puur informatief. Deze module gebruikt Imagick niet; staat daar ‘niet aanwezig’, dan mis je niets.
Inschakelen en de drie getallen instellen
Er zijn drie schakelaars en drie getalvelden. ‘WebP aanmaken’ en ‘AVIF aanmaken’ staan standaard uit, ‘Via <picture> leveren’ staat aan. Die scheiding is opzet: je kunt de bestanden eerst laten ontstaan en de levering later bijschakelen. Omgekeerd geldt: schakel je de levering uit, dan ontstaan de bestanden nog steeds, maar gaat er naar de bezoekers ongewijzigde markup.
De WebP-kwaliteit staat op 82, de AVIF-kwaliteit op 50. Beide velden nemen waarden van 30 tot 100 aan, alles daarboven of daaronder wordt tot dat bereik teruggebracht. De verschillende standaardwaarden zijn geen vergissing: AVIF meet anders dan JPEG, 50 ziet er daar al heel netjes uit. Boven de 90 groeit bij WebP het bestand sneller dan de zichtbare winst.
De bovengrens in megapixels staat op 40 en neemt waarden van 4 tot 400 aan. Ze beschermt tegen de geheugenlimiet: een foto van 6000 × 4000 neemt bij het decoderen ongeveer 96 MB in beslag, ongeacht hoe groot het bestand ervan is. Bovendien rekent Kakapo vóór elke decodering tegen het werkelijk nog vrije geheugen en slaat over, in plaats van de upload op de limiet te laten sneuvelen.
Wijzig je een van de drie schakelaars, dan wordt de opgeslagen paginacache weggegooid. Kwaliteit en megapixelgrens laten hem staan — die werken pas bij de volgende upload en maken geen al opgeslagen pagina onjuist.
Wat er bij het uploaden gebeurt
De omzetting loopt aan het eind van de upload, zodra WordPress alle afbeeldingsmaten heeft aangemaakt. Bewerkt worden het bestand uit de metadata en elke aangemaakte maat — niet het door de core bewaarde origineel, dat toch nooit wordt geleverd.
Elke afgeleide ligt als begeleidend bestand naast zijn bronbestand en draagt diens volledige naam plus extensie: van bild.jpg wordt bild.jpg.webp, niet bild.webp. Reden: in dezelfde map mogen bild.jpg en bild.png naast elkaar liggen; bij het simpelweg vervangen van de extensie zou de ene afgeleide de andere overschrijven. Ligt er op de doellocatie al iets, dan wordt dat niet aangeraakt.
Er wordt eerst naar een hulpbestand geschreven met een procesnummer en een toevalsgetal in de naam. Pas wanneer het nagemeten kleiner is dan het bronbestand, schuift het via rename op zijn plek. Is het groter of even groot, dan wordt het verwijderd en blijft het bij het bronbestand. Een afgebroken verwerking laat daarom nooit een te grote afgeleide achter.
De upload heeft een tijdsbudget van 12 seconden. AVIF is bij het aanmaken vele malen trager dan WebP, en zes maten maal twee formaten lopen anders in de uitvoeringstijd van de webserver — de beheerder zou een afgebroken upload zien. Wat er niet meer in past, haalt een eenmalige naloop op: die wordt 30 seconden later ingepland en heeft dan 90 seconden de tijd. Zowel het afgehandelde als het overgeslagene wordt bij de bijlage genoteerd, zodat dezelfde poging niet bij elke nieuwe aanmaak wordt herhaald.
Bij JPEG’s wordt een EXIF-draaiing nagetrokken, omdat WebP en AVIF uit GD die informatie niet meedragen. Bij PNG-bronbestanden probeert Kakapo WebP eerst verliesvrij — logo’s, illustraties en schermafbeeldingen worden zo vaak kleiner zonder dat randen uitrafelen. Transparantie blijft in beide doelformaten behouden.
Hoe er geleverd wordt
Kakapo vat de <img> in een <picture> en zet daar AVIF- en WebP-bronnen voor, AVIF als eerste — de browser neemt de eerste bron die hij begrijpt. De <picture> krijgt display:contents, zodat hij in flex- en grid-lay-outs van je thema geen extra kader in de opstelling schuift.
Bewust gekozen tegen het alternatief via .htaccess: content-negotiation vereist Apache-regels, werkt op nginx helemaal niet en botst met CDN-caches die de Accept-header niet variëren. Bij <picture> beslist de browser, zonder één regel serverconfiguratie.
Ingegrepen wordt op berichtinhoud en uitgelichte afbeeldingen, met prioriteit 22 — na de Lazy-Load (20), vóór het herschrijven voor het CDN (25), zodat ook de nieuw ontstane bronnen via het CDN lopen. Al bestaande <picture>-blokken blijven onaangeroerd, net als afbeeldingen van vreemde hosts en alles buiten de uploadsmap.
Eén regel is het waard om te kennen: een formaat wordt alleen aangeboden als de grootste versie in de srcset als afgeleide aanwezig is. Ontbreekt een middelgrote of kleine, dan grijpt de browser naar de eerstvolgende grotere — een paar kilobyte meer, maar nooit een onscherpe afbeelding. Ontbrak de grootste, dan zou een breed scherm niet meer op de volle resolutie kunnen komen; precies dat geval wordt uitgesloten.
Als er niets ontstaat: de redenen lezen
De kaart ‘Aangemaakte bestanden & echte besparing’ toont per formaat het aantal bestanden, de som van de bronbestanden, de som van de afgeleiden en het verschil. Elk getal komt uit de vergelijking van twee werkelijke bestandsgroottes op het moment van aanmaken — niets is geschat of geëxtrapoleerd. ‘Bronbestanden’ is daarbij alleen de som van de bestanden waarvoor een afgeleide is ontstaan, niet je hele mediabibliotheek.
Daaronder staat wat niet is omgezet, met reden. De belangrijkste:
‘Resultaat was groter dan het bronbestand’ — geen fout. Bij heel kleine miniaturen gebeurt dat met AVIF regelmatig; het bronbestand blijft en de overige maten krijgen hun afgeleide toch.
‘Niet schrijfbaar’ — controleer de rechten in de uploadsmap. Dat is de enige reden die werkelijk om jou vraagt.
‘Op de doellocatie lag al een bestand’ — dat is niet overschreven. Meestal komt het uit de batchverwerking over de bestaande mediabibliotheek en is het al precies dat wat hier had moeten ontstaan.
‘Paste niet in het geheugen’ — verhoog de megapixelgrens of de PHP-geheugenlimiet.
‘Niet leesbaar’ — defect bestand, CMYK-JPEG of een exotische variant. ‘Geen JPEG/PNG/WebP’ — GIF-animaties en PDF’s worden bewust niet aangeraakt.
Staat de kaart leeg, schakel dan WebP in en upload een afbeelding. Afbeeldingen die al in de mediabibliotheek staan, bereik je daar niet mee, maar via de batchverwerking verderop op dezelfde pagina.