Gestion simpliste de playlist et migration depuis Spotify

Retour accueil


Le code qui résulte de toute cette exploration est accesible dans le dépôt downloadmusic en ce qui concerne la synchronisation playlist <-> fichiers audio

git clone git://katzele.netlib.re/downloadmusic

et dans

git clone git://katzele.netlib.re/zenu-arthur

en ce qui concerne les commandes que j’utilise fréquemment pour lire, filtrer, synchroniser le tout. Elles sont dans les fichiers de menu zenu (article sur le sujet à venir) playlist et filtrer.

Il vous est possible de directement utiliser ce code là1, mais je vous recommande de lire l’article pour savoir d’où il vient et construire votre système selon vos besoins. J’ai peut-être fait des choses plus compliquées et nécessitant plus de dépendances que ce dont vous avez réellement besoin.

Le problème

Depuis que je m’organise pour pouvoir faire la (quasi) totalité de mes activités numériques sur un raspberry ou équivalent je sais qu’inévitablement il va falloir que je m’occupe de spotify. Il y a deux façons traditionnelles de consommer de la musique sur ce service :

  1. accéder au contenu via spotify.com
  2. accéder au contenu via l’application desktop

Il est préférable de ne pas passer par un navigateur web pour écouter de la musique. En effet, de très nombreuses applications savent déjà le faire et de façon bien plus efficace. À l’inverse les navigateurs webs ne sont originellement pas conçus pour. De manière générale il serait opportun, pour réduire les coûts (de quelques natures qu’ils soient), de ne pas utiliser le web pour autre chose que de s’échanger des documents html. Je ne redéveloppe pas tout l’argumentaire expliquant pourquoi et comment, cela a déjà été fait maintes fois. Si vous peinez à trouver des ressources dessus contactez moi !

L’application desktop rencontre le même souci puisqu’elle est basée sur la technologie electron qui fait usage de la stack technique des navigateurs web. Cet état de fait condamne une personne utilisant un ordinateur peu puissant à ne pas pouvoir utiliser spotify. J’imagine que c’est au moins en partie pour cette raison qu’un ensemble de clients tiers est apparu. Pour en lister deux :

Ces deux logiciels sont bien des interfaces, elles ne remplacent pas le backend de spotify. Pour pouvoir les utiliser et écouter de la musique avec il vous faudra utiliser spotifyd qui s’occupera d’aller streamer la musique depuis spotify. Les interfaces contrôleront spotifyd pour lui dire de passer la chanson, monter le volume etc. Pour avoir testé ces deux solutions il y a un an environ elles fonctionnent et sont effectivement beaucoup plus légères mais rencontrent d’assez nombreux problèmes/bug. Je ne vais pas prendre le temps de les lister, j’ai simplement le souvenir qu’à force de frustration j’ai décidé de réutiliser l’appli desktop sur mes terminaux relativement puissants.

J’étais donc rendu au point de départ. Il se trouve qu’il y a d’autres raisons de vouloir se débarrasser de spotify, notamment le DRM ou Gestion des Droits Numériques. Le DRM, c’est pas bien. Les alternatives sont :

Le piratage c’est pas bien, vous ne voleriez pas une voiture n’est-ce pas ? Cependant, si l’on veut rester sur quelque chose d’aussi simple que Spotify j’ai le sentiment que le piratage, notamment télécharger de la musique que l’on trouve sur youtube, est la meilleure solution. Je dois préciser que cette réflexion de ma part est certainement regrettable. Je pense que je me suis fait à la relative simplicité de l’usage de spotify ce qui m’incite à ne pas chercher à acheter la musique. Ces achats devraient se faire dans des lieux différents, auraient des formats différents etc. J’ai consenti à faire des efforts supplémentaire dans d’autres domaines de ma vie quand je sais que cela réduit considérablement les coûts sociaux et environnementaux mais je me voyais mal le faire dans celui-ci. Du moins pas tout de suite.

Mon usage de spotify

D’abord je décris l’usage que j’en fais. Si votre usage est très différent peut-être que ce que j’ai pensé ne vous conviendra pas du tout. J’utilise spotify de trois façons différentes.

