0Wordpress LogoGénérez et diffusez automatiquement des images avif avec wordpress

J'ai passé pas mal de temps à optimiser les performances de ce site, et dans le cadre des travaux en cours je veille sur les nouvelles technologies qui pourraient aider à améliorer la vitesse pour les visiteurs. J'ai suivi l'adoption des formats d'image de nouvelle génération pendant un certain temps et avec la prise en charge par les navigateurs Web maintenant assez répandue, il était temps de comprendre comment utiliser ces nouveaux formats dans wordpress.

Il y a plusieurs étapes requises que j'ai décomposées en titres ci-dessous

Activer la prise en charge dans nginx

La première étape consiste à activer votre serveur Web (dans mon cas nginx) reconnaître les types mime des nouveaux formats. Pour ce faire, vous devez éditer mime.types qui se trouve probablement dans /etc/nginx/mime.types. J'ai ajouté la section suivante

/ le contenu viole les règles viole les règles;
image/heif heif;
image/heic-sequence heics;
image/heif-sequence heifs;
image/avi avi;
image/avif-sequence                              avis;
image / jxl jxl;

Servir automatiquement les fichiers là où ils sont disponibles

L'étape suivante consiste à dire à nginx de servir les fichiers automatiquement chaque fois qu'ils existent (et de revenir aux anciens formats où un nouveau fichier de format n'existe pas)
Pour ce faire, modifiez d'abord le fichier de configuration principal de nginx (généralement /etc/nginx/nginx.conf) et ajoutez la section suivante à l'intérieur du http{} partie de la configuration

carte $http_accept $img_ext
{
   ~ image / jxl '.jxl';
   ~image/avif '.avif';
   ~image/webp '.webp';
   défaut      '';
}

Notez que j'essaie seulement de servir jxl (JPEG-XL) ou fichiers avif, vous pouvez ajouter plus d'options (par ordre de préférence!) si vous le souhaitez.
Suivant, vous devez ajouter ce qui suit sous le serveur{} section de la configuration nginx (qui peut être dans le fichier de configuration principal ou dans un fichier de configuration séparé selon la façon dont vous avez configuré votre structure de configuration nginx)

emplacement ~* ^.+.(png|jpg|jpeg)$
{
   add_header Varier Accepter;
   try_files $uri$img_ext $uri =404;
}

Maintenant, nginx recherchera image.jpg.jxl, puis image.jpg.avif, puis image.jpg.webp et enfin image.jpg lorsqu'il sera demandé pour image.jpg par tous les navigateurs prenant en charge les formats les plus récents.. Ensuite, nous devons les activer dans wordpress

activer les formats de nouvelle génération dans wordpress

Ajoutez le code suivant à votre functions.php (Idéalement, faites-le dans un thème enfant afin que lorsque vous mettez à jour votre thème, vos modifications ne soient pas écrasées)

/***************************************************\
* Permettre SVG support et autres formats d'image modernes *
\***************************************************/
fonction cc_mime_types( $mime )
{
   $mime['svg'] = 'image/svg+xml';
   $mime['webp'] = 'image/webp';
   $mime["Violer"] = "Image / non qualifié ';
   $mime['heif'] = 'image/génie';
   $mime['hex'] = "Image / violer les règles-séquence ';
   $mime['génisses'] = 'image/heif-séquence';
   $mime['avi'] = 'image/avi';
   $mime['avis'] = 'image/séquence-avif';
   $mime['jxl'] = 'image / jxl';
   retourner $mimes;
}
add_filter( 'upload_mimes', 'cc_mime_types' );

Notez que j'ai également activé le support pour SVG images en même temps

Vous pouvez désormais télécharger des images au format de nouvelle génération et les utiliser directement dans wordpress si vous le souhaitez., mais je ne le recommande pas car de nombreux navigateurs plus anciens ne les prennent pas encore en charge - et nous avons déjà configuré nginx pour les servir intelligemment, nous devrions donc en faire usage. Ce que nous voulons faire, c'est générer automatiquement les nouveaux formats lorsque nous téléchargeons des images (il existe déjà des plugins qui le font pour webp, mais rien qui le fasse pour jxl ou avif pour le moment).

Installer libheif

Cette étape nécessite un accès à la ligne de commande de votre hébergeur, ce qui est simple si vous exécutez un VPS, mais peut-être pas si simple si vous êtes sur un hébergement mutualisé, auquel cas vous devrez peut-être demander de l'aide à votre hébergeur
Exécutez les commandes bash suivantes (ceux-ci sont sélectionnés pour CentOS 8, d'autres distributions peuvent être un peu différentes)

dnf -y install --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm https://download1.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-8.noarch.rpm
dnf -y installer libheif

Ajouter une fonction personnalisée à wordpress functions.php pour compresser toutes les images téléchargées (et leurs miniatures) au format avi

Comme pour l'étape précédente de functions.php, je recommande de l'ajouter dans un thème enfant

/*****************************\
* Convertir png et jpg en avif *
\*****************************/
add_filter( 'wp_generate_attachment_metadata', 'jps_compress_img', 10, 2 );
fonction jps_compress_img( $métadonnées, $id_pièce jointe )
{
   // obtenir le chemin du fichier à partir de l'identifiant
   $filepath= get_attached_file($id_pièce jointe);

   // le fichier est-il au format png ou jpeg
   si(informations sur le chemin($chemin du fichier, PATHINFO_EXTENSION)=="jpg" || informations sur le chemin($chemin du fichier, PATHINFO_EXTENSION)=="jpeg" || informations sur le chemin($chemin du fichier, PATHINFO_EXTENSION)=="png")
   {
      // Le cas échéant, exécuter la compression du fichier principal en avif
      shell_exec("heif-enc $filepath -o $filepath.avif -q 50 -UNE");
      $parties = preg_split('~/(?=[^/]*$)~', $chemin du fichier);

      // Ensuite, exécutez la compression des vignettes en avif
      $thumbpaths = $métadonnées['tailles'];
      pour chaque ($chemins d'accès comme $key => $pouce)
      {
          $chemin du pouce= $pouce['déposer'];
          $thumbfullpath= $parts[0] . "/" . $chemin du pouce;
          shell_exec("heif-enc $thumbfullpath -o $thumbfullpath.avif -q 50 -UNE");
      }
   }
   // rendre ce que nous avons
   retourner $métadonnées;
}

//n'oubliez pas de supprimer les avifs si les pièces jointes sont supprimées
fonction jps_delete_avif($id_pièce jointe)
{
   $all_images= get_intermediate_image_sizes($id_pièce jointe);
   pour chaque($all_images as $each_img)
   {
      $each_img_det= wp_get_attachment_image_src($attach_id,$each_img);
      $each_img_path=ABSPATH.'wp-content'.substr($each_img_det[0],strpos($each_img_det[0],"/téléchargements/")).'.avi';
      shell_exec("rm -f $each_img_path");
   }
}
add_action( 'delete_attachment', 'jps_delete_avif' );

À l'heure actuelle, c'est tout - toutes les images que vous téléchargez seront converties en copies avif (avec les originaux conservés). Vous pouvez régénérer toutes vos images pour créer les fichiers avif en utilisant un plugin. Remarque : je n'ai pas encore configuré JPEG-La compression XL car sa prise en charge n'est pas encore disponible dans les navigateurs grand public (bien qu'il soit dans les navigateurs préliminaires, il arrive donc très bientôt).

Pendant que je couvre les formats et l'optimisation de nouvelle génération, j'ai un dernier conseil : pour compresser SVG images avec gzip (ou encore mieux zopfli et brotli). Pour ce faire, il faut une autre fonction personnalisée…

Prime: SVG compression

/*************************************************\
* Compresse SVG images plus avec brotli et zopfli *
\*************************************************/
add_filter( 'wp_generate_attachment_metadata', 'jps_compress_vectors', 10, 2 );
fonction jps_compress_vectors( $métadonnées, $id_pièce jointe )
{
    // obtenir le chemin du fichier à partir de l'identifiant
    $filepath= get_attached_file($id_pièce jointe);

    // le fichier est-il un svg
    si(informations sur le chemin($chemin du fichier, PATHINFO_EXTENSION)=="svg")
    {
       // Le cas échéant, exécuter la compression en utilisant zopfli et brotli
       shell_exec("zopfli --gzip $filepath");
       shell_exec("brotli --best --output=$filepath.br $filepath");
    }

    // rendre ce que nous avons
    renvoyer $métadonnées;
}

Notez que vous aurez besoin de gzip_static et brotli_static activés dans votre configuration nginx.

Auto-compilation pour une version plus récente

J'ai trouvé que sur Centos la dernière version de heif-enc est 1.7 qui a pas mal de bugs lors de la création d'avifs. J'ai donc choisi de compiler mon propre plus récent (1.12) construire et utiliser cela à la place. Cela était un peu compliqué car cela nécessitait le codec aom en tant que bibliothèque partagée. Pour ce faire, exécutez les commandes bash suivantes. Assurez-vous de les exécuter en tant qu'utilisateur normal, pas en tant qu'utilisateur root. Notez également que certaines de ces commandes peuvent ne pas être strictement nécessaires, il m'a fallu un certain temps pour que cela fonctionne et je viens de noter ce qui a fonctionné - je ne suis en aucun cas un expert Linux!

dnf installer x265 x265-devel svt-av1
exporter CXXFLAGS="$CXXFLAGS -fPIC"
disque ~

git clone https://aomedia.googlesource.com/aom
mkdir -p aom_build
cd aom_build
cmake ~/aom -DBUILD_SHARED_LIBS=true
Fabriquer
sudo faire installer
cp ./libaom.so.3 /usr/bin/local/libaom.so.3

disque ~
exporter PKG_CONFIG_PATH=~/aom_build/
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/aom_build/
exporter LD_LIBRARY_PATH

git clone --recurse-submodules --recursive https://github.com/struktrag/libheif.git
cd libheif
./autogen.sh
./configurer
Fabriquer
sudo faire installer

LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/bin/
exporter LD_LIBRARY_PATH

Une fois que vous avez fait cela, assurez-vous que cela fonctionne en exécutant php -a et en exécutant la commande suivante

shell_exec("/usr/local/bin/heif-enc -A");

Vous devriez obtenir une sortie complète, pas seulement un 1 erreur de ligne. En supposant que cela fonctionne, vous pouvez modifier votre functions.php afin que chacune des références shell-exec pointe vers /usr/local/bin/heif-enc au lieu de simplement heif-enc

/*****************************\
* Convertir png et jpg en avif *
\*****************************/
add_filter( 'wp_generate_attachment_metadata', 'jps_compress_img', 10, 2 );
fonction jps_compress_img( $métadonnées, $id_pièce jointe )
{
   // obtenir le chemin du fichier à partir de l'identifiant
   $filepath= get_attached_file($id_pièce jointe);

   // le fichier est-il au format png ou jpeg
   si(informations sur le chemin($chemin du fichier, PATHINFO_EXTENSION)=="jpg" || informations sur le chemin($chemin du fichier, PATHINFO_EXTENSION)=="jpeg" || informations sur le chemin($chemin du fichier, PATHINFO_EXTENSION)=="png")
   {
      // Le cas échéant, exécuter la compression du fichier principal en avif
      shell_exec("/usr/local/bin/heif-enc $filepath -o $filepath.avif -q 50 -UNE");
      $parties = preg_split('~/(?=[^/]*$)~', $chemin du fichier);

      // Ensuite, exécutez la compression des vignettes en avif
      $thumbpaths = $métadonnées['tailles'];
      pour chaque ($chemins d'accès comme $key => $pouce)
      {
          $chemin du pouce= $pouce['déposer'];
          $thumbfullpath= $parts[0] . "/" . $chemin du pouce;
          shell_exec("/usr/local/bin/heif-enc $thumbfullpath -o $thumbfullpath.avif -q 50 -UNE");
      }
   }
   // rendre ce que nous avons
   retourner $métadonnées;
}

Leave a Reply