arthur.bebou

Le site arthur.bebou.netlib.re - retour accueil

git clone git://bebou.netlib.re/arthur.bebou
Log | Files | Refs |

index.sh (33234B)


      1 #! page
      2 
      3 title: Gestion simpliste de playlist et migration depuis Spotify
      4 author: Arthur Pons
      5 description: Comment gérer une playlist musicale avec des outils numériques possiblement sobres et conviviaux ?
      6 publication: 2022-12-11
      7 sectionmd: main
      8 
      9 
     10 Le code qui résulte de toute cette exploration est accesible dans le dépôt
     11 `downloadmusic` en ce qui concerne la synchronisation playlist <-> fichiers
     12 audio
     13 
     14 	git clone git://katzele.netlib.re/downloadmusic
     15 
     16 et dans 
     17 
     18 	git clone git://katzele.netlib.re/zenu-arthur
     19 
     20 en ce qui concerne les commandes que j'utilise fréquemment pour lire,
     21 filtrer, synchroniser le tout. Elles sont dans les fichiers de menu `zenu`
     22 (article sur le sujet à venir) `playlist` et `filtrer`.
     23 
     24 Il vous est possible de directement utiliser ce code là[^2], mais je vous
     25 recommande de lire l'article pour savoir d'où il vient et construire votre
     26 système selon vos besoins. J'ai peut-être fait des choses plus compliquées
     27 et nécessitant plus de dépendances que ce dont vous avez réellement besoin.
     28 
     29 ## Le problème
     30 
     31 Depuis que je m'organise pour pouvoir faire la (quasi) totalité de mes
     32 activités numériques sur un raspberry ou équivalent je sais qu'inévitablement
     33 il va falloir que je m'occupe de spotify. Il y a deux façons traditionnelles de
     34 consommer de la musique sur ce service :
     35 
     36 1. accéder au contenu via spotify.com
     37 2. accéder au contenu via l'application desktop
     38 
     39 Il est préférable de ne pas passer par un navigateur web pour écouter de la
     40 musique. En effet, de très nombreuses applications savent déjà le faire et de
     41 façon bien plus efficace. À l'inverse les navigateurs webs ne sont
     42 originellement pas conçus pour. De manière générale il serait opportun, pour
     43 réduire les coûts (de quelques natures qu'ils soient), de ne pas utiliser le
     44 web pour autre chose que de s'échanger des documents html. Je ne redéveloppe
     45 pas tout l'argumentaire expliquant pourquoi et comment, cela a déjà été fait
     46 maintes fois. Si vous peinez à trouver des ressources dessus contactez moi !
     47 
     48 L'application desktop rencontre le même souci puisqu'elle est basée sur la
     49 technologie [electron] qui fait usage de la stack technique des navigateurs
     50 web. Cet état de fait condamne une personne utilisant un ordinateur peu
     51 puissant à ne pas pouvoir utiliser spotify. J'imagine que c'est au moins en
     52 partie pour cette raison qu'un ensemble de clients tiers est apparu. Pour en
     53 lister deux :
     54 
     55 * [spotify-tui], une interface textuelle dans la console, écrite en rust
     56 * [Psst], une interface graphique, écrite en rust
     57 
     58 Ces deux logiciels sont bien des interfaces, elles ne remplacent pas le backend
     59 de spotify. Pour pouvoir les utiliser et écouter de la musique avec il vous
     60 faudra utiliser [spotifyd] qui s'occupera d'aller streamer la musique depuis
     61 spotify. Les interfaces contrôleront spotifyd pour lui dire de passer la
     62 chanson, monter le volume etc. Pour avoir testé ces deux solutions il y a un an
     63 environ elles fonctionnent et sont effectivement beaucoup plus légères mais
     64 rencontrent d'assez nombreux problèmes/bug. Je ne vais pas prendre le temps de
     65 les lister, j'ai simplement le souvenir qu'à force de frustration j'ai décidé
     66 de réutiliser l'appli desktop sur mes terminaux relativement puissants.
     67 
     68 J'étais donc rendu au point de départ. Il se trouve qu'il y a d'autres raisons
     69 de vouloir se débarrasser de spotify, notamment le [DRM ou Gestion des Droits
     70 Numériques]. Le DRM, c'est pas bien. Les alternatives sont :
     71 
     72 * Écouter la musique sur youtube ou une autre plateforme "ouverte" (quoi
     73   qu'avec un bloqueur de pub c'est kifkif ?)
     74 * Acheter la musique
     75 * Le piratage
     76 
     77 Le piratage c'est pas bien, [vous ne voleriez pas une voiture n'est-ce pas] ?
     78 Cependant, si l'on veut rester sur quelque chose d'aussi simple que Spotify
     79 j'ai le sentiment que le piratage, notamment télécharger de la musique que l'on
     80 trouve sur youtube, est la meilleure solution. Je dois préciser que cette
     81 réflexion de ma part est certainement regrettable. Je pense que je me suis fait
     82 à la relative simplicité de l'usage de spotify ce qui m'incite à ne pas
     83 chercher à acheter la musique. Ces achats devraient se faire dans des lieux
     84 différents, auraient des formats différents etc. J'ai consenti à faire des
     85 efforts supplémentaire dans d'autres domaines de ma vie quand je sais que cela
     86 réduit considérablement les coûts sociaux et environnementaux mais je me voyais
     87 mal le faire dans celui-ci. Du moins pas tout de suite.
     88 
     89 ## Mon usage de spotify
     90 
     91 D'abord je décris l'usage que j'en fais. Si votre usage est très différent
     92 peut-être que ce que j'ai pensé ne vous conviendra pas du tout. J'utilise
     93 spotify de trois façons différentes.
     94 
     95   * Playlist "Liked Songs" (en anglais)
     96 
     97 Je découvre de la musique à travers des ami·e·s, en écoutant la radio, en
     98 allant en soirée, festival, concert ou beaucoup plus rarement en utilisant les
     99 recommandations spotify. Je fais une recherche sur spotify, j'écoute et je
    100 "like" ce que j'apprécie. J'écoute la playlist "Liked Songs" produite dans
    101 l'ordre antéchronologique ou en aléatoire.
    102 
    103   * Ecoute plus spécifique
    104 
    105 J'ai une envie très particulière d'écouter un ou une artiste, je fais une
    106 recherche spécifique et j'écoute, généralement des albums en entier.
    107 
    108   * Ecoute en soirée
    109 
    110 J'ouvre l'interface spotify sur mon pc et je laisse les personnes mettre la
    111 musique qu'elles souhaitent.
    112 
    113 J'ai un usage assez restreint des playlists en dehors de celle générée par les
    114 titres que je like. Au vu de ces usages je me suis construit un petit système
    115 pour répliquer une partie de mon usage de spotify.
    116 
    117 ## shell + ytcli + yt-dlp + mpv + git
    118 
    119 Pour économiser de la bande passante et pouvoir écouter de la musique sans
    120 avoir besoin d'internet, comme lorsque l'on télécharge la musique en local sur
    121 spotify, il faut pouvoir télécharger les morceaux. Je choisis de le faire
    122 depuis youtube du fait de la taille du catalogue disponible sur cette
    123 plateforme. Si vous avez déjà lu [l'article sur ma façon de lire des vidéos
    124 youtube] vous savez que l'on peut télécharger des vidéos youtube avec [yt-dlp].
    125 Puisque yt-dlp permet d'accéder à tous les formats disponibles, il est possible
    126 de télécharger uniquement l'audio d'une vidéo.
    127 
    128 Pour faire simple on peut utiliser les formats "dynamiques" de yt-dlp. Le
    129 format `worstaudio` sélectionnera toujours le format audio de moins bonne
    130 qualité[^1]. Le format `bestaudio` fera l'inverse. Puisque que l'on
    131 souhaite écouter de la musique et que par ailleurs youtube n'héberge pas des
    132 formats audio de très grande taille, le format `bestaudio` me semble adapté à
    133 notre besoin. Ainsi, si l'on souhaite télécharger la musique
    134 `https://www.youtube.com/embed/WBsIKQEGQ_A` on peut lancer la commande
    135 
    136 	yt-dlp -f bestaudio https://www.youtube.com/embed/WBsIKQEGQ_A
    137 
    138 et obtenir un fichier de 3,96Mo nommé "Mop Mop - Jamajumba [WBsIKQEGQ_A].webm".
    139 Si votre morale ou vos contraintes techniques vous imposent de télécharger des
    140 formats plus petits regardez le manuel de yt-dlp pour choisir un format
    141 différent. Pour changer le nom du fichier on peut utiliser l'option `-o` qui
    142 prendra en argument une chaine de caractère. Si l'on récupère quelques liens de
    143 la sorte et que l'on télécharge quelques musiques, construire une playlist
    144 revient à créer un fichier avec la liste des chemins vers les fichiers audios.
    145 
    146 Par exemple, vous pouvez avoir l'arborescence suivante :
    147 
    148 	/home/vous/playlist
    149 	├── Inüit - Hush
    150 	├── Iron Maiden - Phantom Of The Opera - 1998 Remastered Version
    151 	├── King Gizzard & The Lizard Wizard - Inner Cell
    152 	├── Marc Rebillet - VACCINATED ATTITUDE
    153 	├── playlist.m3u
    154 	├── Souad Massi - Mirage (feat. Piers Faccini)
    155 	├── The Notorious B - Big Poppa - 2007 Remaster
    156 	├── Weval - Half Age
    157 	├── Yom - Longing for the Beat
    158 	└── Yuksek, Her - Sweet Addiction - Live Edit
    159 
    160 Avec le contenu de `playlist.m3u` étant :
    161 
    162 	Inüit - Hush
    163 	Iron Maiden - Phantom Of The Opera - 1998 Remastered Version
    164 	King Gizzard & The Lizard Wizard - Inner Cell
    165 	Marc Rebillet - VACCINATED ATTITUDE
    166 	Souad Massi - Mirage (feat. Piers Faccini)
    167 	The Notorious B - Big Poppa - 2007 Remaster
    168 	Weval - Half Age
    169 	Yom - Longing for the Beat
    170 	Yuksek, Her - Sweet Addiction - Live Edit
    171 
    172 Et il suffira de faire
    173 
    174 	mpv playlist.m3u
    175 
    176 ou
    177 
    178 	vlc playlist.m3u
    179 
    180 pour lire toute la playlist dans l'ordre du fichier. Pour la suite je prendrai
    181 mpv pour exemple parce que c'est ce que j'utilise. On peut lancer la playlist
    182 avec :
    183 
    184 mpv --no-audio-display --volume=50 chemin/vers/la/playlist.m3u
    185 
    186 `--no-audio-display` permet de garantir qu'mpv n'ouvrira pas d'interface
    187 graphique, `--volume=50` de ne pas péter mes oreilles par défaut.
    188 
    189 Si l'on veut jouer la playlist de façon aléatoire, deux solutions. Soit on
    190 utilise l'option `--shuffle` d'mpv soit on mélange le contenu du fichier avec
    191 `shuf` :
    192 
    193 	shuf playlist.m3u | xargs -d'\n' mpv
    194 
    195 J'aurais tendance à favoriser l'utilisation de `shuf`. C'est un outil
    196 agnostique que l'on pourra réutiliser à chaque fois qu'il faut mélanger un
    197 fichier. A l'inverse `--shuffle` ne fait sens que dans le cadre d'mpv.
    198 Philo Unix, acquisition de savoirs génériques, etc.
    199 
    200 > J'utilise beaucoup `xargs`, c'est une commande vraiment puissante. Un jour je
    201 > ferai un court article pour expliquer comment elle fonctionne (ou du moins
    202 > l'usage que j'en fais). En attendant sachez qu'ici cela exprime l'idée "prend
    203 > chaque élément rendu par `shuf playslist.m3u` séparé par une retour à la ligne
    204 > (chaque ligne donc) et fais-en un argument à la commande mpv. Cela revient donc
    205 > à lancer la commande `mpv titre1 titre2 titre3 titre4`.
    206 
    207 Tout cela est bien sympa mais comment fait-on si l'on a des playlists de
    208 plusieurs centaines chansons, on va quand même pas chercher les liens sur
    209 youtube à la main et lancer les commandes yt-dlp une par une ?
    210 
    211 Non effectivement, on peut l'automatiser. Ce ne sera pas sans erreurs mais le
    212 gain de temps sera tout de même considérable. Pour automatiser les recherches
    213 youtube nous allons utiliser un outil disponible dans le dépôt [frontends] de
    214 codemadness. On y retrouve, dans le dossier youtube, le nécessaire pour
    215 compiler un binaire nommé `cli` qui permet de faire des recherches youtube et
    216 de récupérer les résultats dans la console sous format texte. Dans le reste de
    217 cet article je nommerai `cli` `ytcli` pour plus de clarté.
    218 
    219 > il est possible que vous ayez des difficultés à compiler ytcli et il est
    220 > préférable de légèrement le modifier pour notre besoin. Je ferai un petit tuto
    221 > à l'avenir pour les personnes que ça intéresse TODO
    222 
    223 `ytcli` s'utilise simplement en lui donnant en argument le sujet de notre
    224 recherche, comme si c'était la boite de recherche sur youtube.com. Par exemple,
    225 si l'on veut chercher le morceau Highway of Endless Dreams d'M83 on pourrait
    226 faire :
    227 
    228 	ytcli "M83 - Highway of Endless Dreams"
    229 
    230 et cela imprime
    231 
    232 	M83 - Highway of Endless Dreams (audio)
    233 	URL:           https://www.youtube.com/embed/iqNohjW_kWc
    234 	Atom feed:     https://www.youtube.com/feeds/videos.xml?channel_id=UC8WbdD3m5dP9giOU9XtAGWQ
    235 	Channel title: M83
    236 	Channelid:     UC8WbdD3m5dP9giOU9XtAGWQ
    237 	Published:     7 years ago
    238 	Viewcount:     138,424 views
    239 	Duration:      4:37
    240 	===
    241 	M83   Highway Of Endless Dreams
    242 	URL:           https://www.youtube.com/embed/HXUKHZ9wwNw
    243 	Atom feed:     https://www.youtube.com/feeds/videos.xml?channel_id=UCynAa3zrpJlU4WjxiBe4qrg
    244 	Channel title: inner silence
    245 	Channelid:     UCynAa3zrpJlU4WjxiBe4qrg
    246 	Published:     8 years ago
    247 	Viewcount:     29,162 views
    248 	Duration:      4:36
    249 	===
    250 	M83 "Highway of Endless Dreams,  Skin of the Night,+" live on 6.6.2008 in Philadelphia, PA.
    251 	URL:           https://www.youtube.com/embed/6SQkmxjUpzc
    252 	Atom feed:     https://www.youtube.com/feeds/videos.xml?channel_id=UCv8I0sTv7aaelMbd3OQEdAw
    253 	Channel title: Not All Punk & Games
    254 	Channelid:     UCv8I0sTv7aaelMbd3OQEdAw
    255 	Published:     6 years ago
    256 	Viewcount:     4,547 views
    257 	Duration:      18:35
    258 	...
    259 
    260 Ces résultats ne sont pas inventés par ytcli, ce sont très exactement les mêmes
    261 que ceux que vous auriez obtenu si vous aviez fait la recherche sur youtube.com
    262 dans un navigateur. `ytcli` ne fait que remanier les données pour les imprimer
    263 sous forme textuelle. Dans la grande majorité des cas le premier résultat est
    264 celui que l'on veut. Pour rappel notre but est d'automatiser le fait de lancer
    265 des commandes de téléchargement telle que celle que l'on a vu précédemment.
    266 
    267 	yt-dlp -f bestaudio https://www.youtube.com/embed/WBsIKQEGQ_A
    268 
    269 Il nous faut donc récupérer le premier lien du premier résultat. A priori, tant
    270 que l'on ne modifie pas `ytcli` cette donnée se trouvera toujours sur la première
    271 ligne commençant par `URL:` ligne. On peut donc récupérer le nécessaire avec ce
    272 coup de grep et de sed :
    273 
    274 	ytcli "M83 - Highway of Endless Dreams" | grep -m1 URL: | sed 's/URL: \+//'
    275 
    276 Maintenant que l'on a un moyen de récupérer le lien du premier résultat d'une
    277 recherche youtube on peut les enchaîner. Notre donnée d'entrée sera la liste
    278 des chansons :
    279 
    280 	cat playlist.m3u
    281 	Inüit - Hush
    282 	Iron Maiden - Phantom Of The Opera - 1998 Remastered Version
    283 	King Gizzard & The Lizard Wizard - Inner Cell
    284 	Marc Rebillet - VACCINATED ATTITUDE
    285 	Souad Massi - Mirage (feat. Piers Faccini)
    286 	The Notorious B - Big Poppa - 2007 Remaster
    287 	Weval - Half Age
    288 	Yom - Longing for the Beat
    289 	Yuksek, Her - Sweet Addiction - Live Edit
    290 
    291 On automatise les recherches :
    292 
    293 	cat playlist.m3u | xargs -d'\n' -n1 ytcli
    294 
    295 > Pour xargs ici le `-n1` permet d'indiquer que l'on ne veut qu'un argument par
    296 > commande. Au lieu de lancer `ytcli titre1 titre2 titre3` ce sont les commandes
    297 > `ytcli titre1` puis `ytcli titre2` puis `ytcli titre3` qui seront exécutées.
    298 
    299 Comme fait précedemment on voudrait récupérer le premier lien de chaque
    300 recherche sauf que nous obtenons tous les résultats d'un coup dans l'ordre :
    301 
    302 
    303 Nous ne pouvons donc plus simplement retenir le premier lien puisque le premier
    304 de la seconde chanson sera quelque part bien plus bas dans le flux. Les données
    305 ressemblent à ça :
    306 
    307 	recherche 1 - résultat 1
    308 	recherche 1 - résultat 2
    309 	recherche 1 - résultat 3
    310 	recherche 2 - résultat 1
    311 	recherche 2 - résultat 2
    312 	recherche 2 - résultat 3
    313 	recherche 3 - résultat 1
    314 	recherche 3 - résultat 2
    315 	recherche 3 - résultat 3
    316 	etc.
    317 
    318 notre `grep -m1 URL:` omettrait toutes les chansons venant après la première
    319 recherche. Il nous faut opérer le `grep` et le `sed` sur chaque "bloc" de
    320 résultats. Pour cela la commande exécutée par xargs doit contenir elle même les
    321 filtres.
    322 
    323 	cat playlist.m3u | xargs -d'\n' -n1 sh -c 'ytcli "$1" | grep -m1 URL: | sed "s/URL: \+//"' --
    324 
    325 > Pour faire en sorte que la commande exécutée par xargs puisse enchaîner des
    326 > pipes sans que ce soit la sortie d'xargs elle même qui soit pipée on lance un
    327 > subshell avec la commande `sh -c`. L'option `-c` permet de dire au subshell
    328 > de lire ses commandes non pas depuis `stdin` mais depuis la chaîne de
    329 > caractère qui suivra dans les arguments. On écrit donc la commande qui nous
    330 > intéresse entre simple cotte en positionnant l'argument `$1` au bon endroit.
    331 > Une fois la commande finie on ferme la simple cotte. Viennent ensuite les
    332 > arguments de cette commande. Par convention le permier argument sera `$0` qui
    333 > contient tradtionnellement le chemin du script exécuté. Puisque qu'ici il n'y
    334 > a pas fichier de script il faut choisir `$0` "à la main". Viennent ensuite
    335 > les arguments `$1`, `$2` etc. C'est pour "sauter" `$0` que l'on met les "--".
    336 > Ainsi on s'assure que l'argument passé par `xargs` ne terminera pas dans `$0`
    337 > (puisqu'il aura déjà pour valeur --) mais bien dans `$1`.
    338 
    339 On récupère la liste :
    340 
    341 	https://www.youtube.com/embed/NZHUCu8ggpY
    342 	https://www.youtube.com/embed/VnDNXbDjPis
    343 	https://www.youtube.com/embed/G3JeZDps7O8
    344 	https://www.youtube.com/embed/qeCwwYjf8gw
    345 	https://www.youtube.com/embed/1qnKfnGFuSU
    346 	https://www.youtube.com/embed/QceVTChhlJM
    347 	https://www.youtube.com/embed/wDRp0KjJ9ds
    348 	https://www.youtube.com/embed/ptJ2fIzksIc
    349 	https://www.youtube.com/embed/qWMP-UxSEss
    350 
    351 Il ne reste plus qu'à les télécharger :
    352 
    353 	cat playlist.m3u |
    354 		xargs -d'\n' -n1 sh -c 'ytcli "$1" | grep -m1 URL: | sed "s/URL: \+//"' -- |
    355 		xargs -n1 yt-dlp -f bestaudio
    356 
    357 > pas besoin de préciser le délimiteur `-d'\n'` ici puisque le démiliteur par
    358 > défaut d'xargs est l'espace et que les liens n'en contiennent pas.
    359 
    360 Il existe dorénavant, dans le dossier ou nous nous trouvons, les fichiers
    361 
    362 	./Big Poppa (2007 Remaster) [QceVTChhlJM].webm
    363 	./Phantom of the Opera (1998 Remaster) [VnDNXbDjPis].webm
    364 	./VACCINATED ATTITUDE [qeCwwYjf8gw].webm
    365 	./Longing for the Beat [ptJ2fIzksIc].webm
    366 	./Inner Cell [G3JeZDps7O8].webm
    367 	./Souad Massi - Mirage feat. Piers Faccini (Carte Blanche Culturebox) [1qnKfnGFuSU].webm
    368 	./Weval - Half Age [wDRp0KjJ9ds].webm
    369 	./INÜIT - HUSH [LIVE] [NZHUCu8ggpY].webm
    370 	./Sweet Addiction - live edit [qWMP-UxSEss].webm
    371 
    372 Problème ! Si l'on lance la commande `mpv playlist.m3u` aucune chanson ne se
    373 lancera. Pourquoi ? En lisant le fichier playlist.m3u mpv va chercher à ouvrir le
    374 fichier `Inuit - Hush` mais celui-ci a été nommé `INÜIT - HUSH [LIVE]
    375 [NZHUCu8ggpY].webm` par yt-dlp, c'est à dire `titre de la vidéo youtube
    376 [identifiant de la vidéo].[format du fichier audio]`. Comme précisé plus tôt on
    377 peut y remédier avec l'option `-o
    378 
    379 	cat playlist.m3u |
    380 		xargs -d'\n' -n1 sh -c 'ytcli "$1" | grep -m1 URL: | sed "s/URL: \+//"' -- |
    381 		paste playlist.m3u - |
    382 		sed 's/	/\n/' |
    383 		xargs -d'\n' -n2 sh -c 'yt-dlp -f bestaudio -o "$1" "$2"' --
    384 
    385 On aura utilisé `paste` pour pouvoir donner en entrée à xargs à la fois le nom
    386 du fichier voulu *et* l'url de la vidéo à télécharger ainsi qu'une substitution
    387 pour simplifier leur ingestion par xargs.
    388 
    389 Nous avons dorénavant un format de fichier pour déclarer une playlist, un moyen
    390 de télécharger toutes les musiques s'y trouvant et un moyen pour lire la dite
    391 playlist. L'essentiel est là. Evidemment vous pourriez vouloir appeler les
    392 fichiers différèmment, sélectionner la second résultat youtube, choisir une
    393 autre qualité si vous êtes sur une mauvaise connexion par exemple, parraléliser
    394 les téléchargements. Notre commande est suffisament flexible et courte pour
    395 pouvoir faire tout cela.
    396 
    397 ### Astuces d'usage :
    398 
    399 * Si vous voulez que `yt-dlp` n'écrive pas un roman à chaque téléchargement
    400 
    401 Utilisez l'option `--quiet`. Si vous voulez tout de même avoir un retour sur ce
    402 qu'il se passe vous pouvez modifier la commande de la sorte :
    403 
    404 * Si vous voulez télécharger l'audio en moins bonne qualité
    405 
    406 Vous pouvez opter pour le format `worstaudio`.
    407 
    408 Il existe pleins d'options différentes pour choisir très précisèment le format
    409 que l'on veut. On peut jouer sur la taille du fichier, le codec, le conteneur,
    410 le bitrate etc. Pour plus de détails voir la [documentation de yt-dlp].
    411 
    412 * Si vous voulez n'écouter qu'une sous partie de la playlist
    413 
    414 Vous pouvez filtrer sur le nom d'un artiste et passer tous les fichiers en
    415 réultant à mpv à la chaîne.
    416 
    417 	grep M83 playlist.m3u | xargs -d'\n' mpv
    418 
    419 Lira toutes les chansons d'M83 de la playlist.
    420 
    421 J'utilise plus récemment `fzy` pour ce genre de besoins. `fzy` est une commande
    422 prenant dans stdin du texte, présentant chaque ligne dans un petit menu
    423 interactif et écrivant dans stdout le contenu de la ligne que l'on a selectionné.
    424 On peut y écrire une recherche qui s'effectuera sur la liste d'éléments.
    425 L'algorithme de recherche est dit "fuzzy". On peut le voir comme une sorte de
    426 grep fuzzy interactif. J'utilise [ce fork] qui a l'avantage de permettre la
    427 multi-sélection. Un exemple d'usage simple de `fzy` dans notre cas pour faire
    428 une recherche dans notre playlist serait :
    429 
    430 	cut -f1 playlist.m3u |
    431 		fzy -m |
    432 		sed 's,^,/chemin/vers/le/dossier/avec/les/fichiers/audio' |
    433 		xargs -d'\n' mpv
    434 
    435 * Si vous utilisez mpv, quelques raccourcis utiles
    436 
    437 `>` pour passer à la chanson suivante\
    438 `<` pour passer à la chanson précédente\
    439 `0` pour augmenter le volume\
    440 `9` pour baisser le volume
    441 
    442 * Si vous constatez des erreurs
    443 
    444 Si vous utilisez beaucoup ce système vous verrez que le script ne télécharge
    445 pas toujours la chanson que vous voulez. Sur ma playlist le taux d'erreur est
    446 d'environ 5%. Elles sont majoritairement dues au fait que le premier résultat
    447 de la recherche youtube n'est pas toujours la version spécifique que vous
    448 cherchez de cette chanson. J'estime que les erreurs sont suffisament rares pour
    449 être corrigées "à la main". Je fais une recherche youtube, récupère l'url de la
    450 version que je cherche et exécute le téléchargement moi-même. Il est assez
    451 fréquent que si le premier résultat youtube n'est pas celui que vous cherchez,
    452 le second sera le bon. Pour automatiser un peu cette affaire on peut donc
    453 imaginer noter les titres des chansons qui posent problème dans un fichier et
    454 les télécharger mais en choisissant la seconde option à chaque fois. Le filtre
    455 ne sera donc plus
    456 
    457 	ytcli "M83 - Highway of Endless Dreams" | grep -m1 URL: | sed 's/URL: \+//'
    458 
    459 mais
    460 
    461 	ytcli "M83 - Highway of Endless Dreams" | grep -m2 URL: | tail -n1 | sed 's/URL: \+//'
    462 
    463 On peut facilement imaginer la première version être présente dans un script ou
    464 un alias et la seconde dans un autre script ou un autre alias nommé
    465 "correction". 
    466 
    467 * Si vous voulez ajouter une ou plusieurs musiques
    468 
    469 Ajouter un morceau revient simplement à écrire une nouvelle ligne dans notre
    470 fichier de playlist. L'emplacement dans le fichier determinera quand il sera
    471 lu. Ajouté tout en haut du fichier il sera lu en premier, tout en bas il sera
    472 lu en dernier etc. Ensuite si vous relancez le téléchargement avec la commande
    473 vue précédemment vous retéléchargerez toutes les chansons. Trois façon de se
    474 prémunir de cela :
    475 
    476 1. Vous filtrez le fichier de playlist pour n'inclure que les chansons que vous
    477 venez d'ajouter.
    478 
    479 Par exemple si vous avez ajouté deux chansons au début du fichier, commencez
    480 par un `head -n2` plutôt qu'un `cat`. Il faudra ajouter un tee quelque part
    481 pour écrire un fichier temporaire ne contenant que les fichiers filtrés sinon
    482 le paste sera bancale. Exemple :
    483 
    484 	head -n2 playlist.m3u |
    485 		tee temp |
    486 		xargs -d'\n' -n1 sh -c 'ytcli "$1" | grep -m1 URL: | sed "s/URL: \+//"' -- |
    487 		paste temp - |
    488 		sed 's/	/\n/' |
    489 		xargs -d'\n' -n2 sh -c 'yt-dlp -f worstaudio -o "$1" "$2"' --
    490 	rm temp
    491 
    492 2. Ajoutez l'option `--no-overwrites` à yt-dlp.
    493 
    494 Avec cete option yt-dlp vérifiera si un fichier au nom que vous voulez donner
    495 au nouveau téléchargement existe déjà. Si oui alors yt-dlp sautera le
    496 téléchargement. Cependant il téléchargera quand même la page web de la vidéo.
    497 Ma théorie est que cela est nécessaire quand on ne donne pas le nom du fichier
    498 nous même. En effet, dans ce cas yt-dlp doit d'abord récupérer quelques infos
    499 (le titre de la vidéo sur youtube notamment) pour savoir si le nom de fichier
    500 qu'il génèrera pour le nouveau téléchargement sera le même qu'un fichier déjà
    501 existant. Puisque l'on force le nom du fichier avec `-o` ce comportement n'a
    502 pas vraiment de sens, il suffirait pour yt-dlp de vérifier que l'argument donné
    503 à `-o` n'est pas le nom d'un fichier déjà existant et ce sans jamais avoir
    504 besoin d'obtenir quoi que ce soit comme information sur la vidéo.
    505 
    506 3. Pour remédier au souci de 2. on peut nous même filtrer le fichier playlist
    507 pour ne retenir que les titres non téléchargés - c'est à dire ceux qui n'ont
    508 pas de fichier à leur nom.
    509 
    510 Pour cela nous allons utiliser une commande nommée `comm` :
    511 
    512 	sort playlist.m3u > temp
    513 	find * |
    514 		comm -23 temp -
    515 	rm temp
    516 
    517 > En shell POSIX il n'est, je crois, pas possible de rediriger deux entrées
    518 > dans une commande. Il nous faut donc créer un fichier intermédiaire `temp`
    519 > pour contenir les titres des chansons de la playlist triées par ordre
    520 > alphabétique. On compare ensuite ce contenu avec les chemins des fichiers du
    521 > dossier local et on n'affiche que ce qui est unique au fichier playlist.m3u.
    522 > `comm` construit des données sous la forme de trois colonnes. La première est
    523 > tout ce qui est unique au premier fichier, la seconde au second et la
    524 > troisième ce qui est commun au deux fichiers. Ici on passe `temp` - c'est à
    525 > dire le contenu du fichier `playlist.m3u` - en premier. C'est bien ce qui
    526 > existe dans ce fichier et pas dans le dossier que l'on veut récupérer. On
    527 > utilise donc les options `-2` et `-3` que l'on peut concatener en `-23` pour
    528 > dire à comm de supprimer la deuxième et la troisième colonne du résultat.
    529 > Finalement on supprime le fichier temporaire.
    530 
    531 En réalité ce filtre pourrait être celui par défaut. Si c'est la première fois
    532 que vous déclarez la playlist il permettra de tout télécharger. Si jamais vous
    533 ajoutez quoi que ce soit il permettra de télécharger les nouveautés. Attention
    534 si vous modifiez le nom d'une chanson dans le fichier sans modifier le nom du
    535 fichier audio correspondant vous retéléchargerez la chanson. Si vous supprimez
    536 un fichier ce filtre ne permettra rien. En somme cela ne permet une
    537 synchronisation qu'en ajout.
    538 
    539 * Si vous voulez supprimer une ou des musiques
    540 
    541 Même approche que pour l'ajout mais avec des options différentes pour `comm`
    542 
    543 	sort playlist.m3u > temp
    544 	find * |
    545 		comm -13 temp - |
    546 		grep -v "playlist.m3u" |
    547 		xargs -d'\n' rm
    548 
    549 > Cette fois-ci c'est ce qui se trouve uniquement dans le dossier et plus dans
    550 > le fichier que l'on souhaite. On utilise donc les options `-13`. On ajoute
    551 > également un grep pour éviter d'inclure les fichiers playlist.m3u dans le
    552 > lot. En effet ce fichier existe bien dans le dossier sans pour autant être
    553 > dans la playlist mais nous ne voudrions pas le supprimer. On pipe le tout
    554 > dans un xargs pour supprimer les fichiers correspondants.
    555 
    556 * Si vous voulez faire des recherches
    557 
    558 J'utilise fzy, voir ce que j'ai écrit plus haut, sous le point "Si vous voulez
    559 n'écouter qu'une sous partie de la playlist".
    560 
    561 * Si vous voulez avoir un système de tag
    562 
    563 J'ai récemment eu l'envie de classifier les chansons d'une playlist en fonction
    564 de certains thèmes. Pour cela on pourrait créer autant de playlist différentes,
    565 c'est tout à fait naturel. Cela ferait autant de fichiers. Alternativement si
    566 vous souhaitez classer les chansons au sein d'une même playlist nous pouvons
    567 ajouter des tags avec la syntaxe `artiste - titre[tabulation]tag1 tag2 tag3...`.
    568 Cela donne par exemple :
    569 
    570 	Fistaille - 13h12	acab
    571 	Maya Dunietz - The wine of love (feat. David Lemoine)
    572 	AURORA, Pomme - Everything Matters	sadgirl
    573 	Edouard Ferlet - Reflex
    574 	Emile Londonien - Missing Arrow	jazz
    575 	Emile Londonien - Covered Bridges	jazz
    576 	Sampa the great - Never Forget	hiphop
    577 	Fred again... - Marea	dance electro
    578 	Sampa the Great - Shadows	hiphop
    579 	Sébastien Tellier - L'amour et la violence
    580 	DOMi & JD BECK - SMiLE	jazz
    581 	Brutalist - Movements	dance electro
    582 	Shubh Saran - Enculture
    583 	Gala - Freed From Desire	dance
    584 	Mara, Sleazy Stereo - Foufoune	dance hiphop
    585 
    586 On peut ensuite faire un `grep` pour filtrer sur un tag
    587 
    588 	grep -i "	.*dance.*" playlist.m3u
    589 
    590 ce qui renvoie
    591 
    592 	Fred again... - Marea	dance electro
    593 	Brutalist - Movements	dance electro
    594 	Gala - Freed From Desire	dance
    595 	Mara, Sleazy Stereo - Foufoune	dance hiphop
    596 
    597 et pourra être lu dans mpv en pipant tout ça
    598 
    599 	grep -i "	.*dance.*" playlist.m3u | cut -f1 | shuf | xargs -d'\n' mpv
    600 
    601 Le petit `shuf` pour désordonner le résultat.\
    602 *Attention*, avec ce système faire `mpv playlist.m3u` ne fonctionnera plus pour
    603 les chansons sur lesquelles vous avez mis un tag puisqu'il n'existera pas de
    604 fichier avec un nom correspondant ("Fistaille - 13h12	acab" n'est pas le
    605 fichier que l'on souhaite lire). Il faut donc adapter vos alias et le script de
    606 synchro de façon à omettre les tags. Ça tombe bien, cela revient à piper le
    607 fichier dans `cut -f1`.
    608 
    609 L'ajout de ce système de tag et cette courte documentation m'a pris quelques
    610 dizaines de minutes et a résulté en la modification et l'écriture de quatre
    611 lignes de codes (ajout de trois `cut -f1` et écriture d'un nouvel alias pour
    612 filtrer sur les tags).
    613 
    614 * Si vous voulez télécharger ce que vous avez entendu sur fip avec l'outil fip
    615 
    616 Pour télécharger cet outil :
    617 
    618 	git clone git://katzele.netlib.re/fip
    619 
    620 Les instructions d'usage sont dans le README.\
    621 Si votre alias pour lancer la lecture est `fip` vous pouvez faire ceci
    622 
    623 	fip | tee session
    624 
    625 pour enregistrer les informations de toutes les chansons diffusées dans le
    626 fichier session. Vous pouvez ensuie télécharger les chansons comme nous l'avons
    627 vu précédemment. Si vous kiffez ce que vous êtes en train d'écouter à l'instant
    628 vous pouvez aussi ouvrir votre fichier de playlist dans vim, taper
    629 
    630 	tail -n1 chemin/vers/session
    631 
    632 et l'exécuter avec `:.!sh` pour directement récupérer les infos.
    633 Alternativement vous pouvez aliaser cette commande :
    634 
    635 	sed -i "1 s/^/$(tail -n1 /chemin/vers/session)\n/" /chemin/vers/playlist.m3u
    636 
    637 * Savoir si l'un ou l'une des artistes de votre playlist passe en concert à
    638   Strasbourg
    639 
    640 L'outil concerts est disponible avec la commande suivante :
    641 
    642 	git clone git://katzele.netlib.re/concerts-light
    643 
    644 Avec on peut faire le croisement des données et savoir quand et où passe un
    645 artiste de votre playlist :
    646 
    647 	cut -f1 playlist.m3u |
    648 		cut -f1 -d- |
    649 		sed 's/ *$//' |
    650 		sort -u |
    651 		sed 's/, /\n/g' |
    652 		xargs -n1 -d'\n' sh -c 'grep "$1" emplacement_des_données_des_concerts' --
    653 
    654 Ou un peu plus performant sur des gros fichiers
    655 
    656 	concerts=$(cut -f2 emplacement_données_concerts | sed 's/, /\n/g' | sort -u)
    657 	artists=$(cut -f1 emplacement_fichier_playlist | cut -f1 -d- | sed 's/ *$//' | sed 's/, /\n/g' | sort -u)
    658 	echo $concerts $artists |
    659 		sort |
    660 		uniq -d
    661 
    662 Côté performance quand il s'agit de croiser des données entre deux sources il
    663 est souvent préférable de jouer sur le tri et la détéction de doublons plutôt
    664 que de faire des recherches à répétition.
    665 
    666 ### Synchronisation
    667 
    668 Une fonctionnalité pratique de spotify est la synchronisation des playlists sur
    669 plusieurs terminaux. J'estime que cette fonctionnalité est suffisamment utile
    670 pour être répliquée. L'information de la playlist est entièrement détenue dans
    671 le fichier playlist.m3u. J'ai donc opté pour un dépôt git, hébergé sur un
    672 serveur distant, avec pour `.gitignore`
    673 
    674 	*
    675 	!.gitignore
    676 	!playlist.m3u
    677 
    678 de façon à ne tracker que la playlist et le .gitignore. Quand j'arrive sur un
    679 nouveau terminal je fais un `git pull` et je lance mon script de synchro. Pour
    680 économiser de la bande passante il reste préférable de transférer les fichiers
    681 audios par clef usb.
    682 
    683 ## Migration depuis spotify
    684 
    685 Si vous avez de très grandes playlists spotify j'ai écrit quelques scripts pour
    686 récupérer les infos des titres. Pour les télécharger :
    687 
    688 	git clone git://katzele.netlib.re/downloadmusic
    689 
    690 Les instructions d'usage sont dans le README. A noter, cela fait un moment
    691 que je n'ai pas testé les scripts de migration, ils peuvent ne plus
    692 fonctionner.
    693 
    694 ## L'existant
    695 
    696 Il existe déjà des outils permettant de télécharger des musiques depuis youtube
    697 en fonction d'une playlist spotify, notamment [spotdl]. J'ai tout de même voulu
    698 en faire ma propre version parce que spotdl
    699 
    700 * nécessite python or je veux vouloir gérer mes playlist sur des systèmes
    701   n'ayant pas ce langage
    702 * est relativement peu performant, à tester plus en détail
    703 * est un logiciel assez conséquent, je n'ai ni le temps ni l'envie de le
    704   comprendre pour pouvoir le modifier
    705 * contient bien plus de fonctionnalités que ce dont j'ai besoin or l'abus de
    706   fonctionnalités est l'un des facteurs qui participent à l'obsolescence
    707   logicielle
    708 
    709 Parmi les fonctionnalités supplémentaires qui pourraient vous intéresser, spotdl peut :
    710 
    711 * récupérer tout un tas de métadonnées (artiste, titre, date de parution, nom
    712   de l'album, n° de la chanson dans l'album, pochette)
    713 * sauter les pubs avec sponsorblock
    714 * télécharger un album depuis un lien spotify (devrait pas être très difficile)
    715 * afficher une interface web
    716 * télécharger les paroles
    717 * ...
    718 
    719 [electron]: https://github.com/electron/electron
    720 [spotify-tui]: https://github.com/Rigellute/spotify-tui
    721 [Psst]: https://github.com/jpochyla/psst
    722 [spotifyd]: https://github.com/Spotifyd/spotifyd
    723 [DRM ou Gestion des Droits Numériques]: https://fr.wikipedia.org/wiki/Gestion_des_droits_num%C3author:9riques
    724 [vous ne voleriez pas une voiture n'est-ce pas]: https://www.youtube.com/embed/HmZm8vNHBSU 
    725 [fip]: http://lien-a-venir.com
    726 [l'article sur ma façon de lire des vidéos youtube]: http://people.netlib.re/notes/221019/interfaces_alternatives_youtube/index.html
    727 [yt-dlp]: https://github.com/yt-dlp/yt-dlp
    728 [documentation de yt-dlp]: https://github.com/yt-dlp/yt-dlp#filtering-formats
    729 [frontends]: https://codemadness.org/git/frontends/files.html
    730 [spotdl]: https://github.com/spotDL/spotify-downloader
    731 [^1]: 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`.
    732 [ce fork]: https://github.com/leo-arch/fzy
    733 [^2]: non sans adaptation, certains chemins sont en dur