Je découvre de la musique à travers des ami·e·s, en écoutant la radio, en allant en soirée, festival, concert ou beaucoup plus rarement en utilisant les recommandations spotify. Je fais une recherche sur spotify, j’écoute et je “like” ce que j’apprécie. J’écoute la playlist “Liked Songs” produite dans l’ordre antéchronologique ou en aléatoire.

J’ai une envie très particulière d’écouter un ou une artiste, je fais une recherche spécifique et j’écoute, généralement des albums en entier.

J’ouvre l’interface spotify sur mon pc et je laisse les personnes mettre la musique qu’elles souhaitent.

J’ai un usage assez restreint des playlists en dehors de celle générée par les titres que je like. Au vu de ces usages je me suis construit un petit système pour répliquer une partie de mon usage de spotify.

shell + ytcli + yt-dlp + mpv + git

Pour économiser de la bande passante et pouvoir écouter de la musique sans avoir besoin d’internet, comme lorsque l’on télécharge la musique en local sur spotify, il faut pouvoir télécharger les morceaux. Je choisis de le faire depuis youtube du fait de la taille du catalogue disponible sur cette plateforme. Si vous avez déjà lu l’article sur ma façon de lire des vidéos youtube vous savez que l’on peut télécharger des vidéos youtube avec yt-dlp. Puisque yt-dlp permet d’accéder à tous les formats disponibles, il est possible de télécharger uniquement l’audio d’une vidéo.

Pour faire simple on peut utiliser les formats “dynamiques” de yt-dlp. Le format worstaudio sélectionnera toujours le format audio de moins bonne qualité2. Le format bestaudio fera l’inverse. Puisque que l’on souhaite écouter de la musique et que par ailleurs youtube n’héberge pas des formats audio de très grande taille, le format bestaudio me semble adapté à notre besoin. Ainsi, si l’on souhaite télécharger la musique https://www.youtube.com/embed/WBsIKQEGQ_A on peut lancer la commande

yt-dlp -f bestaudio https://www.youtube.com/embed/WBsIKQEGQ_A

et obtenir un fichier de 3,96Mo nommé “Mop Mop - Jamajumba [WBsIKQEGQ_A].webm”. Si votre morale ou vos contraintes techniques vous imposent de télécharger des formats plus petits regardez le manuel de yt-dlp pour choisir un format différent. Pour changer le nom du fichier on peut utiliser l’option -o qui prendra en argument une chaine de caractère. Si l’on récupère quelques liens de la sorte et que l’on télécharge quelques musiques, construire une playlist revient à créer un fichier avec la liste des chemins vers les fichiers audios.

Par exemple, vous pouvez avoir l’arborescence suivante :

/home/vous/playlist
├── Inüit - Hush
├── Iron Maiden - Phantom Of The Opera - 1998 Remastered Version
├── King Gizzard & The Lizard Wizard - Inner Cell
├── Marc Rebillet - VACCINATED ATTITUDE
├── playlist.m3u
├── Souad Massi - Mirage (feat. Piers Faccini)
├── The Notorious B - Big Poppa - 2007 Remaster
├── Weval - Half Age
├── Yom - Longing for the Beat
└── Yuksek, Her - Sweet Addiction - Live Edit

Avec le contenu de playlist.m3u étant :

Inüit - Hush
Iron Maiden - Phantom Of The Opera - 1998 Remastered Version
King Gizzard & The Lizard Wizard - Inner Cell
Marc Rebillet - VACCINATED ATTITUDE
Souad Massi - Mirage (feat. Piers Faccini)
The Notorious B - Big Poppa - 2007 Remaster
Weval - Half Age
Yom - Longing for the Beat
Yuksek, Her - Sweet Addiction - Live Edit

Et il suffira de faire

mpv playlist.m3u

ou

vlc playlist.m3u

pour lire toute la playlist dans l’ordre du fichier. Pour la suite je prendrai mpv pour exemple parce que c’est ce que j’utilise. On peut lancer la playlist avec :

