Multimedia: musique locale et streaming

Rappel: du multi-média simple

Je veux qu’on puisse simplement:

  • écouter de la musique (vers la chaine hifi) à partir d’un répertoire;
  • écouter de la musique à partir d’un stream (Deezer, Qobuz …)
  • envoyer des films vers chaine hifi (son) et écran (?) à partir de fichiers
  • stream de radio internet (au moins: France Culture et KUT)

Denis propose BubbleUPnp et MinimServer. C’est parti.

L’architecture

Ce doit être simple du côté utilisateur, mais côté serveur, j’ai eu un peu de mal à comprendre la stack de logiciels.

Il y a trois types de logiciels:

  • le serveur UpNP: ce logiciel prend une source (fichier audio, source radio internet) et l’expose au réseau
  • le renderer UpNP: quand on lui présente un flux (numérique), ce logiciel transforme ce flux en son (en signal analogique sur un cable audio)
  • la télécommande ou control point UpNP: un application qui permet de faire le plombier entre les serveurs et les renderer, c’est à dire de choisir la source (fichiers sur un NAS, flux internet) et de brancher cette source à une destination (la radio de la cuisine, la chaîne HiFi du salon, …)

C’est cet article de HIFIZINE qui m’a le plus aidé à comprendre les interactions des différentes parties.

Choix des logiciels

Serveurs:

Renderer:

  • la radio de la cuisine (Libratone ZipMini) est compatible UpNP, rien à faire c’est automatique;
  • le logiciel upmpdcli qui est un renderer pour MPD, lequel MPD va diriger la musique sur la carte audio (branchée sur l’ampli de la chaîne).

Contrôles:

TODO: insérer un schéma

Musique locale : MinimServer

MinimServer et BubbleUpNP vont avoir besoin de Java pour s’exécuter, donc on installe.

> sudo yum install java-11-openjdk-headless.x86_64

Création d’un groupe media, ajout de l’utilisateur à ce groupe, et tous les fichiers de ce groupe seront accessibles via ce groupe.

> sudo groupadd media
> sudo usermod -a -G media fabien

Installation du software dans /home/minimserver (groupe media):

> cd /home/minimserver
> tar xzpf MinimServer-2.0.16-linux-intel.tar.gz
# configuration minimale
> minimserver/bin/setup
# démarrage au boot
> minimserver/bin/startd
# pour configurer le chemin des donnees
> minimserver/bin/startc

Bon, en fait ça ne fonctionne pas. Après quelques reboot et quelques tests, il semblerait que ça ne fonctionne pas à cause de SELinux. Pro-tip: il faut vérifier le audit.log pour commencer à comprendre le problème.

Donc on passe SELinux en permissif dans /etc/selinux/config. Et ça marche.

On crée un service systemd dans /etc/systemd/system/multi-user.target.wants/minimserver.service:

[Unit]
Description=MinimServer
After=multi-user.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/su "fabien" -c "/home/minimserver/minimserver/bin/startd init"
ExecStop=/home/minimserver/minimserver/bin/stopall

[Install]
WantedBy=multi-user.target

Une interface web de configuration est disponible sur le port 9790, pratique pour lancer un “rescan” quand on a ajouté des fichiers audio dans la base.

BubbleUPnP server

En pré-requis il y a la bibliothèque ffmpeg, non disponible par défaut dasn CentOS/RHEL. Donc on l’ajoute.

> sudo yum-config-manager --set-enabled PowerTools
> sudo yum-config-manager --add-repo=https://negativo17.org/repos/epel-multimedia.repo
> sudo yum install ffmpeg

Ensuite on télécharge BubbleUPnP server, on décompacte, pas d’installation il suffit de lancer le wrapper launch.csh pour exécuter le Java:

> wget https://bubblesoftapps.com/bubbleupnpserver/BubbleUPnPServer-distrib.zip
> unzip BubbleUPnPServer-distrib.zip
> chmod +x launch.sh
> ./launch.sh

(oui, c’est pas très unix ….)

On va faire un service systemd, mais pas question de laisser ça tourner en root. Donc on crée un user “bubbleupnp”, qui ne peut pas se connecter, et qui fait partie du groupe “media”:

> sudo useradd -s /usr/sbin/nologin -d /multimedia/bubbleupnp/ -r -M  bubbleupnp
usermod -a -G media bubbleupnp
sudo chown -R bubbleupnp:media /multimedia/bubbleupnp/

Le fichier service:

> cat /usr/local/lib/systemd/system/bubbleupnpserver.service
[Unit]
Description=BubbleUPnP Server
Requires=network-online.target
After=network-online.target

[Service]
User=bubbleupnp
Group=media
Type=simple
Restart=on-failure
ExecStart=/multimedia/bubbleupnp/launch.sh -dataDir /multimedia/bubbleupnp/bubbldata -httpPort 58050 -httpsPort 58051 -nologstdout

[Install]
WantedBy=multi-user.target

Activation du service au démarrage (en root):

cd /etc/systemd/system/multi-user.target.wants/
ln -s /usr/local/lib/systemd/system/bubbleupnpserver.service 
systemctl daemon-reload
systemctl start bubbleupnpserver.service
systemctl enable bubbleupnpserver.service

Un reboot pour vérifier que ca charge bien au démarrage (avec MinimServer aussi), et c’est bon.

Renderer local: upmpdcli

Là c’est un tout petit peu plus compliqué, pas de rpm ou de package tout fait. Donc on va commencer par installer tous les packages de base pour pouvoir compiler. Note: le package llvm-toolset embarque gcc et tout un tas d’outils, donc plutôt que de les faire un à un, j’ai pris ce package. Il n’empêche qu’il y avait d’autres outils à installer. A commencer par le vénérable make, qui n’est pas dans l’installation minimale de CentOS.

