Taguer ses fichiers audio en ligne de commande avec beets

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

Laisser un commentaire