MPD : le stream était presque parfait
Par Jean-Seb le mercredi 28 avril 2010, 00:11 - Linuxeries - Lien permanent
Aujourd'hui, ce sont mes aventures pour streamer de la musique avec
mpd.
Car mpd est beau, mpd est grand, mpd streame!
Merci à Frédéric Jolliton pour le coup de main lors de la mise au point.
(et il a relu et clarifié, en plus)
MàJ 13 mai 2010 : gagner trois ko de bande passante
avec shh
MàJ 31 jan 2013 : faire un paquet Arch pour une
machine sans Xorg.
Résumé des épisodes précédents
- Ce n'était pas forcément le plus intéressant, mais le premier billet est ici:
- Le streaming n'était pas le sujet de ce billet. Dans ma grande bonté, j'en refais donc un complet.
Comprenons-nous bien
- Ce titre légèrement menaçant fait un peu vendeur de savonnettes dé-régulées cherchant à forcer l'entrée de votre habitation. Cette fois, il ne s'agit que d' une nécessaire introduction à ce qu'est réellement mpd.
De l'avantage du stream
- Pourquoi écouter un stream , et ne pas décoder en local ?
- Vous ne compilerez qu'une fois le player.
- Vous ne dupliquez pas vos fichiers, vous n'avez pas besoin de les promener sur une clé usb ou un disque externe.
- Vous allez faire l'envie de vos voisins (en général, cet argument suffit à emporter la décision).
mpd n'est pas forcément ce que l'on croit
- mpd est un player dont la sortie sonore se fait en local
par défaut (c'est à dire, sur la machine où mpd est lancé).
- Les clients de mpd, tels que ncmpc ou gmpc (client Gnome) ne sont rien d'autre que des télécommandes pour mpd.
- Aucun d'entre eux ne permet d'écouter un stream.
- Ils ne savent qu'envoyer des commandes au daemon mpd.
- Un client mpd est une télécommande ... donc cela signifie que seul
le PC faisant tourner le serveur est en mesure de sortir du son, et que tous
les clients associés à mpd ne servent qu'à contrôler celui-ci à distance ?
- Exactement ! Je n'aurais su mieux le dire !
mais mpd peut streamer
- Néanmoins, si les clients spécifiques à mpd ne peuvent que le contrôler,
mpd est capable de différents rendus.
- Les sorties locales, avec la configuration OSS , Alsa ou ...
null
(qui est bien un rendu local) - Des sorties streamées, avec entre autres un serveur shoutcast, ou son serveur interne httpd.
- Les sorties locales, avec la configuration OSS , Alsa ou ...
- Nous allons utiliser le serveur intégré à mpd, qui streame sans fioritures, tel une web-radio.
- Dès à présent, il est utile de préciser que nous allons utiliser deux
ports.
- Le port de commande de mpd, sur lequel nous pouvons connecter un client, ou
lancer un
telnet. - Le port utilisé par mpd pour servir le stream. Celui-ci n'est actif que quand de la musique est jouée. Il est fermé dès que la musique est stoppée.
- Le port de commande de mpd, sur lequel nous pouvons connecter un client, ou
lancer un
Préparation et configuration de mpd
Flags de compilation Gentoo
media-sound/mpd -alsa -ffmpeg mikmod musepack ogg vorbis lame
- Votre avis concernant ffmpeg pourra varier, mais j'ai préféré limiter les temps de compilation sur une machine un peu limitée.
- J'ai bien sûr retiré toute référence à Alsa (OSS étant inactif par défaut), vu que la machine hébergeant le serveur n'a même pas de carte son.
PKGBUILD pour Arch
Arch a déja son paquet, qui contient un tas de dépendances qui vont faire exploser votre serveur.
Le mieux est de reprendre le PKGBUILD de ABS, pour obtenir les flags de la distribution, et de l'adapter.
Penser ensuite à bloquer les mises à jour de MPD dans pacman.conf.
Voici les deux modifications que j'ai apporté au PKGBUILD :
- depends
J'ai viré tout un tas de trucs qu'il ne fallait surtout pas installer, car invasif (trop de dépendances), ou inutile (jack), ou les deux (pulse, ahaha!). J'ai enlevé libmodplug après quelques hésitations, et je l'ai remplacé par mikmod.
Je me suis également permis d'ajouter le support Ogg-Vorbis.
depends=('libmikmod' 'libmad' 'libid3tag' 'libogg' 'libvorbis')
Il ne reste vraiment pas grand monde, mais ça devrait suffire.
- options de
./configure
Le massacre continue avec les options de configure. Hâtons nous de virer cet horrible systemd, lastfm et autres soundcloud. Bon, ça ira plus vite si je vous donne le nouveau.
./configure \
--prefix=/usr \
--sysconfdir=/etc \
--enable-httpd-output \
--enable-id3 \
--enable-mikmod \
--disable-oss \
--enable-vorbis
La reconstitution du PKGBUILD est laissé à titre d'exercice au lecteur, je me suis contenté ici de donner ce qui changeait, plutôt que de vous noyer sous les inutiles détails de ce qui ne changeait pas.
Création des répertoires nécessaires
- mpd peut être lancé par un utilisateur lambda.
- Vous devriez mettre sa configuration dans le home de celui-ci, et ajuster le paramètre user dans le fichier de configuration.
Fichier de configuration
Voici mon fichier de configuration.
Je n'ai pas inclu tout ce qui ne sert pas, reportez vous au fichier
/etc/mpd.conf
pour plus de précisions.
Son nom et son emplacement dépend de l'utilisateur qui va lancer mpd.
- root :
/etc/mpd.conf
- un utilisateur :
/home/toto/.mpdconf
Pour vos essais, vous pouvez simplifier la situation en ne mettant pas de mot de passe, par exemple.
music_directory "/home/toto/music"
playlist_directory "/home/toto/mpd/playlists"
db_file "/home/toto/mpd/database"
log_file "/home/toto/mpd/mpd.log"
pid_file "/home/toto/mpd/mpd.pid"
state_file "/home/toto/mpd/state"
#ATTENTION : si vous ne lancez pas mpd en root, commentez «user»
#user "toto"
bind_to_address "0.0.0.0"
port "1234"
password "password@read,add,control,admin"
default_permissions "" #pas de bras, pas de chocolat.
input {
plugin "curl"
}
audio_output {
type "httpd"
name "My HTTP Stream"
encoder "lame" # optional, vorbis or lame
port "5678"
bitrate "128" # do not define if quality is defined
format "44100:16:1"
}
filesystem_charset "UTF-8"
- bind_to_address : ne mettez surtout
pas localhost ou 127.0.0.1 :
- Cela provoquerait un bind de mpd sur l'interface loopback. Toute connexion externe serait alors impossible.
- Cependant, vous pourrez toujours faire un tunnel ssh avec l'adresse "127.0.0.1"
- A la place de 0.0.0.0 on peut mettre l'IP d'une carte réseau. Par exemple pour une machine directement sur le net (avec une IP publique) on veut pas forcément rendre mpd accessible. Alors qu'en mettant l'IP de la machine sur le LAN (disons 192.168.1.1) ça ne sera accessible que sur le réseau local.
- default_permissions : pour vos essais en connexion
anonyme (sans mot de passe), vous pouvez mettre les permissions à fond avec
read,add,control,admin
.
- Pour pouvoir vous connecter si vous avez compilé mpd avec tcp_wrapper (libwrap) , vous devrez peut-être ajouter dans /etc/hosts.allow
mpd: ALL
Premier lancement
Placez quelques fichiers musicaux dans le répertoire définit comme music_directory dans le fichier de configuration.
Le premier lancement se fera en local, avec l'utilisateur configuré dans mpd.conf
Au passage, nous allons créer la base de données.
Par la suite, la commande update
sera envoyée par un client mpd.
Dans les anciennes versions, il suffisait de faire ceci:
toto@serveur ~$ mpd --create-db
Hélas, cette méthode ne fonctionne plus, que l'on soit simple utilisateur ou root. Ne croyez pas la FAQ qui prétend que l'on peut créer la base avec l'utilisateur root. Dans tous les cas, vous aurez cette erreur:
/tmp# mpd --create-db ** (mpd:32740): CRITICAL **: option parsing failed: Unknown option --create-db
Alors que faire ?
D'autres sources conseillent de faire un mpc update, mais
encore faudrait-il que mpd soit lancé. Or, mpd se plante au
démarrage puisque la base de données n'est pas là.
Résistez également à la tentation de faire un touch pour créer
la base à la main. Ça ne fonctionnera pas.
La seule chose que j'ai trouvé a été de créer une config minimale dans /etc/mpd.conf et de lancer mpd en tant que root. Ensuite, je l'ai tué et j'ai récupéré le fichier database.db à l'endroit où mpd l'avait créé (j'avais tout mis dans /tmp).
Alors pour info, il s'agit d'un stupide fichier texte. Le voici, si vous rencontrez les mêmes problèmes, un copier/coller pourrait vous faire gagner du temps.
Le dump après le cat vous donne le format binaire strict, au
cas où vous auriez des problèmes avec votre éditeur (rappel: sous Unix, une fin
de ligne est codée sur un seul octet: 0x0a).
/etc# cat /tmp/database.db info_begin format: 1 mpd_version: 0.17.3 fs_charset: UTF-8 tag: Artist tag: ArtistSort tag: Album tag: AlbumArtist tag: AlbumArtistSort tag: Title tag: Track tag: Name tag: Genre tag: Date tag: Composer tag: Performer tag: Disc tag: MUSICBRAINZ_ARTISTID tag: MUSICBRAINZ_ALBUMID tag: MUSICBRAINZ_ALBUMARTISTID tag: MUSICBRAINZ_TRACKID info_end /etc# hexdump /tmp/database.db -C 00000000 69 6e 66 6f 5f 62 65 67 69 6e 0a 66 6f 72 6d 61 |info_begin.forma| 00000010 74 3a 20 31 0a 6d 70 64 5f 76 65 72 73 69 6f 6e |t: 1.mpd_version| 00000020 3a 20 30 2e 31 37 2e 33 0a 66 73 5f 63 68 61 72 |: 0.17.3.fs_char| 00000030 73 65 74 3a 20 55 54 46 2d 38 0a 74 61 67 3a 20 |set: UTF-8.tag: | 00000040 41 72 74 69 73 74 0a 74 61 67 3a 20 41 72 74 69 |Artist.tag: Arti| 00000050 73 74 53 6f 72 74 0a 74 61 67 3a 20 41 6c 62 75 |stSort.tag: Albu| 00000060 6d 0a 74 61 67 3a 20 41 6c 62 75 6d 41 72 74 69 |m.tag: AlbumArti| 00000070 73 74 0a 74 61 67 3a 20 41 6c 62 75 6d 41 72 74 |st.tag: AlbumArt| 00000080 69 73 74 53 6f 72 74 0a 74 61 67 3a 20 54 69 74 |istSort.tag: Tit| 00000090 6c 65 0a 74 61 67 3a 20 54 72 61 63 6b 0a 74 61 |le.tag: Track.ta| 000000a0 67 3a 20 4e 61 6d 65 0a 74 61 67 3a 20 47 65 6e |g: Name.tag: Gen| 000000b0 72 65 0a 74 61 67 3a 20 44 61 74 65 0a 74 61 67 |re.tag: Date.tag| 000000c0 3a 20 43 6f 6d 70 6f 73 65 72 0a 74 61 67 3a 20 |: Composer.tag: | 000000d0 50 65 72 66 6f 72 6d 65 72 0a 74 61 67 3a 20 44 |Performer.tag: D| 000000e0 69 73 63 0a 74 61 67 3a 20 4d 55 53 49 43 42 52 |isc.tag: MUSICBR| 000000f0 41 49 4e 5a 5f 41 52 54 49 53 54 49 44 0a 74 61 |AINZ_ARTISTID.ta| 00000100 67 3a 20 4d 55 53 49 43 42 52 41 49 4e 5a 5f 41 |g: MUSICBRAINZ_A| 00000110 4c 42 55 4d 49 44 0a 74 61 67 3a 20 4d 55 53 49 |LBUMID.tag: MUSI| 00000120 43 42 52 41 49 4e 5a 5f 41 4c 42 55 4d 41 52 54 |CBRAINZ_ALBUMART| 00000130 49 53 54 49 44 0a 74 61 67 3a 20 4d 55 53 49 43 |ISTID.tag: MUSIC| 00000140 42 52 41 49 4e 5a 5f 54 52 41 43 4b 49 44 0a 69 |BRAINZ_TRACKID.i| 00000150 6e 66 6f 5f 65 6e 64 0a |nfo_end.| 00000158
- En cas d'erreur, ou de modification de la base, vous pouvez tuer le serveur
avec :
kill $(pidof mpd)
- Par la suite, vous pourrez utiliser les scripts Gentoo (ou de votre distrib) pour demander le démarrage de mpd au boot.
Test rapide avec telnet
- Plus qu'à tenter un telnet sur le port de votre serveur
- Vous pouvez trouver toutes les commandes comprises par mpd ici:
toto@serveur ~/.ncmpc $ telnet localhost 1234 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. OK MPD 0.15.0 status volume: -1 repeat: 0 random: 0 single: 0 consume: 0 playlist: 3 playlistlength: 0 xfade: 0 state: stop OK close Connection closed by foreign host.
- status vous permettra d'obtenir rapidement confirmation du
fonctionnement de mpd.
- Même si la simple réussite de la connexion telnet devrait suffire.
- Pour fermer proprement la session, utilisez close.
mpc dépanne certes bien...
- Maintenant que le daemon mpd fonctionne, il est temps de tester avec un
logiciel un peu plus évolué, et à distance.
- Je vous conseille de rester sur le réseau local de mpd, ceci limitera les ports à ouvrir dans le firewall, et vous pourrez toujours vous passer d'authentification.
- L'informatique aime les acronymes, et les doublons aussi.
- mpc = music player client
- ne confondez pas avec les vieux fichiers musepack (extension mpc) que l'on peut jouer avec mpd.
- mpc est un utilitaire indispensable pour vous éviter des
telnetrapidement saoulants sur le port du daemon mpd.
- Je vous laisse faire
man mpc, le fonctionnement est trivial.
...mais ncmpc est toujours le plus beau
- Maintenant que tout semble bien tourner, il est temps de passer au client qui ne nous quittera plus.
- Avec un nom à coucher dehors, ncmpc est néanmoins le plus agréable des clients mpd.
- Interprétation personnelle du nom:
- nc = ncurses
- mpc = music player client
Version dans Portage (avril 2010)
- 0.14
- un peu vieille, mais que voulez-vous ...
Flags Gentoo
media-sound/ncmpc artist-screen colors help-screen key-screen lyrics-screen search-screen song-screen
- Beaucoup de possibilités dans les versions récentes de ncmpc , y
compris la possibilité d'afficher les paroles des chansons.
- J'ai activé toutes les options, ça ne mange pas de pain (ni de ressources).
Erreur possible à la compilation de ncmpc
match.c:43: attention : implicit declaration of function ‘g_regex_match_simple’ match.c:45: erreur: ‘G_REGEX_CASELESS’ undeclared (first use in this function)
- Dans ce cas, il faut mettre à jour votre glib (pas la glibc , je parle bien de la glib tout court) et recommencer l'emerge de ncmpc.
Fichier de configuration de ncmpc
- Il se trouve dans ~/ncmpc/config
- Celui-ci est donné juste pour information. Je n'ai pas encore pris le temps de fignoler.
port = 1234 password = "password" scroll = yes scroll-sep = " ***** " enable-colors = yes color background = black color list = brightwhite
Diagnostics
- Lancez la lecture d'un fichier avec mpc, ncmpc, telnet, ou ce que vous
voudrez.
- Ceci doit produire l'envoi du stream sur le port défini pour httpd dans la configuration de mpd.
- Le port stream ne sera ouvert que pendant la génération d'un stream.
toto@serveur ~$ netstat -pln | grep mpd tcp 0 0 0.0.0.0:1234 0.0.0.0:* LISTEN 3694/mpd tcp 0 0 0.0.0.0:5678 0.0.0.0:* LISTEN 3694/mpd
- Les ports utilisés sont ceux définis dans mpd.conf
- Le port de commande de mpd est 1234.
- Le stream est joué sur 5678.
La config du pauvre, mais qui marche tellement bien
- Et encore j'avais un titre plus long pour cette partie, mais il faut savoir rester raisonnable.
- Nous allons utiliser un tunnel ssh dans lequel nous ferons passer le flux.
- Ceci nous évitera de partager nos disques avec la terre entière, ce qui serait non seulement illégal, mais très consommateur en bande passante.
Tunnel ssh
- Ce n'est pas le sujet de ce billet, je vous donne donc la commande pour
créer un tunnel ssh.
- Il y a pas mal d'explications à ce sujet un peu partout, les curieux devraient trouver leur compte facilement.
- Sous MS-Windows, vous pouvez créer facilement des tunnels avec Putty.
- pour créer un tunnel ssh entre votre machine et le serveur mpd
ssh -C -L 5678:localhost:5678 a.b.c.d
- 5678 : port configuré sur mpd pour exporter le stream httpd (ce n'est pas le port de commande de mpd)
- localhost : car vous allez vous connecter sur votre machine pour la redirection de port.
- a.b.c.d : ip de la machine distante faisant tourner mpd.
- En prime, vous récupérez un shell où vous pourrez lancer ncmpc pour controler mpd.
mpd
- Exporte le flux httpd.
- Les façons de le lancer ont été vues plus haut:
- en user :
mpd - au démarrage : voir la doc de votre distrib. Avec Gentoo, vous pourrez
utiliser
/etc/init.d/mpd start
- en user :
ncmpc
- à installer sur le serveur pour controler mpd
- on peut également l'installer sur le client (dans ce cas, pensez à définir un login/password et à ouvrir le port de commande mpd dans le firewall).
mplayer
- Reçoit le stream et assure son rendu.
mplayer http://192.168.1.1:5678- 192.168.1.1 est l'ip de la machine faisant tourner mpd.
- 5678 est le numéro de port utilisé pour envoyer le stream.
Inconvénients de la config du pauvre (mais qui marche tellement bien)
- Je ne vous le cache pas, il y a quelques inconvénients.
Overhead du tunnel
- Si vous êtes vraiment court côté débit, sachez qu'un flux à 128kbs (minimum
pour une qualité acceptable) vous pompe 16ko/s de bande passante.
- Avec le tunneling, vous allez passer à environ 22ko/s de moyenne.
- Je n'ai pas testé avec quelque chose de plus compliqué, à base de OpenVPN
par exemple.
- Si quelqu'un l'a fait, qu'il n'hésite pas à partager son expérience.
- Pour gagner un peu de bande passante sur la session SSH, vous pouvez passer
l'option -N à la connexion.
- Cette option désactive le shell interactif et ne fait qu'établir le tunnel.
- Vous ne pourrez donc plus controler la playlist directement, mais pour un streaming tout simple, cela suffit. Vous gagnez environ trois Ko/s.
Latence
- C'est inhérent au streaming. Pour assurer une liaison sans saccades, tout
est bufferisé.
- Les modifications côté serveurs (changement de chanson, ou arrêt pur et simple) mettront quelques secondes avant d'être répercutées à votre client.
- Quand à l'avance/retour rapide dans un morceau, mieux vaut oublier tout de suite.
- Une idée pourrait être de réduire la taille du buffer , sur une liaison de bonne qualité bien entendu.
Allez, c'est pas si mal finalement
- De toutes façons, vous n'auriez guère mieux avec un serveur shoutcast, alors pourquoi se compliquer la vie ?
- Allez hop. Et profitez-en pour mettre Audacious à la poubelle avant de sortir.
Commentaires
Nice title !