Cette liste a peut-être des éléments inutiles. Et je l’ai construite au fur et à mesure de la compilation - en fonction des besoins.

sudo yum install libupnp libmpdclient expat jsoncpp libmicrohttpd
sudo yum install libcurl python-requests-futures
yum install llvm-toolset
sudo yum install libmicrohttpd-devel expat-devel make autoconf automake libtool libmpdclient-devel jsoncpp-devel

Ensuite on peut passer à la compilation:

tar xzpf libnpupnp-4.0.13.tar.gz
cd libnpupnp-4.0.13
./configure --prefix=/usr --sysconfdir=/etc
make
sudo make install
cd ..
tar xzpf libupnpp-0.19.4.tar.gz
./configure --prefix=/usr --sysconfdir=/etc
make
sudo make install
cd ..
tar xzpf upmpdcli-1.4.14.tar.gz
./configure --prefix=/usr --sysconfdir=/etc --disable-spotify
make
sudo make install

Et là si tout se passe bien on a un executable upmpdcli. Mais pas de son…

Le fichier de service est dans les sources, on le déplace dans la configuration de systemd.

[Unit]
Description=UPnP Renderer front-end to MPD
After=network-online.target mpd.service
Wants=network-online.target

[Service]
User=bubbleupnp
Group=media
Type=simple
Restart=on-failure
#Type=simple
## ExecStartPre=/bin/sleep 30
## Note: if start fails check with "systemctl status upmpdcli"
ExecStart=/usr/bin/upmpdcli -c /etc/upmpdcli.conf
## For some reason, it happens the first start of libupnp fails. Probably
## this should be started later in the start sequence, but I don't know
## how. Retry a bit later.
#Restart=always
#RestartSec=1min

[Install]
WantedBy=multi-user.target

Et on autorise le chargement au boot:

systemctl enable upmpdcli.service
systemctl start upmpdcli.service 

Music Player Daemon

Pour MPD il faut ajouter des dépôts complémentaires:

yum install https://mirrors.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm 
yum install https://mirrors.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-8.noarch.rpm
yum install mpd

Ensuite ça a été la galère. J’ai voulu tenter de passer par PulseAudio, parce que c’est une solution moderne, et je n’ai rien compris. Infoutu d’avoir du son. Donc je suis retourné sur l’ancêtre ALSA et son design vintage.

yum install alsa-utils

Sélection de la bonne carte son:

aplay -L
...
surround21:CARD=Generic_1,DEV=0
    HD-Audio Generic, ALC1220 Analog
    2.1 Surround output to Front and Subwoofer speakers
...

Il y a plein de cartes listées, parce que a priori ma carte gère du mono au 7.1 en passant par le stéréo. Je n’ai qu’un ampli avec deux enceintes, donc après consultation de la documentation de ma carte, il y a une sortie à choisir qui correspond à la configuration “surround21”.

Donc on ajoute dans /etc/asound.conf:

pcm.!default {
    type hw
    card Generic_1
}

ctl.!default {
    type hw
    card Generic_1
}

Et dans /etc/mpd.conf:

audio_output {
        type            "alsa"
        name            "My ALSA Device"
        device          "surround21:CARD=Generic_1,DEV=0"       # optional
##      mixer_type      "hardware"      # optional
##      mixer_device    "default"       # optional
##      mixer_control   "PCM"           # optional
##      mixer_index     "0"             # optional
}

Un coup de alsamixer pour vérifier que les niveaux ne sont pas à 0 (touch “M” pour unmute).

On démarre le MPD et on teste (avec le player en ligne de commande mpc):

mpc add /
mpc play

Miracle, du son :)

Notes: pour le upmpdcli, il faut ouvrir un port dans nftables:

# add upmpdcli interface port
tcp dport 49152 ip saddr $SAFE_TRAFFIC_IPS accept comment "upmpdcli connection"

Bonus: une interface web pour alsamixer

Si jamais lors d’un reboot les paramètres de ALSA sont perdus, et que la carte son se retourve en mute, il faudrait pouvoir accéder à l’équivalent de alsamixer via une interface web. Cela évitera de démarrer un ordinateur, un terminal, ouvrir une session SSH sur le serveur et remettre en place les réglages ALSA.

Pour ça Alsamixer Web UI va faire l’affaire.

git clone https://github.com/JiriSko/amixer-webui.git
pip3 install --user flask
pip3 install --user argparse
# test (attention aux ports ouvert avec nftable, par défaut ici c'est 8080)
python3 alsamixer_webui.py 

La seule commande disponible pour l’installation c’est le make install. Pas de compilation (c’est un script Python). Après inspection du Makefile, il n’y a rien de bien dangereux, juste une copie dans /usr/share/amixer-webui.

sudo make install

Et on fait un service systemd pour le démarrage automatique.

[Unit]
Description=Alsamixer Web UI front end
After=network-online.target mpd.service
Wants=network-online.target

[Service]
User=fabien
Group=media
Type=simple
Restart=on-failure
ExecStart=/usr/bin/python3 /usr/share/amixer-webui/alsamixer_webui.py 

[Install]
WantedBy=multi-user.target

L’utilisateur est fabien parce que on ne veut pas tourner ça en root, et les packages flask et argparse ont été installés pour cet utilisateur.

Un petit tour sur l’adresse http:serveur:8080 et on voit une interface qui permet de régler ALSA.

Il y a même une app sur f-droid !

Done !

Précédent
Suivant