Multiroom Audio mit LogitechMediaServer

Im Herbst letzten Jahres habe ich mir zu Hause eine Multiroom Audio Lösung mit dem Logitech Media Server in Verbindung mit node-red zur Automation gebaut. Der Artikel ist aus einem älteren Forenbeitrag entstanden.

Ich habe verschiedene Hardwarelösungen (nanoPi, nanoPiAir und RaspberryPi Zero) qualitäts- und kostentechnisch gegenüber gestellt. Den RasperryPi ZeroW gab es damals noch nicht.

Folgendes Funktionen sind bis jetzt umgesetzt:

  • Abspielen verschiedener Inhalte in verschiedenen Räumen
  • Synchrones Abspielen von einem Inhalt in mehrere Räumen
  • Jeden Player als Airplay-Empfänger nutzen
  • beliebiges ARM-Board/Linux als Squeeze-Player nutzen (RPi, RPi Zero, NanoPiNeo, NanoPiNeoAir jeweils mit USB Soundkarte)
  • Airplay-Geräte als Squeeze-Player nutzen (ginge auch mit Chromecast)
  • DLNA-Geräte als Squeeze-Player nutzen, leider dann nicht synchron möglich wegen Umwandlung
  • Abspielen MP3’s, Webradio, Youtube (Spotify geht, braucht aber einen kostenpflichtigen Account)
  • Anbindung an node-red um Lautsprecher ein/aus zu schalten wenn Musik läuft
  • Anzeige aktueller Titel, Steuerung Player per node-red
  • …more to come

Server

Der Logitech Media Server (Suqeezebox) läuft bei mir auf meinem x86/64 Server, den ich sowieso zu Hause habe. Auf diesem Server liegen auch meine über die Jahre gesammelten MP3’s. Es läuft Ubuntu 16.04.2 und installiert habe ich dann einfach die Debian-Pakete des LMS: http://wiki.slimdevices.com/index.php/Debian_Package
Das Ganze sollte aber genauso auf einem RPi mit einer USB-Festplatte funktionieren.

Der LMS hat ein Webinterface, das sich per http://<ip/host>:9000/ aufrufen lässt. Zugegeben, das ist ziemlich altbacken aber reicht für rudimentäre Bedienung und Konfiguration. Dort wird dann auch das Musikverzeichnis konfiguriert und das Durchsuchen angestoßen. Der LMS ließt die ID3-Tags und kategorisiert die Musik und macht sie durchsuchbar.

LMS selbst lässt sich per Plugins erweitern, auch aus Drittquellen. Dafür gibt es auch eine recht aktive Community. Wichtig waren für mich diese hier: https://github.com/philippe44
Ich betreibe den LMS ohne jeglichen Account (myqueezebox, etc.) – einzig einen Youtube-API Key musst ich bei Google erzeugen um die Youtube-Funktionalität zu nutzen.

Player

Als Player setze ich aktuell einen NanoPiNeo, einen RaspberryPi Zero, ein AppleTV und ein altes Noxon iRadio per DLNA ein. Als tragbaren Player nutze ich den NanoPiNeo Air:

Den NanoPiNeoAir kann ich nur eingeschränkt empfehlen, da mit ihm nur noch sehr schwer SSH-Kommunikation per WLAN möglich ist, wenn per USB Sound ausgegeben wird. Hatte dazu auch ne längere Diskussion im Armbian Forum https://forum.armbian.com/index.php/topic/3269-nano-pi-neo-air-unstable-wi-fi/
Aktuell läuft Ubuntu 16.04.1 bzw Debian Jessie auf den kleinen Dingern. Als Software nutze ich Squeezelite, das ich anhand dieser Anleitung installiert habe: http://www.gerrelt.nl/RaspberryPi/wordpress/tutorial-installing-squeezelite-player-on-raspbian/

Update 2017: Mit dem aktuellen Armbian kommt es kaum noch zu Problemen beim nanoPiAir.

Theoretisch lässt sich als Squeeze-Player auch ein altes Android Telefon nutzen oder ein RPi-1. Jeder Windows PC sollte genauso funktionieren. Ob ein Linux-Sat-Receiver auch geht, hab ich noch nicht geschaut.

Steuerung

Gesteuert werden kann der LMS natürlich durch das bereits erwähnte Webinterface. Richtig Spaß macht es aber erst mit einer passenden App auf dem Handy/Tablet. Unter Android habe ich Squeezer ausprobiert, was seinen Dienst tadellos erfüllt. Allerdings hab ich nur ein sehr sehr sehr sehr günstiges Android-Tablet zum probieren gehabt und ich glaube dadurch alleine blieb der Spaß auf der Strecke.

Schlussendlich habe ich iPeng 9 für iPad/iPhone gekauft. Mit 8,99€ wirklich happig, aber es lohnt sich in jedem Fall. Die App ist ordentlich geschrieben und bedient alle Möglichkeiten des LMS:

iPad

iPhone

node-red

