Cela fait une paire de fois que les images au format AVIF ne s’affichent pas sur SkyMinds et aujourd’hui, on règle le problème une bonne fois pour toute.
Concrètement, à chaque fois que j’uploade une image dans la bibliothèque de média de WordPress, plusieurs images sont créés: les miniatures bien sûr mais aussi un jeu d’images au format WEBP et au format AVIF. Tout se fait de manière automatique avec ShortPixel lors de l’upload.
Or, dernièrement certaines images ne s’affichent plus. Si on retire la source AVIF du DOM du document, le WEBP s’affiche bien, tout comme l’image originale en PNG ou JPG. C’est donc au niveau de la compression AVIF que cela coince.
Procédure de debug
Configuration NginX
Si vous vous souvenez bien, j’ai dans ma configuration NginX des directives pour donner la précédence aux formats AVIF et WEBP sur toutes mes images. Cela permet de servir en priorité les fichiers images aux formats les plus récents, avec un fallback sur les formats plus anciens (JPG, PNG notamment).
J’ai passé la configuration au peigne fin et il n’y a pas de problème à ce niveau. Les fichiers AVIF sont bien servis, le problème se trouve plus au niveau de l’encodage des fichiers.
Tester les images affectées
Lorsque je visionne un article avec une image affectée par le bug, elle ne saffiche pas mais apparait comme une image cassée. Lorsque l’on ouvre l’image dans un nouvel onglet, on obtient l’erreur suivante: “the image cannot be displayed because it contains errors“.
Je ne connais pas le nom des images affectées ni leur nombre (cela inclut aussi les miniatures) donc le plus simple est de dresser la liste des fichiers AVIF sur le site. Ensuite, je veux inspecter chaque image pour vérifier qu’elles possèdent bien les entêtes et bits nécessaires à leur bon affichage.
Commençons par installer les outils nécessaires pour examiner les fichiers AVIF:
apt install libavif-bin libavif13
On lance un test sur un fichier problématique:
avifdec /home/www/example/wp-content/uploads/2021/05/the-handmaids-tale-june-nick.avif /dev/null
Code language: JavaScript (javascript)
et voici le résultat:
Decoding with AV1 codec 'dav1d' (1 worker thread), please wait...
ERROR: Failed to parse image: BMFF parsing failed
Diagnostics: * Box[meta] does not have a Box[hdlr] as its first child box
Code language: JavaScript (javascript)
L’erreur (“ERROR: Failed to parse image: BMFF parsing failed”), suggère que le fichier est en effet soit corrompu, soit incompatible donc nous allons le recréer.
Un script bash pour recréer tous les fichiers AVIF corrompus
Il est évident que nous n’allons pas tester tous les fichiers un par un. Maintenant que nous avons pu tester un fichier, nous allons créer une boucle pour tester tous les fichiers qui ont été uploadés sur le site : si le fichier est corrompu, nous allons le recréer, sinon on passe au suivant.
Voici le script que j’ai écrit pour récréer les fichiers AVIF:
nano check-avif.sh
Code language: CSS (css)
#!/bin/bash
# Script Name: Recreate corrupted AVIF images
# Script URI : https://www.skyminds.net/recreer-fichiers-avif-corrompus/
# Author: Matt Biscay
# Author URL: https://www.skyminds.net
# Directory to search for AVIF files
SEARCH_DIR="/home/www/example/public_html/wp-content/uploads"
# Dry run mode flag
DRY_RUN=0
# Check for --dry-run option
if [ "$1" == "--dry-run" ]; then
DRY_RUN=1
echo "Dry run mode enabled. No files will be modified."
fi
# Function to check if AVIF file is corrupted
check_avif() {
local output
output=$(avifdec "$1" /dev/null 2>&1)
local status=$?
if [ $status -ne 0 ]; then
if echo "$output" | grep -q -E "ERROR: Failed to decode image|Failed to read image|ERROR: Failed to parse image"; then
return 1
fi
fi
return 0
}
# Function to convert other image formats to AVIF
convert_to_avif() {
convert "$1" "$2"
}
# Loop through all AVIF files in the directory
find "$SEARCH_DIR" -type f -iname "*.avif" | while read -r avif_file; do
# echo "Checking file: $avif_file"
# Check if AVIF file is corrupted
if ! check_avif "$avif_file"; then
echo -e "\033[31mCorrupted AVIF file found: $avif_file\033[0m" # Marking in red
# Try to find the original image file
original_file=$(echo "$avif_file" | sed -e "s/\.avif$//")
for ext in png jpg jpeg webp; do
if [ -f "${original_file}.${ext}" ]; then
original_file="${original_file}.${ext}"
break
fi
done
# Check if original file exists
if [ ! -f "$original_file" ]; then
echo "Original file for $avif_file not found. Skipping."
continue
fi
# Recreate the AVIF file
if [ $DRY_RUN -eq 0 ]; then
echo "Recreating AVIF file from $original_file"
convert_to_avif "$original_file" "$avif_file"
else
echo "Would recreate AVIF file from $original_file (dry run)"
fi
# else
# echo "File is valid: $avif_file"
fi
done
Code language: PHP (php)
Fonctionnement du script
Contexte et configuration initiale
Le script commence par définir un terrain de jeu : le répertoire de recherche. Spécifié comme "/home/www/example/public_html/wp-content/uploads"
, ce chemin représente le lieu où le script va chercher activement les fichiers AVIF à examiner. Il vous suffit d’éditer la variable SEARCH_DIR pour refléter le chemin de vos fichiers.
Le mode Dry Run : une précaution nécessaire
Avant de plonger dans la réparation des fichiers, le script introduit une option de sécurité : le mode Dry Run. Ce mode, activé par l’option --dry-run
, permet au script de s’exécuter sans apporter de modifications réelles aux fichiers. C’est un filet de sécurité pour les utilisateurs qui souhaitent voir les opérations prévues du script sans affecter leurs données réelles.
Identification des fichiers corrompus
Au cœur du script se trouve la fonction check_avif
, une méthode astucieuse pour déterminer si un fichier AVIF est corrompu. En utilisant avifdec
, le script tente de décoder chaque fichier AVIF vers une destination neutre (/dev/null
). Si cette opération échoue avec des messages d’erreur spécifiques, le script reconnaît le fichier comme corrompu. Cette étape est cruciale, car elle assure que seuls les fichiers réellement endommagés sont pris en compte pour la réparation.
Conversion et réparation des fichiers
Pour les fichiers identifiés comme corrompus, le script entreprend une quête pour trouver leur version originale. En retirant l’extension .avif
et en cherchant parmi d’autres formats populaires (PNG, JPG, JPEG, WEBP), le script essaie de localiser la source d’origine de l’image corrompue.
Une fois cette image trouvée, le script utilise la fonction convert_to_avif
pour recréer le fichier AVIF. Cette méthode garantit que les images sont restaurées à leur état d’origine, préservant ainsi la qualité et l’intégrité des données visuelles.
On peut d’abord lancer le script en mode --dry-run
, pour avoir un aperçu des éventuelles recréation de fichiers:
./check-avif.sh --dry-run
Une fois que les tests ont été effectués et que vous avez trouvé des fichiers AVIF corrompus, il ne reste plus qu’à les corriger et les rendre de nouveau opérationnels et visibles dans tous les navigateurs:
./check-avif.sh
Voilà, un petit script à garder dans sa trousse à outils, cela peut toujours servir!
Vous voulez un site WordPress ou WooCommerce qui soit à la fois rapide et performant? Vous êtes au bon endroit.