Après mon post pour taguer les fichiers audio via via une interface graphique, voici le complément pour taguer les fichiers en ligne de commande avec l’outil beets avec quelques scripts utiles.
Beets est un outil écrit en python qui tout comme MusicBrainz Picard permet de taguer automatiquement les fichiers audio à partir de la base de données musicales de MusicBrainz. Rappelons que MusicBrainz est une vaste bibliothèque musicale totalement libre qui collecte des métadonnées musicales que tout un chacun peut alimenter.
Beets utilise une base de données locales où sont stockées les métadatas par fichier audio, les mêmes métadatas peuvent être enregistrés dans chaque fichier. Je l’ai installé sur ma mageia 9 tout simplement en tapant pip install beets
Le fichier de configuration se trouve sous /home/olivier/.config/beets/config.yaml et contiendra a minima
directory : /anatole/beets-music #le répertoire contenant les fichiers audio qui seront copiés ou déplacés library: /anatole/beets-music/music-database.db #la base de données import: copy: no #si yes les fichiers audio modifiés seront copiés dans le répertoire défini plus haut move: no #si yes les fichiers audio modifiées seront déplacés dans le répertoire défini plus haut write: no #si yes les métadatas seront enregistrés dans le fichier, si no elles seront seulement enregistrées dans la base de données
Maintenant pour importer des fichiers audio, il suffit d’indiquer le répertoire où se trouvent les fichiers audio en tapant beet import -s /anatole/musiques/classement\ par\ genre/rock
L’option -s pour singleton permet de traiter chaque fichier comme une piste indépendante, sinon par défaut il va considérer que toutes les pistes du répertoire font partie d’un unique album. Le traitement va se lancer de manière plus ou moins automatique, quand il identifie sans ambiguïté un fichier audio, on va avoir quelque chose comme cela
/anatole/musiques/classement par genre/rock/ACDC - hell bells.mp3 Tagging track: AC/DC - Hells Bells URL: https://musicbrainz.org/recording/5da479ac-3b98-43f6-88d8-6afeb9ccfcc7 (Similarity: 100.0%) /anatole/musiques/classement par genre/rock/ACDC - highway to hell.mp3 Tagging track: AC/DC - Highway to Hell URL: https://musicbrainz.org/recording/5935ec91-8124-42ff-937f-f31a20ffe58f (Similarity: 100.0%) /anatole/musiques/classement par genre/rock/ACDC - Let Me Put My Love Into You.mp3 Tagging track: AC/DC - Let Me Put My Love Into You URL: https://musicbrainz.org/recording/69de4ab7-bfce-424e-b109-d96b34801516 (Similarity: 100.0%)
parfois il peut demander de modifier automatiquement l’intitulé pour trouver le bon fichier
/anatole/musiques/classement par genre/rock/ACDC - shot down in flames.mp3 Correcting track tags from: AC/DC - shot down in flames To: AC/DC - Shot Down in Flames URL: https://musicbrainz.org/recording/bf80d304-2c72-4352-9ced-3aaed8632346 (Similarity: 100.0%)
Quand il n’a pas trouvé une similarité à 100%, il demande une confirmation
/anatole/musiques/classement par genre/rock/3 door's down - when I'm gone.mp3 Correcting track tags from: 3 Doors Down - When I'm Gone To: 3 Doors Down - When I’m Gone URL: https://musicbrainz.org/recording/aa82cd16-2777-4bd2-8068-851810fadae6 (Similarity: 93.6%) (length) [A]pply, More candidates, Skip, Use as-is, Enter search, enter Id, aBort? A
et quand il trouve plusieurs similarités, il nous laisse le choix
/anatole/musiques/classement par genre/rock/ACDC - Big Gun.mp3 Finding tags for track "AC/DC - Big Gun". Candidates: 1. AC/DC - Big Gun (58.3%) (id) 2. AC/DC - Big Gun (58.3%) (id) 3. AC/DC - Big Gun (58.3%) (id) 4. AC/DC - Big Gun (54.9%) (id, length) 5. AC/DC - Big Gun (50.0%) (id) # selection (default 1), Skip, Use as-is, Enter search, enter Id, aBort? 1 Tagging track: AC/DC - Big Gun URL: https://musicbrainz.org/recording/0588b976-c15a-4ca4-89fc-46ca10dac2da (Similarity: 58.3%) (id) Apply, More candidates, Skip, Use as-is, Enter search, enter Id, aBort? A
parfois il ne trouve pas du tout et dans ce cas il faut aller sur le site de MusicBrainz, trouver le morceau en question et relever son « recording Id »
/anatole/musiques/classement par genre/rock/Jimi Hendrix - hey joe.mp3 Tagging track: The Jimi Hendrix Experience - Hey Joe URL: https://musicbrainz.org/recording/98839598-c702-4666-ba7f-1da11a1d6611 (Similarity: 83.3%) (length) [A]pply, More candidates, Skip, Use as-is, Enter search, enter Id, aBort? m Finding tags for track "The Jimi Hendrix Experience - Hey Joe". Candidates: 1. The Jimi Hendrix Experience - Hey Joe (83.3%) (length) 2. The Jimi Hendrix Experience - Hey Joe (50.0%) (id) 3. The Jimi Hendrix Experience - Hey Joe (50.0%) (id) 4. The Jimi Hendrix Experience - Hey Joe (50.0%) (id) 5. The Jimi Hendrix Experience - Hey Joe (41.7%) (id, length) 6. The Jimi Hendrix Experience - Hey Joe (41.7%) (id, length) # selection (default 1), Skip, Use as-is, Enter search, enter Id, aBort? e Artist: Jimi Hendrix Track: Hey Joe Tagging track: The Jimi Hendrix Experience - Hey Joe URL: https://musicbrainz.org/recording/98839598-c702-4666-ba7f-1da11a1d6611 (Similarity: 83.3%) (length) [A]pply, More candidates, Skip, Use as-is, Enter search, enter Id, aBort? i Enter recording ID: 0a0d07ea-2933-4b4c-8f7f-b68a68013bfd Correcting track tags from: The Jimi Hendrix Experience - Hey Joe To: Jimi Hendrix - Hey Joe URL: https://musicbrainz.org/recording/0a0d07ea-2933-4b4c-8f7f-b68a68013bfd (Similarity: 33.6%) (id, length, artist) Apply, More candidates, Skip, Use as-is, Enter search, enter Id, aBort? a
On peut également avoir ce cas de figure
/anatole/musiques/classement par genre/rock/Chuck Berry - roll over Beethoven.mp3 Finding tags for track "Chuck Berry - Roll over Beethoven". Candidates: 1. Chuck Berry - Roll Over Beethoven (70.6%) (id) 2. Chuck Berry - Roll Over Beethoven (70.6%) (id) 3. Chuck Berry - Roll Over Beethoven (68.7%) (id, length) 4. Chuck Berry - Roll Over Beethoven (41.2%) (id) 5. Chuck Berry - Roll Over Beethoven (41.2%) (id) 6. Chuck Berry - Roll Over Beethoven (39.7%) (id, length) 7. Chuck Berry - Roll Over Beethoven (29.4%) (id, length) 8. The Swing Commanders - Roll Over Beethoven (Berry) (18.4%) (id, length, artist, ...) # selection (default 1), Skip, Use as-is, Enter search, enter Id, aBort? Correcting track tags from: Chuck Berry - Roll over Beethoven To: Chuck Berry - Roll Over Beethoven URL: https://musicbrainz.org/recording/f4c25958-5e6e-4890-8937-62507c9f41e1 (Similarity: 70.6%) (id) Apply, More candidates, Skip, Use as-is, Enter search, enter Id, aBort? a This item is already in the library! Old: MP3, 128kbps, 2:31, 2.4 MiB New: MP3, 252kbps, 2:23, 4.4 MiB [S]kip new, Keep all, Remove old, Merge all? R
une fois que c’est terminé, on peut lister le contenu de la base de données en tapant beet list et pour chercher une chaîne de caractère dans la base, on tapera simplement beet list grange qui donnera
ZZ Top - Tres hombres - La Grange
Pour connaitre les titres datés de 1977 on tapera beet list year:1977 et pour une plage de dates beet list year:1970..1980. Il suffira de compléter la commande par –-f ‘$path‘ pour que les fichiers apparaissent avec un chemin en absolu et rediriger vers un fichier à l’extension .m3u pour créer ainsi une playlist prête à l’emploi. Cela donne :
beet list -f '$path' year:1970..1980 > playlist-années70.m3u
Pour connaitre les champs sur lesquels on peut filtre, il faudra activer le plugins info en rajoutant info à la ligne plugins du fichier de configuration. Et un beet info zz top legs donnera
/anatole/musiques/classement par genre/rock/ZZ top - leggs.mp3 album: Eliminator albumartist: ZZ Top albumstatus: official albumtype: album albumtypes: album art: True artist: ZZ Top artist_sort: ZZ Top artists: ZZ Top bitdepth: 0 bitrate: 128000 bitrate_mode: catalognum: CD 23774 catalognums: CD 23774 channels: 2 country: US date: 1983-03-23 day: 23 disc: 1 disctotal: 1 encoder_info: encoder_settings: format: MP3 genre: Rock genres: Rock isrc: USWB10702822 label: Warner Bros. Records length: 273.901875 mb_albumartistid: a81259a0-a2f5-464b-866e-71220f2739f1 mb_albumartistids: a81259a0-a2f5-464b-866e-71220f2739f1 mb_albumid: ac85b905-13c2-48f6-8951-d45612205fc2 mb_artistid: a81259a0-a2f5-464b-866e-71220f2739f1 mb_artistids: a81259a0-a2f5-464b-866e-71220f2739f1 mb_releasegroupid: c58b50f0-d7a4-322c-b281-d86ebe3b8acf mb_releasetrackid: c1ced785-f7cb-3180-94f7-a9814419f949 mb_trackid: b7072e8d-39f8-4e7c-8c30-4317ca590d2e media: CD month: 3 original_date: 1983-01-01 original_year: 1983 samplerate: 44100 script: Latn title: Legs track: 6 tracktotal: 11 year: 1983
Pour filtrer sur le genre musical on tapera ainsi beet list genre:rock.
beets bénéficie de pas mal de plugins comme on peut le voir sur cette page. Le plugin bpmanalyser permet ainsi calculer le tempo d’un morceau et d’inscrire cette information dans un tag bpm dans les métadatas. Sur ma Mageia 9, je l’ai installé en tapant:
python3-numpy-devel python3-aubio pip install beets-bpmanalyser
On active le plugins en rajoutant bpmanalyser au niveau de la ligne plugins du fichier de configuration
plugins: info bpmanalyser
Par exemple pour afficher simplement le tempo des chansons de AC/DC sans modification de la base de données ou des fichiers (option dry-run), on tapera beet bpmanalyser –dry-run artist:AC/DC voilà le résultat
bpmanalyser: Bpm[128]: /anatole/musiques/classement par genre/rock/ACDC - You Shook Me All Night Long.mp3 bpmanalyser: Bpm[ERROR]: - /anatole/musiques/classement par genre/rock/ACDC - Let Me Put My Love Into You.mp3 bpmanalyser: Bpm[135]: /anatole/musiques/classement par genre/rock/ACDC - Big Gun.mp3 bpmanalyser: Bpm[128]: /anatole/musiques/classement par genre/rock/ACDC - hell bells.mp3 bpmanalyser: Bpm[132]: /anatole/musiques/classement par genre/rock/ACDC - shot down in flames.mp3 bpmanalyser: Bpm[135]: /anatole/musiques/classement par genre/rock/ACDC - thunderstruck.mp3
Si on souhaite modifier seulement les fichiers qui n’ont pas le tag bpm, on tapera beet bpmanalyser bpm:0 cela va donner quelque chose comme cela
Update tempo information on all songs where it is missing bpmanalyser: Bpm[123]: /anatole/musiques/classement par genre/rock/Aerosmith - jaded.mp3 bpmanalyser: Bpm[157]: /anatole/musiques/classement par genre/kitsch/Antoine - la moto godille.mp3 bpmanalyser: Bpm[107]: /anatole/musiques/classement par genre/rock/Aerosmith - cryin'.mp3 bpmanalyser: Bpm[ERROR]: - /anatole/musiques/classement par genre/rock/Aerosmith - I don't wanna miss a thing.mp3
Certains fichiers peuvent générer une erreur qui est visible en rajoutant les options -vv
RuntimeError: AUBIO ERROR: source_avcodec: error when sending packet for
Pour les fichiers en question ffprobe donne ce warning
[mp3 @ 0x1c2b4c0] Skipping 351 bytes of junk at 24586. [mp3 @ 0x1c2b4c0] Estimating duration from bitrate, this may be inaccurate
On peut penser qu’il est préférable de régénérer les dits fichiers. Pour relancer une analyse pour l’ensemble des fichiers de la base avec écriture dans chacun des fichiers on tapera beet bpmanalyser –force –write
Maintenant quelques scripts utiles basés sur ce qu’on vient de voir. Le script pour créer une playlist avec des fichiers musicaux dans une fourchette de tempo basé sur la commande ffprobe
#!/bin/bash read -p "Valeur tempo min (par défaut 0): " min read -p "Valeur tempo max (par défaut 200): " max read -p "Chemin absolu ou relatif dans le fichier playlist (par défaut relatif): " chemin if [ -z "$min" ] then $min=0 fi if [ -z "$max" ] then $max=200 fi if [ "$chemin" = "absolu" ] then path=$(pwd) else path="." fi IFS=$'\n' playlist="playlist/playlist-tempo-entre-$min-$max.m3u" rm -f $playlist for fichier in $(find $path type f | grep '/*.ogg\|/*.mp3\|/*.flac') do tempo=$(ffprobe -loglevel quiet -hide_banner -show_entries format_tags=TBPM -of default=noprint_wrappers=1:nokey=1 $fichier 2>&1) if [ -n "$tempo" ] then if [ $tempo -gt $min ] && [ $tempo -lt $max ] then echo "Fichier trouvé $fichier tempo $tempo" echo $fichier>>$playlist fi fi done; unset IFS
Ça peut donner des résultats surprenants, rappelons que le tempo correspond au battement régulier qui rythme le morceau. Il s’exprime en battement ou pulsation par minute et on peut très bien avoir des chansons bien rythmés avec du bon gros son de guitares saturées avec un tempo plutôt lent.
Le tempo n’est sans doute pas la valeur miracle pour créer des playlists de musiques qui sonnent de manière similaire à l’oreille et il sera sans doute utile de le compléter avec d’autres caractéristiques audio comme le rythme qui correspond à la durée des notes.
Sans entrer dans des complications de traitement du signal pour analyser chaque fichier audio, il existe le plugin acousticbrainz qui permet de récupérer l’ensemble un certain nombre de champs d’analyse audio disponibles dans la base MusicBrainz, dont le rythme, la tonalité, la « dançabilité » d’un morceau, etc.
On activera tout d’abord le plugin en rajoutant acousticbrainz au niveau de la ligne plugins du fichier de configuration
plugins: info bpmanalyser acousticbrainz
on tape ensuite beet acousticbrainz pour télécharger les métadatas d’analyse audio. Voilà le résultat
acousticbrainz: getting data for: Antoine - La Motogodille - La Motogodille acousticbrainz: recording ID 5d89b304-4448-4605-b03e-c133f7e66c2e not found acousticbrainz: getting data for: Apollo 440 - Gettin' High on Your Own Supply - Stop the Rock acousticbrainz: getting data for: Aqua - Aquarius - Cartoon Heroes acousticbrainz: getting data for: Ash - Meltdown - Starcrossed (...) acousticbrainz: recording ID da9e7176-6495-4c54-8a23-41c2fa87bb02 not found acousticbrainz: getting data for: ZZ Top - Eliminator - Legs acousticbrainz: recording ID def311a4-58ed-4c3c-adf0-a00fb13b4fb0 not found acousticbrainz: getting data for: ZZ Top - Incinerator - Rough Boy acousticbrainz: recording ID c4d362b8-12c8-4b20-a2fa-b37f19ba39a0 not found acousticbrainz: getting data for: ZZ Top - Tres hombres - La Grange
Ces métadatas supplémentaires sont inscrites dans la base de donnée et n’apparaissent pas directement dans le fichier audio, pour les visualiser on tapera par exemple beet info -l zz top gimme all your lovin, l’option -l indique qu’il faut lire ce qu’il y a dans la base de donnée et non dans le fichier directement, voilà ce que ça donnera
acoustid_id: e3f5a31c-7238-4815-8f6a-240211ed380f added: 2024-01-27 17:34:48 album: Eliminator album_id: albumartist: ZZ Top albumartist_credit: albumartist_sort: albumdisambig: albumstatus: official albumtype: album albumtypes: ['album'] arranger: artist: ZZ Top artist_credit: ZZ Top artist_sort: ZZ Top asin: average_loudness: 0.895212 bitdepth: 0 bitrate: 128kbps bpm: 0 catalognum: CD 23774 channels: 2 chords_changes_rate: 0.039907 chords_key: C chords_number_rate: 0.001550 chords_scale: major comments: comp: False composer: composer_sort: country: US danceable: 0.826061 data_source: MusicBrainz day: 23 disc: 01 discogs_albumid: 0 discogs_artistid: 0 discogs_labelid: 0 disctitle: disctotal: 01 encoder: filesize: 3850833 format: MP3 gender: male genre: Rock genre_rosamerica: pop grouping: id: 1381 initial_key: isrc: USRHD0709703;USWB10301934;USWB10702680;USWB11202723;USWB11300067;USWB11301286;USWB11901051;USWB19902780 key_strength: 0.792436 label: Warner Bros. Records language: length: 3:58 lyricist: lyrics: mb_albumartistid: a81259a0-a2f5-464b-866e-71220f2739f1 mb_albumid: ac85b905-13c2-48f6-8951-d45612205fc2 mb_artistid: a81259a0-a2f5-464b-866e-71220f2739f1 mb_releasegroupid: c58b50f0-d7a4-322c-b281-d86ebe3b8acf mb_releasetrackid: mb_trackid: 6dd73bac-956b-40ef-be01-860fcdd4990b mb_workid: media: CD month: 03 mood_acoustic: 0.024929 mood_aggressive: 0.727396 mood_electronic: 0.762750 mood_happy: 0.305811 mood_party: 0.443847 mood_relaxed: 0.136193 mood_sad: 0.061455 moods_mirex: Cluster5 mtime: 1970-01-01 01:00:00 original_day: 00 original_month: 00 original_year: 1983 path: /anatole/musiques/classement par genre/rock/ZZ Top - gimme all your lovin.mp3 r128_album_gain: 000000 r128_track_gain: 000000 releasegroupdisambig: rg_album_gain: 0.0 rg_album_peak: 0.0 rg_track_gain: 0.0 rg_track_peak: 0.0 rhythm: 0.000000 samplerate: 44kHz script: Latn singleton: True style: timbre: bright title: Gimme All Your Lovin’ tonal: 0.420130 track: 01 trackdisambig: tracktotal: 11 voice_instrumental: voice work: work_disambig: year: 1983
Maintenant pour faire la liste des titres dans la valeur de danceable est entre 0.8 et 1, on tapera beet list -f ‘$path’ danceable:0.8..1, cela va donner une liste de fichiers audio avec leur chemin absolu qui peut en l’état constituer une playlist. Ça sera similaire pour les autres valeurs d’analyse audio.
Ce n’est qu’un survol de beets qui permet une configuration assez poussée comme on peut en juger en visualisant ce florilège de fichier de configuration comme ce fichier, celui là et celui là encore.
Pour terminer deux scripts pour classer les fichiers audio par année de sortie et par artiste, ça va créer une arborescence avec un lien vers le fichier d’origine qui seront à adapter bien sûr avec vos chemins. Premier script avec classement par année.
#!/bin/bash IFS=$'\n' chemin="/ultra/data/musiques" rep_genre="classement par genre" rep_annee="classement par année" rep_sans_annee="_Titres non datés" if [ -d "$chemin/$rep_annee" ];then rm -Rf $chemin/$rep_annee fi for fichier in $(find $chemin/$rep_genre type f | grep '/*.ogg\|/*.mp3\|/*.flac') do annee=$(ffprobe -loglevel quiet -hide_banner -show_entries format_tags=originalyear -of default=noprint_wrappers=1:nokey=1 $fichier 2>&1) if [ -z "$annee" ] then if [ ! -d "$chemin/$rep_annee/$rep_sans_annee" ];then mkdir -p $chemin/$rep_annee/$rep_sans_annee fi ln -s $fichier $chemin/$rep_annee/$rep_sans_annee else if [ ! -d "$chemin/$rep_annee/$annee" ];then mkdir -p $chemin/$rep_annee/$annee fi ln -s $fichier $chemin/$rep_annee/$annee fi done; unset IFS
Et le script avec classement par artiste
#!/bin/bash IFS=$'\n' chemin="/ultra/data/musiques" rep_genre="classement par genre" rep_artiste="classement par artiste" rep_sans_artiste="Artiste inconnu" rm -Rf $chemin/$rep_artiste for fichier in $(find $chemin type f | grep '/*.ogg\|/*.mp3\|/*.flac') do artiste=$(ffprobe -loglevel quiet -hide_banner -show_entries format_tags=artist -of default=noprint_wrappers=1:nokey=1 $fichier 2>&1) if [ -z "$artiste" ] then if [ ! -d "$chemin/$rep_artiste/$rep_sans_artiste" ];then mkdir -p $chemin/$rep_artiste/$rep_sans_artiste fi ln -s $fichier $chemin/$rep_artiste/$rep_sans_artiste else if [ ! -d "$chemin/$rep_artiste/$artiste" ];then mkdir -p $chemin/$rep_artiste/$artiste fi ln -s $fichier $chemin/$rep_artiste/$artiste fi done; unset IFS