Hier hab ich noch nicht so viel gemacht und nur den Player in der Küche angebunden. Ich prüfe jede Sekunde den mode des players und schalte bei play die Steckdose der Aktivboxen ein. Wenn auf pause gewechselt wird, wird 2 Minuten gewartet und dann die Steckdose wieder aus geschaltet.

Zusätzlich lasse ich noch im Dashboard anzeigen was gerade läuft. Da bin ich aber noch nicht ganz fertig.

(für „only when changed“ kann man natürlich auch den rbe-node nehmen)

Kosten

Kommen wir zum spannenden Teil, wo liegen die Kosten pro Player?

Die nanoPi’s habe ich direkt bei FriendlyElec bestellt, Lieferzeit ca. 3,5 Wochen. Mittlerweilse sind diese aber auch schon in DE bestellbar.

NanoPiNeo (Ethernet)
Board: 10€ (512MB)
SD-Karte 7€ (Sandisk 16GB)
GooBay 5V/2A Netzteil 7€
Generic C-Media USB Sound 3€
—–
28,-€

NanoPiNeoAir (WLan)
Board: 20€
IPEX Antenne ca. 5€
GooBay 5V/2A Netzteil 7€
Generic C-Media USB Sound 3€
(keine SD-Karte notwendig, da internes 8GB eMMC)
—–
35,-€

Präferierte Hardware

Empfehlen mag ich einen Raspberry Pi Zero mit PhatDAC. Der PhatDac ist eine „echte“ Soundkarte für den Rapsberry Pi Zero. Klanglich ist man dabei einfach in einer anderen Welt gegenüber den China-C-Media-USB-Soundkarten, das hört  sogar das ungeübte Ohr.

Raspberry Pi mit PhatDAC und WLan-Stick

Raspberry Pi Zero von thepihut (WLan)
Board: 4,50€ (4£)
PhatDAC 13,70€ (12£)
WiFi USB mini + OTG Adapter 8,50€
SD-Karte 7€ (Sandisk 16GB)
GooBay 5V/2A Netzteil 7€
—–
40,70€

Natürlich kommt da dann immer noch die gewünschte Aktivbox dazu. Für etwas qualitativ hochwertiges, sollte man schon um die 70-80€ ausgeben. Ein Sonos Play 1 ist also Preislich nicht ganz soweit davon entfernt.
Man muss für sich entscheiden ob der Bastellaufwand die Vorteile gegenüber dem Sonos aufwiegt.

Hier eine weitere Idee, wie man den Player schick in einer Regalbox verbauen kann: http://indibit.de/multiroom-audio-wlan-lautsprecher-selber-bauen/ – die Lösung mit den zwei Netzteilen hat mir nicht ganz so gut gefallen.

Update 2017: Durch den RaspberyPi ZeroW kann man die Kosten für den bevorzugten Player noch mal um 2,- € senken. Der ZeroW liegt bei 10,-£ und man benötigt dann eben keinen separaten WLan-Stick mehr.

