Wie verwandle ich einen Raspberry Pi, eine USB-WLAN-Karte und ein Paar USB-Lautsprecher in eine mobile Krachstation, welche die gleiche Musik wiedergeben kann, wie mein Hauptrechner? Nun, die Theorie wäre ja einfach: Auf dem Hauptrechner läuft
mpd und dieser kann in quasi jedem gewünschten Format und Protokoll ausgeben. Dieser wird nun zwecks Steigerung der Verfügbarkeit erstmal auf den Intranet-Server gezügelt.
Der erste Versuch war, einen normalen Stream zu verwenden. Dazu wird wahlweise mpds integrierter Web/Streaming-Server gestartet (Nachteil: sobald man die wiedergabe pausiert, wird das Socket geschlossen, ein allfälliger Client wird deshalb terminiert), oder noch ein Icecast zwischengeschaltet (Vorteil: ein permanenter Stream, sobald mpd pausiert wird, strahlt Icecast ein (lautloses) Fallback-File in Endlosschleife aus). Leider hat diese Lösung einen riesigen Nachteil: Der Client hängt 2-10 Sekunden hinterher. Startet man die Wiedergabe, drückt man auf Pause oder wechselt manuell zum nächsten Lied, dauert es eine mittlere Ewigkeit, bis die Änderung beim Client ankommt. Fazit: für meinen Zweck unbrauchbar.
Na gut, zweiter Versuch. mpd Pipe-Output. Damit gibt mpd einfach einen rohen Audiostream per Pipe an ein anderes Programm weiter. Diesen Stream kann man entweder direkt per netcat übers Netzwerk raushauen oder aber, um das Netz nicht übermässig zu belasten, erst zu ogg codieren. Hierzu trägt man in der /etc/mpd.conf folgendes ein:
audio_output {
type "pipe"
name "my pipe"
command "oggenc -r -Q -q4 - | nc 192.168.0.60 8765"
}
Auf der Empfängerseite wird mittels xinetd ein passender Empfänger bereitgestellt. Dazu benötigt man einerseits eine Konfiguration für xinetd unter /etc/xinetd.d/oggplay:
service oggplay
{
port = 8765
type = UNLISTED
socket_type = stream
wait = no
user = root
server = /usr/local/bin/oggplay.sh
log_on_failure += USERID
disable = no
}
Leider scheint diese nur mit root-Rechten zu funktionieren, von xinetd aus gestartet kann ein Prozess des eingeschränkten Benutzers aus irgend einem Grund nicht auf die Soundhardware zugreifen (von einer Login-Shell aus geht das jedoch). Genauer untersucht habe ich das nicht, da ich ja erst mal einen Proof-Of-Concept wollte. Ebenfalls wird noch das eigentliche Player-Skript unter /usr/local/bin/oggplay.sh benötigt:
#!/bin/bash
/usr/bin/ogg123 -v -d wav -f- - | /usr/bin/aplay -v -D sysdefault:CARD=USB
Das funktionert soweit... nicht wirklich. Der erste Song konnte in aller Regel noch wiedergegeben, spätestens nach dem ersten Songwechsel waren dann aber massive Aussetzer in der Wiedergabe. Kein Wunder, hier wird ja auch überhaupt nichts gepuffert. Sehr traurig allerdings, dass es auch über Ethernet mit geringer Latenz/Jitter kein Bisschen besser funktioniert als über WLAN. Fazit: unbrauchbar.
Als nächstes habe ich dann zu ganz radikalen, verzweifelten Massnahmen gegriffen und im dritten Versuch angefangen, meine Systeme mit Pulseaudio zu verschandeln (und natürlich erst noch ein Diskimage gezogen). Auf dem Server werden
folgende Pakete und Konfiguration benötigt:
aptitude install pulseaudio pulseaudio-utils mpd mpc
/etc/mpd.conf:
audio_output {
type "pulse"
name "Multicast RTP"
sink "rtp"
}
/etc/pulse/default.pa in Debian 6 / PA 0.9:
#! /usr/bin/pulseaudio -nF
load-module module-native-protocol-unix
load-module module-suspend-on-idle timeout=1
load-module module-null-sink sink_name=rtp description="Multicast RTP"
load-module module-rtp-send source=rtp.monitor
bzw unter Debian 7 / PA 2.0:
#! /usr/bin/pulseaudio -nF
load-module module-native-protocol-unix
load-module module-suspend-on-idle timeout=1
load-module module-null-sink sink_name=rtp sink_properties="device.description='RTP Multicast Sink'"
load-module module-rtp-send source=rtp.monitor
/etc/pulse/daemon.conf:
exit-idle-time = -1
default-sample-format = s16le
Das war's schon
Nehmen wir nun den Raspberry in Angriff. Zuerst werden ein paar PulseAudio-Konfigurationswerkzeuge installiert:
aptitude install paman paprefs pavucontrol
Des weiteren wird PulseAudio so konfiguriert, dass standardmässig die USB-Lautsprecher verwendet werden. Hierzu genügt die Zeile "default-sink = 1" in der Datei /etc/pulse/client.conf.
Startet man nun die grafische Oberfläche und aktiviert dort den RTP-Empfang per Klickibunti in paprefs, haut die Sache auch sofort hin. Das ist aber witzlos, wenn die Kiste ja nachher Headless und ohne angemeldeten Benutzer funktionieren soll. Folglich beendet man X11 wieder. In den Howtos zu diesem Thema (u.a. auch in den Raspberry-spezifischen Diskussionen wie
hier und
hier) wird gesagt, dass "einfach nur" in /etc/pulse/default.pa die Zeile "load-module module-rtp-recv" einfügt und PulseAudio durch Änderung in /etc/default/pulseaudio als Systemdienst eingerichtet werden soll. Eventuell muss man noch in der /etc/pulse/daemon.conf "resample-method = src-sinc-fastest" eintragen. Nach einem Neustart soll es auch schon laufen. Simpel, oder? Da muss ein Haken dran sein! Ist auch so. Davon zeigt sich das System nämlich überhaupt nicht beeindruckt und bleibt mucksmäuschenstill.
Was ist nun also der Unterschied zwischen der Kommandozielen- und der GUI-Konfiguration? Keine Ahnung. Auch "pacmd dump" hilft hier nicht weiter. Wie bekommt man den Dreck trotzdem zum laufen? Nun, wie so oft mit der beliebten Methode "von hinten durch die Brust ins Auge": Die Änderung in /etc/default/pulseaudio wird wieder rückgängig gemacht, so dass Pulseaudio nicht beim Systemstart gestartet wird. Danach trägt man in die /etc/rc.local einen fixen Aufruf des PulseAudio-Dienstes ein, und zwar mit folgender Zeile:
su pi -c 'pulseaudio -D --log-target=syslog --start --realtime --resample-method=src-sinc-fastest'
und Tadaaaa! Es lärmt, sobald der mpd anfängt zu spielen. Allerdings ist "Lärm" wirklich die passende Bezeichnung. Die Wiedergabe scheppert leicht, was wohl dem Resampling geschuldet ist.
Jetzt steht mir nur noch eines bevor: Auch meinen Desktop mit Pulseaudio zu ruinieren. Dies, nachdem das aktuelle Alsa-Setup doch prächtig funktioniert.