260827-Tofs à compresse sur le PC Windows
Procédure Photos-Caesium — compression de photos par dépôt de dossier
Mise en place le 2026-08-27 sur le poste Windows julie. Copie de référence de cette page : Jux-scripts/Photos-Caesium/doc_bookstack_284.md.
En bref
On dépose des photos dans un dossier, on les récupère compressées dans un autre. Rien à lancer, rien à paramétrer au coup par coup. C'est le principe de la procédure Komga-PDF (page 220) appliqué aux images.
Gain mesuré sur 71 photos de téléphone : 251,1 Mo → 90,4 Mo, soit -64 %, en 22 secondes. EXIF, GPS, dimensions et dates de prise de vue intégralement conservés.
| Dépôt | D:\Procedures photos\Tofs a compresse\ |
| Résultat | D:\Procedures photos\Tofs-compressed\ |
| Moteur | caesiumclt v1.4.0 (binaire Rust, local) |
| Script | Jux-scripts/Photos-Caesium/compress_photos.py |
| Machine | PC julie uniquement — le VPS n'intervient pas |
Pourquoi 100 % local, contrairement à Komga-PDF
Komga-PDF passe par le VPS. Photos-Caesium non, et c'est délibéré. Trois raisons, par ordre d'importance :
1. Il n'y a pas de service à réutiliser. Komga-PDF s'appuie sur StirlingPDF, déjà déployé sur le VPS et qui expose compress-pdf en HTTP. Pour les images il n'existe aucun équivalent : Caesium est un binaire en ligne de commande, pas un service. L'héberger sur le VPS n'apporterait donc pas une API mais un simple exécutable — qu'on peut tout aussi bien poser sur le PC.
2. Le CPU. La compression JPEG (mozjpeg) est du calcul pur, massivement parallélisable. Le Ryzen 5 2600X offre 12 threads et ne fait généralement rien ; le VPS fait tourner une trentaine de containers, avec un swap déjà largement occupé et un antécédent de saturation disque à 100 % (24/06/2026). Les 71 photos de la mesure de référence ont été traitées en 22 secondes sur le PC.
3. Le transfert. Les photos sont déjà sur le PC ou le NAS. Les envoyer au VPS pour les faire revenir consommerait deux fois le débit montant de la Livebox sans contrepartie.
Le seul cas qui justifierait le VPS serait de pouvoir déposer depuis le téléphone pendant que le PC est éteint — c'est exactement ce qui avait fait choisir le VPS pour Komga-PDF. Le portage serait trivial : le dépôt caesium-clt publie un binaire linux-musl statique qui tournerait sans rien installer, et le script Python n'utilise que la bibliothèque standard. À reconsidérer si le besoin apparaît.
Pourquoi les dossiers sont hors de l'arbre Syncthing
Les deux dossiers avaient d'abord été créés dans D:\Syncthing\, puis déplacés vers D:\Procedures photos\. Il ne faut pas les y remettre.
Il n'existe qu'un seul dossier Syncthing dans tout le maillage (afltj-njyuy), partagé avec 7 appareils dont le Xiaomi et la tablette SM-T720. Tout ce qui tombe dedans se réplique partout. C'est supportable pour Komga-PDF — un PDF de 130 Mo de temps en temps — mais un vidage de carte SD à plusieurs gigaoctets descendrait intégralement sur les téléphones, avant même que la compression ait commencé.
Conséquence assumée : le dépôt à distance n'est pas possible. On dépose depuis le PC.
Arborescence
D:\Procedures photos\
├── Tofs a compresse\ ← dépôt (sous-dossiers acceptés)
├── Tofs-compressed\ ← résultat, même arborescence
├── originaux-traites\ ← originaux après traitement (créé au besoin)
├── non-traites\ ← formats non pris en charge (créé au besoin)
├── echecs\ ← abandons après 3 tentatives (créé au besoin)
├── bin\caesiumclt.exe
├── logs\photos_compress.log
├── config.json
├── Compresser maintenant.cmd
├── Simuler le gain.cmd
└── Surveillance (fenetre visible).cmd
Le script lui-même vit dans Jux-scripts/Photos-Caesium/, donc dans l'arbre Syncthing : il est versionné et disponible sur toutes les machines. Seules les données restent locales.
Usage
Au quotidien
Déposer les photos dans Tofs a compresse\, puis double-cliquer Compresser maintenant.cmd. Les fichiers compressés apparaissent dans Tofs-compressed\ avec la même arborescence — un album déposé revient en album.
Simuler le gain.cmd compresse pour de vrai en zone tampon, annonce le gain obtenu, puis jette le résultat sans rien déplacer. Utile pour arbitrer entre deux profils avant de s'engager.
Surveillance (fenetre visible).cmd laisse tourner la boucle avec la console à l'écran.
En ligne de commande
py -3.12 compress_photos.py --une-fois
py -3.12 compress_photos.py --simulation
py -3.12 compress_photos.py --profil sans-perte --une-fois
py -3.12 compress_photos.py --profils
py -3.12 compress_photos.py # surveillance continue
Surveillance automatique à l'ouverture de session — en place depuis le 2026-08-27
Tâche planifiée Photos-Caesium, créée par la commande suivante dans une console PowerShell de Julien :
schtasks /Create /TN "Photos-Caesium" /TR '"C:\Users\julie\AppData\Local\Programs\Python\Python312\pythonw.exe" "D:\Syncthing\Jux_univers\Jux-scripts\Photos-Caesium\compress_photos.py"' /SC ONLOGON /RL LIMITED /F
Vérification : schtasks /Query /TN "Photos-Caesium" /V /FO LIST, ou taskschd.msc. Retrait : schtasks /Delete /TN "Photos-Caesium" /F.
pythonw.exe et non python.exe, sinon une fenêtre de console s'ouvre à chaque ouverture de session.
Cette tâche doit être créée par Julien, pas depuis une session Claude Code — piège MSIX, cf. page 282.
Profils de compression
Définis dans config.json, modifiables sans toucher au code. --profil <nom> permet de surcharger ponctuellement.
| Profil | Options Caesium | Gain sur photos de téléphone |
|---|---|---|
q80 (actif par défaut) |
-q 80 |
-59 à -72 % |
q90 |
-q 90 |
~-45 % |
sans-perte |
--lossless |
-23 % |
web-3000px |
-q 80 --long-edge 3000 --no-upscale |
~-85 % |
Options appliquées à tous les profils (options_communes) : -e --keep-dates --min-savings 1%.
Le point important : « sans altérer la qualité » coûte les deux tiers du gain
C'était la demande initiale, et elle mérite d'être précisée, parce que les deux modes de Caesium n'ont rien de comparable en rendement :
--losslessne touche pas un seul pixel. Il reconstruit les tables de Huffman et réoptimise le conteneur. Sur les mêmes 71 photos : -23 %.-q 80ré-encode l'image. La différence est invisible à l'œil sur une photographie, et c'est le réglage par défaut de l'interface graphique Caesium — celui qui donne l'impression que « Caesium compresse admirablement bien ». Sur les mêmes fichiers : -64 %.
D'où le choix de q80 par défaut. Pour des originaux irremplaçables, basculer sur sans-perte dans config.json, ou traiter ce lot-là avec --profil sans-perte.
Mesure de référence — 2026-08-27
71 photos de téléphone (lot « Ligurie 2026 »), Ryzen 5 2600X, --threads 0 (12 threads) :
| Taille | Durée | |
|---|---|---|
| Originaux | 251,1 Mo | — |
q80 |
90,4 Mo (-64,0 %) | 22 s |
sans-perte (sur un sous-ensemble) |
-22,8 % | — |
Soit environ 12 Mo/s de débit de traitement. Un vidage de carte SD de 8 Go se traite donc en une dizaine de minutes.
EXIF, GPS et dates — vérifiés
-e (garder l'EXIF) n'est PAS le comportement par défaut de Caesium. Sans cette option, dates de prise de vue et coordonnées GPS sont purement supprimées — ce qui serait fâcheux avant tout versement dans Immich. L'option est donc dans options_communes : ne pas la retirer.
Contrôle effectué le 2026-08-27 sur trois photos, en comparant original et compressé :
| Fichier | Taille | Dimensions | Bloc EXIF | GPS | DateTimeOriginal |
|---|---|---|---|---|---|
| IMG_20260805_110420 orig. | 3 303 207 o | 1970×2997 | 1 819 o | oui | 2026:08:05 10:31:44 |
| IMG_20260805_110420 q80 | 669 121 o | 1970×2997 | 1 819 o | oui | identique |
| IMG_20260814_103531 orig. | 2 647 488 o | 4096×3072 | 52 665 o | oui | 2026:08:14 10:35:31 |
| IMG_20260814_103531 q80 | 952 436 o | 4096×3072 | 52 665 o | oui | identique |
| IMG_20260815_161301 orig. | 2 145 571 o | 3072×4096 | 52 597 o | oui | 2026:08:15 16:13:01 |
| IMG_20260815_161301 q80 | 649 956 o | 3072×4096 | 52 597 o | oui | identique |
Bloc EXIF identique à l'octet près, IFD GPS présent, dimensions inchangées, --keep-dates préservant par ailleurs les horodatages du fichier lui-même.
Formats
Pris en charge : JPEG, PNG, WebP, GIF, TIFF.
Non pris en charge : HEIC (iPhone) et RAW. Ces fichiers sont déplacés dans non-traites\ — jamais supprimés — avec une ligne au journal. Caesium ne sait pas les lire ; si le besoin HEIC se présente, il faudra une étape de conversion en amont.
Fonctionnement interne
- Sondage toutes les 15 s du dossier de dépôt. Il n'y a pas d'
inotifysous Windows : le sondage est la seule voie, et c'est de toute façon la partie robuste du dispositif (voir le correctif Komga-PDF du 23/08). - Traitement déclenché après 20 s sans le moindre changement dans l'arborescence — taille ou date d'un fichier quelconque. C'est ce qui évite d'attraper un fichier en cours de copie. Plafond de sécurité à 15 min, au-delà duquel on traite quand même.
- Le lot entier part en un seul appel à
caesiumclt, qui parallélise sur tous les cœurs (--threads 0). - Écriture d'abord dans
.staging, puis déplacement vers la sortie. Jamais de fichier partiel visible dansTofs-compressed\. - Structure préservée (
-R -S). - Collision de nom en sortie : suffixe
(2),(3)… Rien n'est jamais écrasé. - Gain inférieur à 1 % (
--min-savings 1%) : Caesium n'écrit rien, et le script recopie l'original tel quel en sortie. Un fichier déposé ressort toujours. - Échec : 3 tentatives (clé taille + date de modification, mémorisée dans
.etat.json), puis mise à l'écart dansechecs\. - Journal persistant
logs\photos_compress.log, rotation à 5 Mo. - Sort des originaux —
config.json, cléapres_traitement:deplacer(défaut, versoriginaux-traites\),supprimer, oulaisser.
Les points 2, 4, 7, 8 et 9 reprennent d'emblée les correctifs apportés à komga_watch_vps.sh le 2026-08-23 (page 220) : événements perdus pendant le traitement, écriture non atomique, absence de mémoire des échecs, journal volatil. Autant ne pas refaire les mêmes erreurs.
⚠
apres_traitement: "laisser"fait retraiter le dépôt en boucle à chaque passe. À réserver aux tests.
Pièges rencontrés à l'installation
1. --dry-run de Caesium ne mesure rien. L'option existe et s'exécute sans erreur, mais le rapport JSON renvoie compressed_size == original_size, soit un gain annoncé de 0,0 %. Elle simule l'écriture, pas la compression. Le mode --simulation du script ne l'utilise donc pas : il compresse réellement dans .staging, relève le chiffre, puis jette le résultat. C'est plus coûteux en CPU, mais c'est le seul moyen d'obtenir une estimation honnête.
2. -e n'est pas le défaut. Voir plus haut — perte silencieuse des dates et du GPS.
3. --json est la bonne interface de pilotage. Caesium renvoie un rapport structuré, une entrée par fichier (original_path, output_path, original_size, compressed_size, status, message) plus un summary. Tout le script s'appuie dessus plutôt que de parser la sortie texte.
4. --min-savings rend inutile le garde-fou maison. Sur Komga-PDF il avait fallu écrire à la main la règle « si la compression ne gagne rien, recopier l'original ». Caesium l'implémente nativement : sous le seuil, il n'écrit pas de fichier de sortie. Le script se contente de détecter l'absence et de recopier.
5. Création de la tâche planifiée depuis Claude Code : à éviter. Une session Claude Code tourne dans un conteneur MSIX (page 282). La création a par ailleurs été refusée par le garde-fou de la session — ce qui tombe bien. C'est à Julien de la créer depuis sa propre console.
6. Le binaire ne s'installe pas. caesiumclt.exe est un exécutable Rust statique de 5,7 Mo, sans dépendance ni installeur. Il se dépose dans bin\ et se met à jour en le remplaçant.
Le binaire
- Version :
caesiumcltv1.4.0, publiée le 8 juillet 2026 - Source :
https://github.com/Lymphatus/caesium-clt/releases - Archive :
caesiumclt-v1.4.0-x86_64-pc-windows-msvc.zip— 2 296 760 octets - SHA-256 :
a56454a83207fc25830f4d12679d7385c0906060f2ce5f54345ac5a4cf94b00f - Licence : GPL / MPL selon les composants (
bin\LICENSE.md)
Le même dépôt publie caesiumclt-v1.4.0-x86_64-unknown-linux-musl.tar.gz, statique, qui permettrait de porter la procédure sur le VPS ou Ubuntu sans modifier une ligne du script.
Maintenance
- Vider
originaux-traites\de temps en temps : les originaux y sont conservés, pas effacés. C'est le dossier qui grossit. - Surveiller
non-traites\: s'il se remplit, c'est que des HEIC ou des RAW arrivent dans le flux. echecs\doit rester vide. Toute entrée signale un fichier corrompu ou un cas non prévu — consulter le journal.- Journal :
D:\Procedures photos\logs\photos_compress.log, rotation automatique à 5 Mo.
Reste à faire
- Décider du sort du lot de démonstration laissé dans
Tofs-compressed\Ligurie 2026\(71 photos, 90 Mo) — il sert à juger la qualitéq80à l'œil, les originaux correspondants étant restés dansD:\Syncthing\PDF temps\photos Ligurie a traiter\
Voir aussi
- Page 220 — Procédure Komga-PDF, dont celle-ci reprend le principe et les correctifs
- Page 282 — piège MSIX de Claude Code sur le poste
julie - Page 211 — retour d'expérience StirlingPDF (la voie serveur, écartée ici)
⚠ Le -e manquant a deja fait des degats — passe du 2026-07-14
Cette page insiste sur le fait que -e n'est pas le defaut de Caesium et que sans lui l'EXIF disparait. Ce n'est pas une precaution theorique : une passe anterieure a la mise en place de la procedure, le 2026-07-14, a ete lancee sans cette option.
Degats constates le 2026-08-28, sur les photos de l'ete 2026 : 275 fichiers depouilles de tout bloc EXIF — date et GPS. Signature : 493 Ko de moyenne pour les fichiers traites, contre 1103 Ko pour les 76 intacts du meme voyage.
Consequence differee, invisible sur le moment : sans DateTimeOriginal, Immich se rabat sur la date du fichier. Or le WebDAV kDrive ne preserve pas les mtime — a la premiere resynchronisation, six semaines plus tard, les 275 photos sont allees se ranger au jour de la synchro et la chronologie du voyage s'est effondree.
Le GPS, lui, est definitivement perdu. Seule la date a pu etre reconstruite, a partir du nom des fichiers, par Jux-scripts/Photos-Caesium/dater_photos_nas.py. Recit complet et methode : page 164 (13_Immich).
A retenir avant toute passe de compression : verifier -e dans la ligne de commande et controler l'EXIF d'un fichier de sortie avant de traiter un lot. Un fichier de sortie sans bloc EXIF doit faire arreter la passe immediatement — les originaux ne sont pas toujours recuperables.
Contrôle du 2026-09-28 — la chaîne réelle, mesurée de bout en bout
Question de Julien : « la procédure Photos-Caesium du PC est bien la même que celle appliquée sur le NAS ? Notamment elle embarque le maintien des EXIF des photos sans les aplatir ? » — vérifié par la mesure, sur la chaîne réelle, et non par relecture du code.
Oui. Bloc EXIF identique à l'octet près, GPS au chiffre près, 72 étiquettes sur 72 conservées, dimensions et date de fichier inchangées. Rien n'est aplati ni simplifié : Caesium ne réécrit que les données d'image.
Protocole
Trois photos du Xiaomi 15T Pro (dont deux géolocalisées) mises de côté en référence, puis déposées dans Tofs a compresse\ sans rien lancer — c'est la tâche Photos-Caesium en surveillance qui les a prises, comme pour un dépôt ordinaire. Comparaison ensuite entre la référence et la sortie.
mtime)identique — --keep-dates tient
Poids13,1 Mo → 5,1 Mo, -61 %
Les 72 étiquettes conservées couvrent tout ce que l'appareil écrit : marque, modèle, objectif, ouverture, temps de pose, ISO, orientation, balance des blancs, et le bloc GPS complet.
Chronologie mesurée : dépôt à 20:43:51, déclenchement à 20:44:32 (les 20 secondes de calme), livraison à 20:44:34 — 43 secondes de bout en bout, sans intervention.
Originaux vérifiés intacts : les trois fichiers sources de l'arbre Syncthing sont identiques à l'octet après l'opération — le test n'a porté que sur des copies.
PC et NAS : le même moteur, une garantie de plus sur le NAS
compress_photos.py)NAS (traiter_lot_nas.py)
Binairecaesiumclt 1.4.0, identique
Profil-q 80, identique
Options communes-e --keep-dates --min-savings 1%, identiques
Date / propriétaire réimposés puis revérifiésnonoui (calquer() : os.utime, os.chown, os.chmod, puis relecture)
La différence ne porte pas sur l'EXIF, qui est protégé à l'identique par -e dans les deux cas. Elle porte sur la date de fichier et le propriétaire, et elle existe pour une raison propre au NAS : les photos y appartiennent à admin:users, et une compression lancée sans privilèges les réattribuerait toutes en cassant SMB et Synology Photos. Sur le PC il n'y a qu'un utilisateur, et la mesure ci-dessus montre que --keep-dates suffit — les trois mtime sont identiques à la seconde. Ajouter la même vérification au script du PC représenterait une quinzaine de lignes ; la mesure ne le réclame pas.
Le profil actif ne redimensionne pas
Le profil en service est q80 : il ne touche ni aux dimensions ni au nombre d'étiquettes. Le profil web-3000px présent dans config.json ramènerait le grand côté à 3 000 pixels — il est disponible mais non sélectionné, et ne le sera que sur demande explicite.
L'outil de contrôle
Jux-scripts/Photos-Caesium/comparer_exif.py — stdlib seule, aucune dépendance. Prend deux dossiers (référence et sortie) et compare fichier par fichier : bloc EXIF octet par octet, GPS converti en degrés décimaux, DateTimeOriginal, appareil, dimensions, nombre d'étiquettes, mtime, poids.
py -3.12 comparer_exif.py <dossier_reference> <dossier_sortie>
Il rend un verdict global et se prête au contrôle de sanité : lancé avec le même dossier des deux côtés, il doit tout déclarer conforme. À rejouer après toute modification du profil, de config.json ou du binaire — et en particulier pour honorer la règle de la section précédente : contrôler l'EXIF d'un fichier de sortie avant de traiter un lot.