9 Kommentare

  1. Guten Tag ; Ich habe eine Frage , da ich ein ähnliches Projekt habe würde ich gern wissen wie du in node red den Zustand abfragst ob ein Audio stream läuft oder nicht . Betreibe eine usb Soundkarte am Raspberry 2 .
    Mfg.

      1. Danke aber Irgendwie bekomme ich das noch nicht gebacken , könntest Du mir den Code von da an was du sendest bis „only when changed“ senden , ich versuche mich dann langsam reinzufressen . Wäre dir sehr dankbar .
        Bis dann Peter

  2. Hallo Patrik,
    gute Anleitung von Dir. Ich habe auch konfigurations Problem mit dem node-red-contrib-squeezebox.
    Ich habe zwei piCorePlayer am Server die ich über node red steuern möchte. Die reagieren aber auf kein play oder pause. Kannst Du mir ein Konfigurationsbeispiel zukommen lassen?

    1. Hey Christoph,
      sorry für die späte Antwort. Hier mal das Auslesen des aktuellen Titels meines SqueezeLight-Players „Büro“.
      Hoffe das hilft weiter.

      Gruß,
      Patrik

      [{"id":"c53de97e.b1dce","type":"change","z":"c3e29e37.b6d1e","name":"get current_title","rules":[{"t":"set","p":"bueroPlayState","pt":"flow","to":"payload.result.mode","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"payload.result.current_title","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":2240,"wires":[["93b59bee.bc67e8"]]},{"id":"4d3f1b89.9a7b24","type":"ui_text","z":"c3e29e37.b6d1e","group":"7cb19f56.64bbe","order":1,"width":0,"height":0,"name":"","label":"","format":"{{msg.payload}}","layout":"col-center","x":530,"y":2320,"wires":[]},{"id":"2bf5ded1.47dc62","type":"inject","z":"c3e29e37.b6d1e","name":"","topic":"","payload":"status","payloadType":"str","repeat":"5","crontab":"","once":false,"x":120,"y":2240,"wires":[["232698b5.c0b18"]]},{"id":"93b59bee.bc67e8","type":"function","z":"c3e29e37.b6d1e","name":"play icon","func":"nif(flow.get('bueroPlayState') == 'play'){n msg.payload = ' ' + msg.payload;n} else {n msg.payload = ' '+ msg.payload;n}nnreturn msg;","outputs":1,"noerr":0,"x":520,"y":2280,"wires":[["4d3f1b89.9a7b24"]]},{"id":"232698b5.c0b18","type":"squeezebox-out","z":"c3e29e37.b6d1e","squeezebox_server":"ae3882e3.904cb","player_name":"Büro","command":"","x":310,"y":2240,"wires":[["c53de97e.b1dce"]]},{"id":"7cb19f56.64bbe","type":"ui_group","z":"","name":"Musik","tab":"5bec5a0a.5e2244","order":2,"disp":true,"width":"6"},{"id":"ae3882e3.904cb","type":"squeezebox-server","z":"","host":"http://","port":"9000","name":"Logitech Media Server"},{"id":"5bec5a0a.5e2244","type":"ui_tab","z":"c3e29e37.b6d1e","name":"Büro","icon":"fa-desktop"}]

  3. Hi Patrick,
    Das ganze sieht sehr viel versprechend aus….
    Leider bin ich sowohl bei NodeRed als auch bei LMS nicht so super bewandert…
    Kannst Du nochmal genau darauf eingehen wie du die Nodes konfiguriert hast und ggf wo ich die Befehle (msg.payload) herbekomme, die verwendet werden können?
    Ich bekomme aktuell nicht mal einen brauchbaren Status zurück…

    Danke und Gruß Jochen.

    1. Hey Jochen,

      hier mal beispielhaft der Flow wie man den aktuellen Titel aus dem Player „Büro“ ausließt:

      [{"id":"c53de97e.b1dce","type":"change","z":"c3e29e37.b6d1e","name":"get current_title","rules":[{"t":"set","p":"bueroPlayState","pt":"flow","to":"payload.result.mode","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"payload.result.current_title","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":2240,"wires":[["93b59bee.bc67e8"]]},{"id":"4d3f1b89.9a7b24","type":"ui_text","z":"c3e29e37.b6d1e","group":"7cb19f56.64bbe","order":1,"width":0,"height":0,"name":"","label":"","format":"{{msg.payload}}","layout":"col-center","x":530,"y":2320,"wires":[]},{"id":"2bf5ded1.47dc62","type":"inject","z":"c3e29e37.b6d1e","name":"","topic":"","payload":"status","payloadType":"str","repeat":"5","crontab":"","once":false,"x":120,"y":2240,"wires":[["232698b5.c0b18"]]},{"id":"93b59bee.bc67e8","type":"function","z":"c3e29e37.b6d1e","name":"play icon","func":"\nif(flow.get('bueroPlayState') == 'play'){\n msg.payload = ' ' + msg.payload;\n} else {\n msg.payload = ' '+ msg.payload;\n}\n\nreturn msg;","outputs":1,"noerr":0,"x":520,"y":2280,"wires":[["4d3f1b89.9a7b24"]]},{"id":"232698b5.c0b18","type":"squeezebox-out","z":"c3e29e37.b6d1e","squeezebox_server":"ae3882e3.904cb","player_name":"Büro","command":"","x":310,"y":2240,"wires":[["c53de97e.b1dce"]]},{"id":"7cb19f56.64bbe","type":"ui_group","z":"","name":"Musik","tab":"5bec5a0a.5e2244","order":2,"disp":true,"width":"6"},{"id":"ae3882e3.904cb","type":"squeezebox-server","z":"","host":"http://lms.fritz.box","port":"9000","name":"Logitech Media Server"},{"id":"5bec5a0a.5e2244","type":"ui_tab","z":"c3e29e37.b6d1e","name":"Büro","icon":"fa-desktop"}]

      1. Hi Patrick,
        Nachdem ich herausgefunden habe, wie ich mit dem Code von Dir umzugehen habe, hat er mich schon mal ein ganzes STück weiter gebracht!!!
        Danke hierfür!

        Allerdings stellen sich mir noch ein paar Fragen, die ich aber vemutlich größtenteils selbst rausfinden muss…
        Geschaft habe ich schonmal einen Lautstärkeregler als „Slider“ einzubauen, aber irgendwie weiß ich immer noch nicht, was so alles geht….
        Über den Flow von Dir hab ich rausfinden können was er bei der Abfrage so alles ausgibt und auch schon ein wenig damit herumspielen können.

        Bei Radiosendern hab ich es sogar geschaft den Artist und den Titel aus dem „remoteMeta“ auszulesen. Hierbei scheitere ich aber beispielsweise daran beide gemeinsam auszugeben, kannst du mir hierzu einen Tipp geben?
        Ist das was bei der Abfrage zurückgemeldet wird, alles was man mit dem Player machen kann oder gibt es irgendwo eine Liste mit funktionerenden bzw. möglichen befehlen?
        Play
        Stop
        Pause
        Volume
        Ist mit klar, aber geht da noch mehr? Z.B. Die Befehle verknüpfen zu einem, Bestimmte Lieder/Playlists/oder Streams starten etc.?

        Danke und Gruß,
        Jochen

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.