Einführung
Wer seine Internetseite schon einige Zeit betreibt, hat mit der Zeit einiges an Bildern angesammelt. Sofern die eigene Seite auf einem dedizierten Server gehostet ist, könnte man die Bilder alle in einem Rutsch mit einem Kommandozeilenprogramm, wie beispielsweise ImageMagic, in eine WebP-Version konvertieren. Diese müssten dann allerdings immer noch so eingebunden werden, dass nur kompatible Browser die WebP-Bilder ausgeliefert bekommen, während die älteren Browser weiterhin die PNG- oder JPEG-Bilder bekommen. Der Lösungsweg, den ich hier zeige nutzt ein PHP-Skript, dass die Konvertierung ins WebP-Format und die Auslieferung zum Zeitpunkt der Anfrage vornimmt. In einer späteren Ergänzung werden die so erzeugten WebP-Versionen dann auf dem Webserver neben den Ursprungsbildern gespeichert und direkt ausgeliefert. Voraussetzung für die Funktionsfähigkeit des Skriptes ist, dass die PHP-Extension Imagick auf dem jeweiligen Serverinstalliert sein muss. Das ist auch bei vielen Shared-Hostern, wie beispielsweise Strato und 1&1 bzw. IONOS der Fall.
Im weiteren behandle ich das PHP-Skript und die notwendigen .htaccess-Direktiven für eine WordPress-Installation. Selbstverständlich kann das hier gezeigte Skript auch mit anderen CMS oder sogar komplett Barfuß verwendet werden. In dem Fall bitte nicht vergessen die Dateipfade entsprechend anzupassen.
PHP Skript
Die Funktionsweise des PHP-Skriptes selbst ist ziemlich übersichtlich. In einer Standard-WordPress-Installation muss das PHP-Skript unter „/wp-content/uploads/webp.php“ abgelegt werden. Dorthin werden alle Anfragen zu PNG- und JPEG-Dateien innerhalb des Pfades „/wp-content/uploads/*“ von den später behandelten .htaccess-Direktiven weitergeleitet. Selbstverständlich kann dieses Skript auch mit anderen CMS oder sogar komplett Barfuß verwendet werden. In dem Fall bitte nicht vergessen die Dateipfade entsprechend anzupassen.
Das Skript erwartet als Parameter den Namen und Pfad der zu konvertierenden Datei. Dies wird mit dem GET-Parameter „file=“ erledigt. Da das Skript theoretisch von einem Besucher auch von Außen angesprochen werden könnte und es genug Menschen mit bösen Absichten gibt, muss der übergebene Parameter selbstverständlich überprüft und bereinigt werden. Sollte der Parameter fehlen oder ungültig sein, wird „400 Bad Request“ HTTP-Statuscode zurückgegeben. Sofern der Pfad gültig ist und die Datei tatsächlich existiert, wird ein Imagick-Objekt aus der angegebenen Datei erzeugt, alle Metadaten entfernt, der Qualitätsfaktor auf 75 % gesetzt und das resultierende WebP-Bild an den Browser geschickt. Die Konvertierungsfunktion ist in einem Try-Catch-Block verpackt, der etwaige Fehler mit dem gefürchteten „HTTP/1.1 500 Internal Server Error“ Statuscode quittiert.
<?php
// Sanitize and validate the file path
$filePath = isset($_GET['file']) ? $_GET['file'] : null;
if (!$filePath || !is_file($filePath)) {
header('HTTP/1.1 400 Bad Request');
echo 'Invalid or missing file parameter.';
exit;
}
try {
// Initialize Imagick
$im = new Imagick();
$im->readImage($filePath);
$im->stripImage(); // Remove unnecessary metadata
// Set image format and compression
$im->setImageFormat('webp');
// Use a constant for quality if desired
$im->setImageCompressionQuality(75);
// Output the image as a WebP format
header('Content-Type: image/webp');
echo $im->getImagesBlob();
} catch (Exception $e) {
// Handle errors gracefully
header('HTTP/1.1 500 Internal Server Error');
echo 'Error processing image: ' . $e->getMessage();
} finally {
// Clean up
if (isset($im)) {
$im->clear();
}
}
?>
.htaccess Direktiven
Die Hauptaufgabe der .htaccess-Direktiven ist es Anfragen zu Bilddateien an das PHP-Skript weiterzuleiten, sofern der Browser in der Lage ist WebP-Bilder zu verstehen. Hierzu werden ein paar Bedingungen abgearbeitet. Die erste Bedingung, die eine Anfrage erfüllen muss ist, dass der Accept-Header des Browsers „image/webp“ enthält und uns so signalisiert, dass er für WebP-Dateien empfänglich ist. An der Stelle muss ich gestehen, dass diese Bedingung in meiner eigenen Implementierung komplett fehlt: Es ist 2025, wenn irgendein Browser kein WebP versteht, hat er bei mir halt Pech gehabt. 🙂 Die zweite Bedingung ist, dass die angefragte Datei auf .jpg, .jpeg oder .png endet. Zuletzt wird noch überprüft ob die angeforderte Datei überhaupt auf dem Server existiert. Sind all diese Bedingungen erfüllt, so wird die Anfrage intern nach „/wp-content/uploads/webp.php?file=<filename>“ umgeschrieben. Hierbei ist <filename> natürlich der Name und Pfad der angeforderten Bilddatei.
RewriteBase /wp-content/uploads/
<IfModule mod_rewrite.c>
# Check if the browser accepts WEBP
RewriteCond %{HTTP_ACCEPT} image/webp
# Check if the request is for an existing image file (jpg, png, jpeg)
RewriteCond %{REQUEST_FILENAME} \.(jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} -f
# Redirect the request to the webp.php script for conversion
RewriteRule ^(.*)\.(jpe?g|png)$ /wp-content/uploads/webp.php?file=$1.$2 [NC,L]
</IfModule>
Da es sich hierbei um eine interne Weiterleitung handelt, bekommt der Besucher von diesem Prozess nichts mit. Die Datei wird über ihren gewohnten Pfad aufgerufen und scheint sich auch genau dort zu befinden. Es wird vom Webserver nur anstatt der angeforderten Datei eine WebP-Variante ausgeliefert. Dies passiert quasi unentdeckt im Hintergrund. Deshalb müssen auch die Dateipfade auf der Website, sei es direkt oder in WordPress nicht angepasst werden.
Speichern und Ausliefern von WebP-Kopien
Soweit erzeugt das PHP-Skript die konvertierten WebP-Dateien immer dann, wenn eine Bilddatei vom Besucher angefragt wird. Wenn ein Bild also 10 mal angefragt wird, durchläuft das PHP-Skript insgesamt 10 mal den gleichen Konvertierungsprozess. Dies ist zwar Platzsparend aber selbst mit ausreichend Pferdestärken auf dem Webserver immer langsamer als das direkte ausliefern von fertigen WebP-Dateien. Durch das Hinzufügen einer einzigen Codezeile speichert das PHP-Skript das konvertierte WebP-Bild neben dem Originalbild permanent auf dem Server ab. Hierfür wird der gleiche Pfad der Ursprungsdatei verwendet und lediglich die Endung „.webp“ hinzugefügt.
echo $im->getImagesBlob();
$im->writeImage($filePath.".webp");
Durch das Hinzufügen einer zweiten .htaccess-Direktive kann nun geprüft werden, ob die Webp-Version eventuell bereits existiert. Ist dies der Fall, erfolgt eine interne Weiterleitung zu der fertigen WebP-Datei. Existiert diese noch nicht, so wird eine konvertierte Version vom PHP-Skript ausgeliefert und eine Kopie für den nächsten Zugriff abgespeichert.
<IfModule mod_rewrite.c>
# Check if the browser accepts WEBP
RewriteCond %{HTTP_ACCEPT} image/webp
# Only apply the rule if the requested file is an existing jpg, png, or jpeg
RewriteCond %{REQUEST_FILENAME} \.(jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME}.webp -f
# Rewrite the request to the corresponding .webp file
RewriteRule ^(.*)\.(jpe?g|png)$ $1.$2.webp [L,T=image/webp]
</IfModule>
Die Funktionsweise dieser Lösung kann man auf meiner gesamten Website beobachten. Ruft man beispielsweise das Titelbild von diesem Beitrag direkt auf, so erhält man trotz der .png-Endung ein WebP-Bild. Ebenso kann man feststellen, dass das Bild in der unteren, rechten Ecke ein Wasserzeichen hat. In meiner Variante des Skriptes füge ich dieses allen Bilddateien automatisch hinzu. Eine solche Funktion lässt sich sehr leicht in das obige PHP-Skript mit Hilfe der Imagick-Funktionen einbauen.
Das vollständige PHP-Skript und die dazugehörige .htaccess-Datei können aus meinem WebP GitHub Repository heruntergeladen werden.
S. Westerhold: Automatische WebP-Konvertierung ohne Plugin (2025), in: Baltic Labor Blog für Hochfrequenz- und Messtechnik, ISSN (Online): 2751-806X, URL: https://baltic-labor.de/2025/01/automatische-webp-konvertierung-ohne-plugin/ (Stand: 14.01.2025).
- Automatische WebP-Konvertierung ohne Plugin - 14.01.2025
- UFW Firewall Regeln mit (dynamischen) DNS Hostnamen - 14.01.2025
- IP-Adressen hinter Proxy wiederherstellen - 26.12.2024