260904-conversion des fichiers FLAC en MP3 avec Tags vérifiés
Conversion des fichiers FLAC en MP3, avec tags vérifiés
Mise en place le 2026-09-04 sur le poste Windows julie. Script versionné dans
Jux-scripts/Musique-FLAC/, documentation de référence : le README.md du même dossier.
On dépose des FLAC dans un dossier, on les récupère encodés en MP3 dans un autre, sans rien lancer à la main. C'est la troisième procédure bâtie sur ce moule, après Komga-PDF (compression de PDF) et Photos-Caesium (compression de photos), dont elle reprend les garde-fous éprouvés : écriture par fichier provisoire, mémoire des échecs, journal persistant, attente d'une période de calme avant de toucher au dépôt.
Sa particularité : elle ne fait pas confiance au convertisseur. Les tags sont lus dans le FLAC par le script lui-même, réécrits explicitement, puis relus dans le MP3 produit et comparés champ par champ. Un MP3 auquel il manque un tag n'est pas livré.
Pourquoi localement, et pourquoi ffmpeg
Le VPS n'intervient pas. L'encodage MP3 est du calcul pur : le Ryzen 5 2600X (12 fils) est très largement supérieur au VPS pour cet usage, et les fichiers sont déjà sur le poste. Aucun aller-retour réseau, aucune API à maintenir — même raisonnement que pour Photos-Caesium.
Aucun encodeur n'était présent sur ce poste : ni ffmpeg, ni lame, ni flac, et Python n'a pas
mutagen. Il a donc fallu poser un binaire, comme caesiumclt pour les photos. ffmpeg a été
retenu contre le couple flac.exe + lame.exe (moins de 3 Mo à eux deux, contre 98 Mo) parce
qu'il fait le décodage, l'encodage LAME et la pochette en un seul appel, et qu'il est
distribué par une build Windows officielle. Le script, lui, reste en bibliothèque standard pure.
Emplacements
| Rôle | Chemin |
|---|---|
| Dépôt | D:\Musique\FLAC à encoder\ |
| Résultat | D:\Musique\MP3 fait\ |
| Originaux après conversion | D:\Musique\FLAC traités\ |
| Échecs (après 3 tentatives) | D:\Musique\echecs\ |
| Binaire | D:\Musique\bin\ffmpeg.exe |
| Configuration | D:\Musique\config.json |
| Journal | D:\Musique\logs\flac_mp3.log |
| Mémoire des traitements | D:\Musique\etat.json |
| Script | Jux-scripts\Musique-FLAC\flac_mp3.py (synchronisé, donc versionné) |
Les dossiers de travail sont volontairement hors de l'arbre Syncthing, pour la même raison
que Photos-Caesium : il n'existe qu'un seul dossier Syncthing dans tout le maillage
(afltj-njyuy), partagé avec 7 appareils. Un album FLAC de 400 Mo déposé dedans descendrait
intégralement sur le Xiaomi et la SM-T720.
L'arborescence du dépôt est reproduite à l'identique en sortie : on dépose le dossier de l'album, on récupère le dossier de l'album.
Usage
Trois lanceurs à double-cliquer dans D:\Musique\ :
Convertir maintenant.cmd— une passe puis sortieSimuler (lire les tags).cmd— n'encode rien, annonce les tags lus dans chaque FLACSurveillance (fenetre visible).cmd— boucle de surveillance avec la console à l'écran
En ligne de commande :
py -3.12 flac_mp3.py --une-fois
py -3.12 flac_mp3.py --simulation
py -3.12 flac_mp3.py --profil 320 --une-fois
py -3.12 flac_mp3.py --profils
py -3.12 flac_mp3.py --verifier "D:\Musique\MP3 fait\album\01 - titre.mp3"
py -3.12 flac_mp3.py --oublier-echecs
py -3.12 flac_mp3.py # surveillance continue
--verifier relit les tags d'un MP3 déjà produit et les affiche : c'est l'outil de contrôle à
la main, indépendant de toute conversion.
Profils de qualité
Définis dans config.json, V0 par défaut.
| Profil | Options LAME | Débit moyen |
|---|---|---|
V0 |
-q:a 0 |
~245 kbps VBR — transparent, réglage de référence |
V2 |
-q:a 2 |
~190 kbps VBR — nettement plus léger |
320 |
-b:a 320k |
320 kbps CBR — compatibilité matérielle maximale |
256 / 192 |
-b:a … |
débits fixes intermédiaires |
Ce que fait le script, dans l'ordre
- Attend que le dépôt soit calme. Sondage toutes les 15 s ; le traitement ne démarre qu'après 20 s sans le moindre changement dans l'arborescence (nombre de fichiers, volume total, date la plus récente). C'est ce qui évite d'attraper un fichier en cours de copie. Plafond de 15 min, après quoi le traitement est forcé.
- Lit le FLAC lui-même : bloc
STREAMINFO(durée, fréquence, canaux) et blocVORBIS_COMMENT(tous les tags), présence d'un blocPICTURE. - Refuse d'emblée un FLAC dépourvu de
title,artistoualbum— liste réglable partags_obligatoires. - Encode en écrivant chaque tag explicitement (voir le piège n°1 plus bas), pochette
comprise, vers un fichier
.staging-…et non directement vers la destination. - Relit les trames ID3v2 du MP3 produit et les compare aux tags attendus.
- Recompare la durée du MP3 à celle du FLAC (voir le piège n°3 — c'est le contrôle le plus utile de la chaîne).
- Ne publie le MP3 que si tout passe. Le fichier provisoire est renommé en place (opération atomique) ; en cas d'échec il est supprimé et rien n'apparaît en sortie.
- Déplace l'original dans
FLAC traités\. Les fichiers d'accompagnement (cover.jpg,.cue,.log,.m3u…) suivent l'album ; les images sont en plus copiées en sortie. Les dossiers vidés sont élagués, de sorte que le dépôt se vide de lui-même.
En cas d'échec, le fichier est retenté 3 fois (clé taille + date de modification, mémorisée
dans etat.json), puis écarté dans echecs\ accompagné d'un .erreur.txt qui dit pourquoi.
Correspondance des tags
| Vorbis | ID3v2 | Remarque |
|---|---|---|
TITLE |
TIT2 |
|
ARTIST |
TPE1 |
|
ALBUM |
TALB |
|
ALBUMARTIST / ALBUM ARTIST |
TPE2 |
|
DATE / YEAR |
TYER (v2.3) ou TDRC (v2.4) |
voir piège n°2 |
TRACKNUMBER + TRACKTOTAL |
TRCK = 3/12 |
recomposé, voir piège n°1 |
DISCNUMBER + DISCTOTAL |
TPOS = 1/2 |
recomposé |
GENRE |
TCON |
|
COMPOSER |
TCOM |
|
ORGANIZATION / LABEL / PUBLISHER |
TPUB |
|
COPYRIGHT |
TCOP |
|
ISRC |
TSRC |
|
BPM |
TBPM |
|
COMMENT / DESCRIPTION |
COMM |
|
LYRICS / UNSYNCEDLYRICS |
USLT |
|
bloc PICTURE |
APIC |
pochette |
| tout le reste | TXXX:<nom> |
REPLAYGAIN_*, MUSICBRAINZ_*… conservés tels quels |
Aucun tag n'est perdu : ce qui n'a pas de trame dédiée part en TXXX sous son propre nom, et
c'est relu tel quel à la vérification.
Pièges — à ne pas re-découvrir
1. ffmpeg -map_metadata 0 perd les totaux de piste et de disque. C'est la raison d'être de
la réécriture explicite (-map_metadata -1 puis un -metadata par champ). Mesuré sur le même
FLAC source :
| ffmpeg nu | ce script | |
|---|---|---|
| piste | track 3 + TXXX:tracktotal 12 |
TRCK 3/12 |
| disque | disc 1 + TXXX:disctotal 2 |
TPOS 1/2 |
| éditeur | TXXX:organization |
TPUB |
Un lecteur qui affiche « piste 3 sur 12 » lit TRCK, pas un TXXX non standard. La conversion
naïve produit donc des albums qui s'affichent mal sans que rien ne le signale.
2. ID3v2.3 ne sait pas stocker une date complète. Sa trame TYER ne contient que l'année :
un DATE=2024-03-17 devient 2024. Ce n'est pas une perte de tag mais une limite du format —
le script le classe en écart toléré et ne bloque pas. "id3v2_version": 4 dans config.json
conserve la date entière (trame TDRC), au prix de la compatibilité avec les vieux lecteurs
matériels. La vérification fonctionne dans les deux cas. v2.3 est le défaut retenu.
3. ⚠ Un FLAC tronqué se convertit sans la moindre erreur. Vérifié : sur un FLAC coupé au
tiers, ffmpeg sort en code 0 et produit un MP3 parfaitement valide… de 0,27 s au lieu de
2,00 s. Ni le code de retour, ni la validité du MP3, ni les tags ne trahissent quoi que ce soit
— les tags sont même intacts, puisqu'ils vivent en tête de fichier. Seule la comparaison des
durées l'attrape, d'où verifier_duree activé par défaut. C'est le contrôle le plus utile de
toute la chaîne, et le seul qui protège d'une livraison silencieusement mutilée.
4. Le bloc VORBIS_COMMENT est en petit-boutiste, alors que tout le reste du format FLAC
est en gros-boutiste. Se tromper de sens donne des longueurs de champ aberrantes et un parseur
qui part dans le décor.
5. Les tailles ID3 ne se lisent pas toutes pareil. L'en-tête ID3v2 et les trames v2.4 utilisent des entiers syncsafe (7 bits utiles par octet, le 8ᵉ toujours à 0) ; les trames v2.3, elles, portent une taille sur 32 bits ordinaires. Un seul mode de lecture pour les deux versions donne des trames décalées.
6. Valeurs multiples. Vorbis autorise plusieurs ARTIST dans un même fichier, ID3v2.3 non.
Elles sont jointes par ; — et c'est cette même chaîne qui sert de valeur attendue à la
vérification, donc la comparaison reste exacte.
7. pythonw.exe + binaire console = cascade de fenêtres noires. Le script passe
creationflags=CREATE_NO_WINDOW à tous ses appels ffmpeg. Sans ce drapeau, un lancement en
tâche planifiée par pythonw.exe (qui n'a pas de console) fait allouer une fenêtre par appel.
Même piège que la surveillance Blink du 2026-08-30.
8. Pas d'inotify sous Windows : la surveillance se fait par sondage, pas par événements.
Surveillance automatique à l'ouverture de session
À créer par Julien dans sa propre console, pas depuis Claude Code — une tâche créée depuis le conteneur MSIX risquerait de figer un chemin virtualisé (page BookStack 282) :
schtasks /Create /TN "Musique-FLAC" /TR "\"C:\Users\julie\AppData\Local\Programs\Python\Python312\pythonw.exe\" \"D:\Syncthing\Jux_univers\Jux-scripts\Musique-FLAC\flac_mp3.py\"" /SC ONLOGON /RL LIMITED /F
pythonw.exe (et non python.exe) pour qu'aucune fenêtre n'apparaisse. Vérification :
schtasks /Query /TN "Musique-FLAC" /V /FO LIST, ou taskschd.msc. Pour retirer :
schtasks /Delete /TN "Musique-FLAC" /F.
Contrôle depuis une session Claude : Get-CimInstance Win32_Process -Filter "Name='pythonw.exe'".
Mesures de mise en place (2026-09-04)
- ffmpeg 9.0.1 (build essentials gyan.dev) : archive de 106,1 Mo, seul
ffmpeg.execonservé → 98,1 Mo dansD:\Musique\bin\.ffprobe.exeetffplay.exeécartés : le script analyse les tags lui-même, il n'en a pas besoin. - Délai de prise en charge : fichier déposé à 07:06:44, MP3 livré à 07:07:43, soit 59 s (15 s de sondage + 20 s de calme requis + encodage).
- Chemins d'échec vérifiés un par un : fichier qui n'est pas un FLAC, FLAC sans tags
obligatoires, FLAC tronqué → 3 tentatives chacun puis mise à l'écart dans
echecs\avec le motif. Dépôt vidé, aucun MP3 partiel livré. - Aller-retour des tags vérifié sur 15 tags dont accents, guillemets français et exposant
(
Prélude n°1 — «Nuit»,Élodie Ström), totaux de piste et de disque, ISRC,REPLAYGAIN_*etMUSICBRAINZ_*: tous restitués, pochette 600×600 conservée. - Taux de compression : pas encore mesuré sur de la vraie musique. Les 55 % relevés à l'essai portent sur une onde sinusoïdale de synthèse, qui ne compresse comme rien de réel — ce chiffre n'a aucune valeur prédictive. À relever sur le premier album.
Reste à faire
- Relever le taux de compression réel sur un album complet.
- Créer la tâche planifiée (commande ci-dessus, à taper par Julien).
- Décider si les MP3 produits ont vocation à rejoindre la chaîne Navidrome (
musicsur kDrive) ou restent un export local vers téléphone et autoradio.