mpv –no-audio-display –volume=50 chemin/vers/la/playlist.m3u

--no-audio-display permet de garantir qu’mpv n’ouvrira pas d’interface graphique, --volume=50 de ne pas péter mes oreilles par défaut.

Si l’on veut jouer la playlist de façon aléatoire, deux solutions. Soit on utilise l’option --shuffle d’mpv soit on mélange le contenu du fichier avec shuf :

shuf playlist.m3u | xargs -d'\n' mpv

J’aurais tendance à favoriser l’utilisation de shuf. C’est un outil agnostique que l’on pourra réutiliser à chaque fois qu’il faut mélanger un fichier. A l’inverse --shuffle ne fait sens que dans le cadre d’mpv. Philo Unix, acquisition de savoirs génériques, etc.

J’utilise beaucoup xargs, c’est une commande vraiment puissante. Un jour je ferai un court article pour expliquer comment elle fonctionne (ou du moins l’usage que j’en fais). En attendant sachez qu’ici cela exprime l’idée “prend chaque élément rendu par shuf playslist.m3u séparé par une retour à la ligne (chaque ligne donc) et fais-en un argument à la commande mpv. Cela revient donc à lancer la commande mpv titre1 titre2 titre3 titre4.

Tout cela est bien sympa mais comment fait-on si l’on a des playlists de plusieurs centaines chansons, on va quand même pas chercher les liens sur youtube à la main et lancer les commandes yt-dlp une par une ?

Non effectivement, on peut l’automatiser. Ce ne sera pas sans erreurs mais le gain de temps sera tout de même considérable. Pour automatiser les recherches youtube nous allons utiliser un outil disponible dans le dépôt frontends de codemadness. On y retrouve, dans le dossier youtube, le nécessaire pour compiler un binaire nommé cli qui permet de faire des recherches youtube et de récupérer les résultats dans la console sous format texte. Dans le reste de cet article je nommerai cli ytcli pour plus de clarté.

il est possible que vous ayez des difficultés à compiler ytcli et il est préférable de légèrement le modifier pour notre besoin. Je ferai un petit tuto à l’avenir pour les personnes que ça intéresse TODO

ytcli s’utilise simplement en lui donnant en argument le sujet de notre recherche, comme si c’était la boite de recherche sur youtube.com. Par exemple, si l’on veut chercher le morceau Highway of Endless Dreams d’M83 on pourrait faire :

ytcli "M83 - Highway of Endless Dreams"

et cela imprime

M83 - Highway of Endless Dreams (audio)
URL:           https://www.youtube.com/embed/iqNohjW_kWc
Atom feed:     https://www.youtube.com/feeds/videos.xml?channel_id=UC8WbdD3m5dP9giOU9XtAGWQ
Channel title: M83
Channelid:     UC8WbdD3m5dP9giOU9XtAGWQ
Published:     7 years ago
Viewcount:     138,424 views
Duration:      4:37
===
M83   Highway Of Endless Dreams
URL:           https://www.youtube.com/embed/HXUKHZ9wwNw
Atom feed:     https://www.youtube.com/feeds/videos.xml?channel_id=UCynAa3zrpJlU4WjxiBe4qrg
Channel title: inner silence
Channelid:     UCynAa3zrpJlU4WjxiBe4qrg
Published:     8 years ago
Viewcount:     29,162 views
Duration:      4:36
===
M83 "Highway of Endless Dreams,  Skin of the Night,+" live on 6.6.2008 in Philadelphia, PA.
URL:           https://www.youtube.com/embed/6SQkmxjUpzc
Atom feed:     https://www.youtube.com/feeds/videos.xml?channel_id=UCv8I0sTv7aaelMbd3OQEdAw
Channel title: Not All Punk & Games
Channelid:     UCv8I0sTv7aaelMbd3OQEdAw
Published:     6 years ago
Viewcount:     4,547 views
Duration:      18:35
...

