Bluehemian Raspberry
Raspberry Pi als Bluetooth-Audio-Empfänger mit Internet-Radio und MP3-Player
Wer sich partout nicht von alten HiFi-Geräten trennen kann und diesen lieber zu einem würdigen Weiterleben verhilft, der kann gleich zwei Fliegen mit einer Klappe schlagen. Wir haben aus einem ausgedienten Raspberry Pi einen Bluetooth-Empfänger mit Internetradio und MP3-Player gebaut.
Es muss kein neuer Verstärker sein, denn ein Raspberry Pi bringt auch dem HiFi-Klassiker noch modernes Bluetooth bei. Kombiniert mit einem Bluetooth-USB-Adapter und einer Aufsteck- oder USB-Soundkarte entsteht daraus ein Bluetooth-Audio-Empfänger mit MP3-Spieler und integriertem Internetradio. Natürlich funktioniert das Konzept genauso mit einem aktuellen Raspi 3 oder Raspi Zero W mit integriertem Funkmodul.
Die Idee zu einer solchen Konstruktion haben bereits mehrere c’t-Artikel angerissen: Ein Konzept für einen Bluetooth-Audio-Empfänger für den Raspi erläuterte bereits der Artikel „Raspberry in Blue“ in c’t 21/2016. Diese überarbeitete Version wird durch den vielseitigen Audio-Player Mopidy [2] aufgewertet. Zudem haben leider einige Veränderungen bei der Raspi-Distribution Raspbian Stretch dazu geführt, dass der im alten Artikel beschriebene Weg nicht mehr ohne Weiteres funktioniert. Die hier beschriebene Methode ohne PulseAudio ist darüber hinaus erheblich einfacher.
Neben einem Raspi mit Bluetooth benötigen Sie nur einen externen D/A-Wandler (siehe Kasten „Hochwertige D/A-Wandler“ auf S. 134). Der ist in jedem Fall besser als der Audioausgang des Raspi. Will man auf dem Raspi selbst keine umfangreiche MP3-Sammlung speichern, so ist eine 4-GByte-Speicherkarte völlig ausreichend.
Als Betriebssystem kommt das aktuelle Raspbian Stretch Lite zum Einsatz. Konfigurieren Sie dieses je nach Vorliebe über Tastatur und Monitor oder per SSH [3]. Zudem muss man gegebenenfalls den D/A-Wandler nach Herstellerangaben einrichten. USB-Soundkarten funktionieren meist sofort.
Gimme the BlueZ
Bringen Sie zunächst Raspbian mit sudo apt update und sudo apt dist-upgrade auf den aktuellen Stand.
Um zu Anfang für etwas „Ordnung“ zu sorgen, sollten Sie den Onboard-Sound des Raspi deaktivieren. Suchen Sie dafür die Zeile
dtparam=audio=on
in der Datei /boot/config.txt und machen Sie aus dem on ein off.
Anschließend installieren Sie die für das Projekt notwendigen Softwarepakete mit
sudo apt install :
.--no-install-recommends :
.python-dbus python-gobject bluealsa
Der Parameter --no-install-recommends sorgt dafür, dass Apt keine überflüssigen Pakete wie zum Beispiel grafische Werkzeuge installiert.
Während die Python-Pakete die Skript-Unterstützung für die Bluetooth-Verbindung bereitstellen, schafft Bluealsa die Verbindung zum Soundsystem ALSA. Den Bluetooth-Adapter verwaltet der Bluetooth-Stack BlueZ, welcher in Stretch, ebenso wie ALSA, standardmäßig installiert ist.
Damit andere Geräte den Raspi als Bluetooth-Audio-Ziel verwenden, muss er sich als Audiogerät ausgeben und das A2DP-Profil (Advanced Audio Distribution Profile) unterstützen. Um dem Raspi mitzuteilen, dass er als für alle Geräte sichtbares Audio-Gerät auftreten soll, tragen Sie in der Datei /etc/bluetooth/main.conf unterhalb des Schlüssels [General] die folgenden Zeilen ein:
Class = 0x240428
DiscoverableTimeout = 0
PairableTimeout = 0
Die Option Class legt die Geräteklasse fest. 0x240428 steht für Bluetooth-Audio-Empfänger. Will man die Zeit, in der das Gerät sichtbar ist und für die Kopplung bereit steht, auf einen bestimmten Zeitraum nach dem Einschalten begrenzen, so sind DiscoverableTimeout und PairableTimeout die richtigen Stellschrauben. Tragen Sie den gewünschten Zeitraum dort in Sekunden ein. Bei 0 bleibt es immer sichtbar.
Um den Bluetooth-Gerätenamen des Raspis zu ändern, müssen Sie in das Verzeichnis /var/lib/bluetooth/ wechseln. Darin finden Sie einen Unterordner, der wie die Geräteadresse Ihres Bluetooth-Adapters heißt und eine Datei namens config enthält. Tragen Sie dort unter [General] die Zeile
Name = RaspiMusicbox
ein. Dann können Sie Ihren Raspi leichter identifizieren.
The Sound of Software
Nun gilt es, das Bluetooth-Gerät während des Systemstarts zu initialisieren und in die Kopplungs-/Verbindungsschleife zu versetzen. Dafür kommt das Skript Simple-agent zum Einsatz. Es stammt aus einer früheren BlueZ-Version und wurde von uns für die Kopplung ohne PIN-Eingabe modifiziert.
Für Raspbian Stretch mussten wir sowohl die Geräteinitialisierung („Discoverable Mode“, „Secure Simple Pairing Mode“) als auch die Synchronisierung mit dem Bluetooth Stack modifizieren. Aufgrund eines veränderten Timings beim Booten stürzt das alte Skript öfter ab. Das Simple-Agent-Skript und alle weiteren Dateien zum Artikel finden Sie als Paket unter ct.de/yhw9.
Kopieren Sie es mit Root-Rechten nach /usr/local/bin und machen Sie es mit sudo chmod 755 /usr/local/bin/simple-agent ausführbar.
Ein Systemd-Service startet das Skript. Der Umweg über den automatischen Login des Benutzers Pi ist ohne PulseAudio nicht mehr notwendig. Kopieren Sie dazu die Datei simple-agent.service nach /etc/systemd/system/. Anschließend aktivieren Sie den Service mit dem Befehl
sudo systemctl enable simple-agent
Haben Sie mehrere Bluetooth-Adapter angeschlossen, können Sie auch festlegen, welchen davon Simple-agent verwalten soll. Verändern Sie dafür in simple-agent.service die Zeile, die mit „ExecStart“ beginnt. Für den zweiten Adapter sieht die Zeile so aus:
/usr/local/bin/simple-agent hci1 &
Starten Sie den Raspi anschließend neu. Dann können Sie testen, ob das Skript korrekt arbeitet. Am einfachsten geht das mit dem Smartphone. In der Geräteliste sollte der Raspi als Audio-Zielgerät (meist mit Kopfhörersymbol) auftauchen.
Das Kommandozeilen-Tool Bluetoothctl hilft bei Problemen und dient dazu, eine vorhandene Gerätekopplung wieder zu löschen. Es ist das Schweizer Taschenmesser der BlueZ-Konfiguration und ersetzt somit auch die aus Gründen der Abwärtskompatibilität noch mitgelieferten Programme Hciconfig und Hcitool.
Song Song Blue
Noch gibt die Musicbox keinen Piep von sich. Hier kommt das Paket bluealsa ins Spiel. Es enthält das Programm Bluealsa-aplay, welches ein virtuelles Audiogerät einrichtet und als Player fungiert (siehe Kasten auf S. 136). Den Aufruf von Bluealsa-aplay löst eine Udev-Regel aus. Erzeugen Sie dazu die Datei /etc/udev/rules.d/99-bluetooth-input.rules mit dem Inhalt
.RUN+="/usr/local/bin/:
.a2dp-autoconnect"
Dass die Udev-Regel auf Eingabegeräte (input) reagiert, ist Absicht, da BlueZ für jedes A2DP-Gerät auch ein Eingabegerät für Fernbedienungskommandos (A2RCP) erzeugt. Das ist der aktuell zuverlässigste Weg, um alle Bluetooth-Geräte zu erwischen.
Weiter gehts mit dem Einrichten einer Systemd-Unit für Bluealsa-aplay. Dazu muss man die Konfigurationsdatei bluealsa-aplay@.service nach /etc/systemd/system kopieren. Das @-Symbol im Namen ist kein Tippfehler.
Kopieren Sie das Skript a2dp-autoconnect anschließend mit Root-Rechten nach /usr/local/bin. Schließlich machen Sie das Skript mit chmod 755 /usr/local/bin/a2dp-autoconnect ausführbar.
Jetzt ist eine gute Gelegenheit, um den D/A-Wandler nach Herstelleranweisung einzurichten.
Nach einem Neustart funktioniert der Bluetooth-Empfänger schon. Wenn es Probleme gibt, sollten Sie zuerst mit Bluetoothctl überprüfen, ob die Kopplung überhaupt geklappt hat: Nach Aufruf des Programms erhalten Sie sofort die Liste der gekoppelten Geräte. Solange Bluetoothctl aktiv ist, quittiert es jede erfolgreiche Aktion (Kopplung, Verbindung etc.) mit einer entsprechenden Ausgabe. Sollte Sie Ihr Raspi nach einer PIN fragen, ist der Bluetooth-Adapter möglicherweise zu alt für den PIN-losen Kopplungsmodus. Geben Sie dann einfach 1234 ein.
Wenn auf der Bluetooth-Seite alles in Ordnung ist, aber die Musicbox trotzdem stumm bleibt, so spricht Bluealsa-aplay möglicherweise nicht das korrekte Audio-PCM-Gerät an:
Eine Liste der auf dem Raspi verfügbaren Audio-PCM-Geräte erhält man mit aplay -l.
Hat man das gewünschte Audio-PCM-Gerät identifiziert, so bildet man aus den Indices für Karte und Gerät einen Konfigurationsstring -dhw:<Karte>,<Gerät>, also zum Beispiel -dhw:1,0. Diesen muss man nun in bluealsa-aplay@.service an die Zeile
ExecStart=/usr/bin/bluealsa-aplay %I
anfügen, zum Beispiel so:
ExecStart=/usr/bin/bluealsa-aplay %I :
.-dhw:1,0
Nun sollte die Bluetooth-Verbindung auch mit dem richtigen Audiogerät funktionieren.
Zum Kasten: Hochwertige D/A-Wandler
Wichtig ist, dass immer nur ein Bluetooth-A2DP-Sender gleichzeitig mit dem Raspi verbunden ist, da nur dann klar ist, welcher Sender aktuell gerade durchgeschaltet ist. Mehrere gleichzeitige A2DP-Quellen werden nicht gemischt.
Work Hard, Play Harder
Als Bluetooth-Audio-Empfänger ist der Raspi jedoch nicht ausgelastet. Er kann auch die eigene MP3-Sammlung oder Internetradio-Streams wiedergeben. Als Basis dafür dient Mopidy – ein zu MPD kompatibler Streaming-Server.
Mopidy ist in Python programmiert und relativ einfach zu installieren, doch ohne ein paar Erweiterungen ist es nur wenig nützlich. Installieren Sie auch gleich den Mopidy-Musicbox-Webclient, mit dem man das Programm per Browser administrieren kann, sowie TuneIn als Verzeichnisdienst für Internet-Radiostationen. Das Basisprogramm von Mopidy installieren Sie mit:
sudo apt install :
.--no-install-recommends mopidy :
.gstreamer1.0-alsa
Bei den Erweiterungen hängt es allerdings davon ab, ob diese als Raspbian-Pakete verfügbar sind. Im ersten Fall installiert man diese einfach mit Apt, im zweiten Fall benötigt man den Python-Paketmanager Pip.
Die TuneIn-Erweiterung lässt sich als Raspbian-Paket installieren:
sudo apt install :
.--no-install-recommends :
.mopidy-tunein
Für den Mopidy-Musicbox-Webclient muss man den Weg über Pip gehen.
Installieren Sie dafür zunächst das Paket python-pip mit Hilfe von Apt:
sudo apt install :
.--no-install-recommends :
python-pip
Anschließend installiert pip den Webclient:
sudo pip install :
.Mopidy-MusicBox-Webclient
Vermissen Sie noch eine Mopidy-Erweiterung, können Sie diese mit Hilfe von
apt search mopidy
oder
pip search mopidy
suchen und installieren.
Nehmen Sie in der Mopidy-Konfigurationsdatei /etc/mopidy/mopidy.conf die folgenden Anpassungen vor, um Stolperfallen zu vermeiden.
Fügen Sie am Ende der Datei den Schlüssel [http] mit folgenden Einstellungen ein:
[http]
hostname = ::
port = 6680
zeroconf = Meine Musicbox
Die erste Einstellung macht den Server im Heimnetz sowohl über IPv4 als auch IPv6 verfügbar. Die nächste Zeile setzt den Port, unter dem man Mopidy erreichen kann, die dritte den Namen, unter dem der Server erscheint, wenn man mit einem Client nach Mopidy-Servern sucht.
Unter dem Schlüssel [local] kann man das media_dir auf den Pfad seiner MP3-Sammlung setzen. Belässt man den Wert auf /var/lib/mopidy/media, so muss man seine Sammlung eben in dieses Verzeichnis kopieren und berücksichtigen, dass die Speicherkarte dafür groß genug ist. Liegt die Sammlung jedoch auf einem Netzwerklaufwerk (zum Beispiel auf einem NAS), so muss man hier den Mount-Point eintragen.
In letzterem Fall kann es beim initialen Indizieren der MP3s durch Zugriffsverzögerungen zu Timeouts kommen. Um diese zu vermeiden, empfiehlt es sich, die Option scan_timeout auf 5000 (Millisekunden) oder höher zu setzen.
Um die verfügbaren Mediendateien auch abspielen zu können, müssen Sie deren Indizierung mit
sudo -u mopidy mopidy --config :
./etc/mopidy local scan
auslösen. Dieser Prozess kann bei Musiksammlungen im Bereich von mehreren 10 GByte durchaus mehrere Stunden dauern und beschäftigt den Raspi reichlich. Ist der erste Scan schließlich durchgelaufen, so tauchen die gefundenen Stücke im Web-Interface unter „Browse/ Local media“ auf. Voilà – die Musicbox ist fertig befüllt und wartet auf Anfragen. Dieser Vorgang muss nach einer Aktualisierung der Mediendateien explizit erneut angestoßen werden. Beachten Sie, dass Sie Mopidy nach jedem weiteren Scan neustarten müssen, damit das Programm die aktuelle Datenbank verwendet.
Weiterhin empfiehlt es sich, den Schlüssel [tunein] einzufügen:
[tunein]
timeout = 5000
So vermeiden Sie Timeouts beim Browsen der verfügbaren Radiostationen.
Nun reicht ein sudo systemctl restart mopidy, um den Server mit den neuen Einstellungen zu starten. Unter der IP-Adresse beziehungsweise dem DNS-Namen und dem Port 6680 (zum Beispiel http://raspberrypi:6680) sollte jetzt ein Link auf den Mopidy-Musicbox-Webclient erscheinen.
Mit sudo systemctl enable mopidy aktiviert man Mopidy als Dienst. Nach einem Reboot befindet sich das System schließlich im finalen Zustand. Sollten jetzt noch Probleme auftauchen, so kann man mit sudo systemctl status mopidy den aktuellen Status des Dienstes erfragen.
Im Web-Interface kann man unter „Browse/TuneIn“ eine Radiostation seiner Wahl aussuchen. Unter „Streams“ lässt sich die Auswahl in die „Favorites“ des Programms übernehmen. Hier gibt man auch Stationen ein, die nicht im Verzeichnis von TuneIn enthalten sind. Und spätestens jetzt sollte aus den Lautsprechern der Musicbox auch Sound rauskommen.
Auch mit einem Smartphone ist es möglich, Mopidy zu steuern. Bereits der Mopidy-MusicBox-Webclient im Smartphone-Browser reicht dafür aus. Die App Mopidy Mobile für Android ist eine empfehlenswerte Alternative.
Hier kommt der mit der Option zeroconf festgelegte Name, also zum Beispiel zeroconf = Michaels Musicbox, zum Tragen: Unter diesem Namen erscheint der Mopidy-Server in der Auswahlliste von Mopidy Mobile, ohne dass man die Web-Adresse des Servers erst eingeben müsste. Nach einfachem Antippen landet man auch schon in der Menüstruktur. Der Zeroconf-Mechanismus funktioniert nur im lokalen Netz.
Start me up!
Manchmal wird man feststellen, dass entweder der Bluetooth-Empfänger oder Mopidy partout nicht beginnen wollen, den gewünschten Stream zu spielen. Dafür gibt es zwei potenzielle Ursachen: Ist noch eine Bluetooth-A2DP-Verbindung mit einer Quelle offen, so kann das Gerät keine andere Quelle wiedergeben. Windows ist hier leider besonders anhänglich und verbindet sich gerne automatisch mit allen sichtbaren gekoppelten Geräten, ohne dass man großen Einfluss darauf hätte. In Bluetoothctl sieht man mittels des Befehls info, welches Gerät gerade mit dem Raspi gekoppelt ist und kann es dann auf dem entsprechenden Client oder mit disconnect auf dem Raspi gleich trennen.
Zum Kasten: ALSA, BlueZ und kein PulseAudio
Nun sollten sich wieder andere Quellen mit dem Raspi verbinden und Mopidy auch wieder seinen Dienst verrichten. Enthält die Mopidy-Warteschlange („Queue“) noch Stücke, so lassen sich auch keine Bluetooth-Quellen wiedergeben, auch wenn Mopidy selbst gerade nichts abspielt. In diesem Fall muss man mit dem Web- oder Smartphone-Client die Queue leeren.
Auch auf der Hardware- und Netzwerkseite lassen sich noch ein paar Klippen umschiffen: Ist die Lautstärke des Raspi zu gering, so kann man sie mit dem Kommandozeilenprogramm alsamixer anpassen. Stellt man beim Zugriff auf Mopidy vom Smartphone oder Browser per WLAN fest, dass es hier sporadisch zu initialen Wartezeiten von mehreren Sekunden kommt, so ist wahrscheinlich der WLAN-Adapter des Raspis schuld. Ist dieser längere Zeit nicht in Gebrauch, so fällt er in den Stromsparmodus und erwacht erst ein paar Sekunden nach einer Anfrage von außen wieder, was für eine Anwendung wie den Mopidy-Server natürlich wenig erfreulich ist. Im offiziellen Raspberry-Pi-Forum wird beschrieben, wie man den Sleep-Modus des WLAN-Adapters beim Raspi deaktivieren kann [4]. Dieser Mechanismus hat jedoch keine hundertprozentige Erfolgsgarantie, da er zu einem gewissen Grad vom verwendeten WLAN-Adapter abhängt und zudem auch noch ein Problem dieses Features mit dem aktuellen Linux-Kernel von Raspbian Stretch besteht.
Will man die Robustheit des Dateisystems gegen Datenverluste beim Abschalten erhöhen, so kann man, wie unter ct.de/yfvp beschrieben, den größten Teil des Dateisystems als nicht beschreibbar (read-only) konfigurieren. Hierbei sollte man beachten, dass Mopidy die Schreibrechte auf das Verzeichnis /var/lib/mopidy explizit behalten muss, da der Dienst sonst nicht mehr funktioniert.
Ausblick
Die neue Musicbox Mk II macht schon eine Menge Spaß, bietet aber auch noch großes Potenzial für mehr. Es seien zum Beispiel die Erweiterungen für Streaming-Dienste wie Spotify oder Soundcloud erwähnt. Ein umfangreicher Überblick über die verfügbaren Erweiterungen findet sich auf der Mopidy-Website. Also ran an die Tasten! (mls@ct.de)
Downloads und Links:ct.de/yhw9