Ces résultats ne sont pas inventés par ytcli, ce sont très exactement les mêmes que ceux que vous auriez obtenu si vous aviez fait la recherche sur youtube.com dans un navigateur. ytcli ne fait que remanier les données pour les imprimer sous forme textuelle. Dans la grande majorité des cas le premier résultat est celui que l’on veut. Pour rappel notre but est d’automatiser le fait de lancer des commandes de téléchargement telle que celle que l’on a vu précédemment.

yt-dlp -f bestaudio https://www.youtube.com/embed/WBsIKQEGQ_A

Il nous faut donc récupérer le premier lien du premier résultat. A priori, tant que l’on ne modifie pas ytcli cette donnée se trouvera toujours sur la première ligne commençant par URL: ligne. On peut donc récupérer le nécessaire avec ce coup de grep et de sed :

ytcli "M83 - Highway of Endless Dreams" | grep -m1 URL: | sed 's/URL: \+//'

Maintenant que l’on a un moyen de récupérer le lien du premier résultat d’une recherche youtube on peut les enchaîner. Notre donnée d’entrée sera la liste des chansons :

cat playlist.m3u
Inüit - Hush
Iron Maiden - Phantom Of The Opera - 1998 Remastered Version
King Gizzard & The Lizard Wizard - Inner Cell
Marc Rebillet - VACCINATED ATTITUDE
Souad Massi - Mirage (feat. Piers Faccini)
The Notorious B - Big Poppa - 2007 Remaster
Weval - Half Age
Yom - Longing for the Beat
Yuksek, Her - Sweet Addiction - Live Edit

On automatise les recherches :

cat playlist.m3u | xargs -d'\n' -n1 ytcli

Pour xargs ici le -n1 permet d’indiquer que l’on ne veut qu’un argument par commande. Au lieu de lancer ytcli titre1 titre2 titre3 ce sont les commandes ytcli titre1 puis ytcli titre2 puis ytcli titre3 qui seront exécutées.

Comme fait précedemment on voudrait récupérer le premier lien de chaque recherche sauf que nous obtenons tous les résultats d’un coup dans l’ordre :

Nous ne pouvons donc plus simplement retenir le premier lien puisque le premier de la seconde chanson sera quelque part bien plus bas dans le flux. Les données ressemblent à ça :

recherche 1 - résultat 1
recherche 1 - résultat 2
recherche 1 - résultat 3
recherche 2 - résultat 1
recherche 2 - résultat 2
recherche 2 - résultat 3
recherche 3 - résultat 1
recherche 3 - résultat 2
recherche 3 - résultat 3
etc.

notre grep -m1 URL: omettrait toutes les chansons venant après la première recherche. Il nous faut opérer le grep et le sed sur chaque “bloc” de résultats. Pour cela la commande exécutée par xargs doit contenir elle même les filtres.

cat playlist.m3u | xargs -d'\n' -n1 sh -c 'ytcli "$1" | grep -m1 URL: | sed "s/URL: \+//"' --

Pour faire en sorte que la commande exécutée par xargs puisse enchaîner des pipes sans que ce soit la sortie d’xargs elle même qui soit pipée on lance un subshell avec la commande sh -c. L’option -c permet de dire au subshell de lire ses commandes non pas depuis stdin mais depuis la chaîne de caractère qui suivra dans les arguments. On écrit donc la commande qui nous intéresse entre simple cotte en positionnant l’argument $1 au bon endroit. Une fois la commande finie on ferme la simple cotte. Viennent ensuite les arguments de cette commande. Par convention le permier argument sera $0 qui contient tradtionnellement le chemin du script exécuté. Puisque qu’ici il n’y a pas fichier de script il faut choisir $0 “à la main”. Viennent ensuite les arguments $1, $2 etc. C’est pour “sauter” $0 que l’on met les “–”. Ainsi on s’assure que l’argument passé par xargs ne terminera pas dans $0 (puisqu’il aura déjà pour valeur –) mais bien dans $1.

On récupère la liste :

https://www.youtube.com/embed/NZHUCu8ggpY
https://www.youtube.com/embed/VnDNXbDjPis
https://www.youtube.com/embed/G3JeZDps7O8
https://www.youtube.com/embed/qeCwwYjf8gw
https://www.youtube.com/embed/1qnKfnGFuSU
https://www.youtube.com/embed/QceVTChhlJM
https://www.youtube.com/embed/wDRp0KjJ9ds
https://www.youtube.com/embed/ptJ2fIzksIc
https://www.youtube.com/embed/qWMP-UxSEss

Il ne reste plus qu’à les télécharger :

cat playlist.m3u |
    xargs -d'\n' -n1 sh -c 'ytcli "$1" | grep -m1 URL: | sed "s/URL: \+//"' -- |
    xargs -n1 yt-dlp -f bestaudio

pas besoin de préciser le délimiteur -d'\n' ici puisque le démiliteur par défaut d’xargs est l’espace et que les liens n’en contiennent pas.

Il existe dorénavant, dans le dossier ou nous nous trouvons, les fichiers

./Big Poppa (2007 Remaster) [QceVTChhlJM].webm
./Phantom of the Opera (1998 Remaster) [VnDNXbDjPis].webm
./VACCINATED ATTITUDE [qeCwwYjf8gw].webm
./Longing for the Beat [ptJ2fIzksIc].webm
./Inner Cell [G3JeZDps7O8].webm
./Souad Massi - Mirage feat. Piers Faccini (Carte Blanche Culturebox) [1qnKfnGFuSU].webm
./Weval - Half Age [wDRp0KjJ9ds].webm
./INÜIT - HUSH [LIVE] [NZHUCu8ggpY].webm
./Sweet Addiction - live edit [qWMP-UxSEss].webm

Problème ! Si l’on lance la commande mpv playlist.m3u aucune chanson ne se lancera. Pourquoi ? En lisant le fichier playlist.m3u mpv va chercher à ouvrir le fichier Inuit - Hush mais celui-ci a été nommé INÜIT - HUSH [LIVE] [NZHUCu8ggpY].webm par yt-dlp, c’est à dire titre de la vidéo youtube [identifiant de la vidéo].[format du fichier audio]. Comme précisé plus tôt on peut y remédier avec l’option `-o

cat playlist.m3u |
    xargs -d'\n' -n1 sh -c 'ytcli "$1" | grep -m1 URL: | sed "s/URL: \+//"' -- |
    paste playlist.m3u - |
    sed 's/ /\n/' |
    xargs -d'\n' -n2 sh -c 'yt-dlp -f bestaudio -o "$1" "$2"' --

On aura utilisé paste pour pouvoir donner en entrée à xargs à la fois le nom du fichier voulu et l’url de la vidéo à télécharger ainsi qu’une substitution pour simplifier leur ingestion par xargs.

Nous avons dorénavant un format de fichier pour déclarer une playlist, un moyen de télécharger toutes les musiques s’y trouvant et un moyen pour lire la dite playlist. L’essentiel est là. Evidemment vous pourriez vouloir appeler les fichiers différèmment, sélectionner la second résultat youtube, choisir une autre qualité si vous êtes sur une mauvaise connexion par exemple, parraléliser les téléchargements. Notre commande est suffisament flexible et courte pour pouvoir faire tout cela.

Astuces d’usage :

Utilisez l’option --quiet. Si vous voulez tout de même avoir un retour sur ce qu’il se passe vous pouvez modifier la commande de la sorte :

Vous pouvez opter pour le format worstaudio.

Il existe pleins d’options différentes pour choisir très précisèment le format que l’on veut. On peut jouer sur la taille du fichier, le codec, le conteneur, le bitrate etc. Pour plus de détails voir la documentation de yt-dlp.

Vous pouvez filtrer sur le nom d’un artiste et passer tous les fichiers en réultant à mpv à la chaîne.

grep M83 playlist.m3u | xargs -d'\n' mpv

Lira toutes les chansons d’M83 de la playlist.

J’utilise plus récemment fzy pour ce genre de besoins. fzy est une commande prenant dans stdin du texte, présentant chaque ligne dans un petit menu interactif et écrivant dans stdout le contenu de la ligne que l’on a selectionné. On peut y écrire une recherche qui s’effectuera sur la liste d’éléments. L’algorithme de recherche est dit “fuzzy”. On peut le voir comme une sorte de grep fuzzy interactif. J’utilise ce fork qui a l’avantage de permettre la multi-sélection. Un exemple d’usage simple de fzy dans notre cas pour faire une recherche dans notre playlist serait :

cut -f1 playlist.m3u |
    fzy -m |
    sed 's,^,/chemin/vers/le/dossier/avec/les/fichiers/audio' |
    xargs -d'\n' mpv

> pour passer à la chanson suivante
< pour passer à la chanson précédente
0 pour augmenter le volume
9 pour baisser le volume

Si vous utilisez beaucoup ce système vous verrez que le script ne télécharge pas toujours la chanson que vous voulez. Sur ma playlist le taux d’erreur est d’environ 5%. Elles sont majoritairement dues au fait que le premier résultat de la recherche youtube n’est pas toujours la version spécifique que vous cherchez de cette chanson. J’estime que les erreurs sont suffisament rares pour être corrigées “à la main”. Je fais une recherche youtube, récupère l’url de la version que je cherche et exécute le téléchargement moi-même. Il est assez fréquent que si le premier résultat youtube n’est pas celui que vous cherchez, le second sera le bon. Pour automatiser un peu cette affaire on peut donc imaginer noter les titres des chansons qui posent problème dans un fichier et les télécharger mais en choisissant la seconde option à chaque fois. Le filtre ne sera donc plus

ytcli "M83 - Highway of Endless Dreams" | grep -m1 URL: | sed 's/URL: \+//'

mais

ytcli "M83 - Highway of Endless Dreams" | grep -m2 URL: | tail -n1 | sed 's/URL: \+//'

On peut facilement imaginer la première version être présente dans un script ou un alias et la seconde dans un autre script ou un autre alias nommé “correction”.

Ajouter un morceau revient simplement à écrire une nouvelle ligne dans notre fichier de playlist. L’emplacement dans le fichier determinera quand il sera lu. Ajouté tout en haut du fichier il sera lu en premier, tout en bas il sera lu en dernier etc. Ensuite si vous relancez le téléchargement avec la commande vue précédemment vous retéléchargerez toutes les chansons. Trois façon de se prémunir de cela :

  1. Vous filtrez le fichier de playlist pour n’inclure que les chansons que vous venez d’ajouter.

Par exemple si vous avez ajouté deux chansons au début du fichier, commencez par un head -n2 plutôt qu’un cat. Il faudra ajouter un tee quelque part pour écrire un fichier temporaire ne contenant que les fichiers filtrés sinon le paste sera bancale. Exemple :

head -n2 playlist.m3u |
    tee temp |
    xargs -d'\n' -n1 sh -c 'ytcli "$1" | grep -m1 URL: | sed "s/URL: \+//"' -- |
    paste temp - |
    sed 's/ /\n/' |
    xargs -d'\n' -n2 sh -c 'yt-dlp -f worstaudio -o "$1" "$2"' --
rm temp
  1. Ajoutez l’option --no-overwrites à yt-dlp.

Avec cete option yt-dlp vérifiera si un fichier au nom que vous voulez donner au nouveau téléchargement existe déjà. Si oui alors yt-dlp sautera le téléchargement. Cependant il téléchargera quand même la page web de la vidéo. Ma théorie est que cela est nécessaire quand on ne donne pas le nom du fichier nous même. En effet, dans ce cas yt-dlp doit d’abord récupérer quelques infos (le titre de la vidéo sur youtube notamment) pour savoir si le nom de fichier qu’il génèrera pour le nouveau téléchargement sera le même qu’un fichier déjà existant. Puisque l’on force le nom du fichier avec -o ce comportement n’a pas vraiment de sens, il suffirait pour yt-dlp de vérifier que l’argument donné à -o n’est pas le nom d’un fichier déjà existant et ce sans jamais avoir besoin d’obtenir quoi que ce soit comme information sur la vidéo.

  1. Pour remédier au souci de 2. on peut nous même filtrer le fichier playlist pour ne retenir que les titres non téléchargés - c’est à dire ceux qui n’ont pas de fichier à leur nom.

Pour cela nous allons utiliser une commande nommée comm :

sort playlist.m3u > temp
find * |
    comm -23 temp -
rm temp

En shell POSIX il n’est, je crois, pas possible de rediriger deux entrées dans une commande. Il nous faut donc créer un fichier intermédiaire temp pour contenir les titres des chansons de la playlist triées par ordre alphabétique. On compare ensuite ce contenu avec les chemins des fichiers du dossier local et on n’affiche que ce qui est unique au fichier playlist.m3u. comm construit des données sous la forme de trois colonnes. La première est tout ce qui est unique au premier fichier, la seconde au second et la troisième ce qui est commun au deux fichiers. Ici on passe temp - c’est à dire le contenu du fichier playlist.m3u - en premier. C’est bien ce qui existe dans ce fichier et pas dans le dossier que l’on veut récupérer. On utilise donc les options -2 et -3 que l’on peut concatener en -23 pour dire à comm de supprimer la deuxième et la troisième colonne du résultat. Finalement on supprime le fichier temporaire.

En réalité ce filtre pourrait être celui par défaut. Si c’est la première fois que vous déclarez la playlist il permettra de tout télécharger. Si jamais vous ajoutez quoi que ce soit il permettra de télécharger les nouveautés. Attention si vous modifiez le nom d’une chanson dans le fichier sans modifier le nom du fichier audio correspondant vous retéléchargerez la chanson. Si vous supprimez un fichier ce filtre ne permettra rien. En somme cela ne permet une synchronisation qu’en ajout.

Même approche que pour l’ajout mais avec des options différentes pour comm

sort playlist.m3u > temp
find * |
    comm -13 temp - |
    grep -v "playlist.m3u" |
    xargs -d'\n' rm

Cette fois-ci c’est ce qui se trouve uniquement dans le dossier et plus dans le fichier que l’on souhaite. On utilise donc les options -13. On ajoute également un grep pour éviter d’inclure les fichiers playlist.m3u dans le lot. En effet ce fichier existe bien dans le dossier sans pour autant être dans la playlist mais nous ne voudrions pas le supprimer. On pipe le tout dans un xargs pour supprimer les fichiers correspondants.

J’utilise fzy, voir ce que j’ai écrit plus haut, sous le point “Si vous voulez n’écouter qu’une sous partie de la playlist”.

J’ai récemment eu l’envie de classifier les chansons d’une playlist en fonction de certains thèmes. Pour cela on pourrait créer autant de playlist différentes, c’est tout à fait naturel. Cela ferait autant de fichiers. Alternativement si vous souhaitez classer les chansons au sein d’une même playlist nous pouvons ajouter des tags avec la syntaxe artiste - titre[tabulation]tag1 tag2 tag3.... Cela donne par exemple :

Fistaille - 13h12   acab
Maya Dunietz - The wine of love (feat. David Lemoine)
AURORA, Pomme - Everything Matters  sadgirl
Edouard Ferlet - Reflex
Emile Londonien - Missing Arrow jazz
Emile Londonien - Covered Bridges   jazz
Sampa the great - Never Forget  hiphop
Fred again... - Marea   dance electro
Sampa the Great - Shadows   hiphop
Sébastien Tellier - L'amour et la violence
DOMi & JD BECK - SMiLE  jazz
Brutalist - Movements   dance electro
Shubh Saran - Enculture
Gala - Freed From Desire    dance
Mara, Sleazy Stereo - Foufoune  dance hiphop

On peut ensuite faire un grep pour filtrer sur un tag

grep -i "   .*dance.*" playlist.m3u

ce qui renvoie

Fred again... - Marea   dance electro
Brutalist - Movements   dance electro
Gala - Freed From Desire    dance
Mara, Sleazy Stereo - Foufoune  dance hiphop

et pourra être lu dans mpv en pipant tout ça

grep -i "   .*dance.*" playlist.m3u | cut -f1 | shuf | xargs -d'\n' mpv

Le petit shuf pour désordonner le résultat.
Attention, avec ce système faire mpv playlist.m3u ne fonctionnera plus pour les chansons sur lesquelles vous avez mis un tag puisqu’il n’existera pas de fichier avec un nom correspondant (“Fistaille - 13h12 acab” n’est pas le fichier que l’on souhaite lire). Il faut donc adapter vos alias et le script de synchro de façon à omettre les tags. Ça tombe bien, cela revient à piper le fichier dans cut -f1.

L’ajout de ce système de tag et cette courte documentation m’a pris quelques dizaines de minutes et a résulté en la modification et l’écriture de quatre lignes de codes (ajout de trois cut -f1 et écriture d’un nouvel alias pour filtrer sur les tags).

Pour télécharger cet outil :

git clone git://katzele.netlib.re/fip

Les instructions d’usage sont dans le README.
Si votre alias pour lancer la lecture est fip vous pouvez faire ceci

fip | tee session

pour enregistrer les informations de toutes les chansons diffusées dans le fichier session. Vous pouvez ensuie télécharger les chansons comme nous l’avons vu précédemment. Si vous kiffez ce que vous êtes en train d’écouter à l’instant vous pouvez aussi ouvrir votre fichier de playlist dans vim, taper

tail -n1 chemin/vers/session

et l’exécuter avec :.!sh pour directement récupérer les infos. Alternativement vous pouvez aliaser cette commande :

sed -i "1 s/^/$(tail -n1 /chemin/vers/session)\n/" /chemin/vers/playlist.m3u

L’outil concerts est disponible avec la commande suivante :

git clone git://katzele.netlib.re/concerts-light

Avec on peut faire le croisement des données et savoir quand et où passe un artiste de votre playlist :

cut -f1 playlist.m3u |
    cut -f1 -d- |
    sed 's/ *$//' |
    sort -u |
    sed 's/, /\n/g' |
    xargs -n1 -d'\n' sh -c 'grep "$1" emplacement_des_données_des_concerts' --

Ou un peu plus performant sur des gros fichiers

concerts=$(cut -f2 emplacement_données_concerts | sed 's/, /\n/g' | sort -u)
artists=$(cut -f1 emplacement_fichier_playlist | cut -f1 -d- | sed 's/ *$//' | sed 's/, /\n/g' | sort -u)
echo $concerts $artists |
    sort |
    uniq -d

Côté performance quand il s’agit de croiser des données entre deux sources il est souvent préférable de jouer sur le tri et la détéction de doublons plutôt que de faire des recherches à répétition.

Synchronisation

Une fonctionnalité pratique de spotify est la synchronisation des playlists sur plusieurs terminaux. J’estime que cette fonctionnalité est suffisamment utile pour être répliquée. L’information de la playlist est entièrement détenue dans le fichier playlist.m3u. J’ai donc opté pour un dépôt git, hébergé sur un serveur distant, avec pour .gitignore

*
!.gitignore
!playlist.m3u

de façon à ne tracker que la playlist et le .gitignore. Quand j’arrive sur un nouveau terminal je fais un git pull et je lance mon script de synchro. Pour économiser de la bande passante il reste préférable de transférer les fichiers audios par clef usb.

Migration depuis spotify

Si vous avez de très grandes playlists spotify j’ai écrit quelques scripts pour récupérer les infos des titres. Pour les télécharger :

git clone git://katzele.netlib.re/downloadmusic

Les instructions d’usage sont dans le README. A noter, cela fait un moment que je n’ai pas testé les scripts de migration, ils peuvent ne plus fonctionner.

L’existant

Il existe déjà des outils permettant de télécharger des musiques depuis youtube en fonction d’une playlist spotify, notamment spotdl. J’ai tout de même voulu en faire ma propre version parce que spotdl

Parmi les fonctionnalités supplémentaires qui pourraient vous intéresser, spotdl peut :


  1. non sans adaptation, certains chemins sont en dur 

  2. Ce qui ne veut pas nécessairement dire que ce sera le fichier le plus petit. Pour que worst corresponde effectivement au stream avec le bitrate le plus faible il faut redéfinir le critère de “qualité” sur la taille avec -S