In my quest to automate my house, I keep looking enviously at the Sonos range of speakers and then recoiling at the price tag. I simply can’t justify £167 per room with other financial commitments, so for some time now I’ve been looking for a solution that I can put together using Open Source components.
I’ve been aware of the Music Player Daemon (MPD) for some years now, so to discover that there is an OpenHAB Binding to allow you to control your music from the same controls as the lights and video started me thinking about how I might use MPD as the basis for a whole-house multi-room audio solution.
There are a large number of variants of the MPD available on-line, and one of the easiest to set-up, with a significant number of plugins, is Mopidy. Written in Python and with support for database-backed library information and most on-line music services (including Spotify and Google Play), Mopidy appears to be a very good MPD-compatible solution. The other advantage that Mopidy has is that it is built in to Gramofon and Pi Musicbox so we already know that it will work on cheap commodity hardware such as the Raspberry Pi.
The downside to MPD is that it has no concept of “zones”. At the moment, to get the multi-room audio we require with a purely MPD solution, we would need to install a NAS of some kind with all of the music on it, then put a device into each room that is connected to the NAS and finally install and run Mopidy on each client. This approach works well for when you want different tracks in each room, but what if you wanted to broadcast the same audio stream throughout the house for a major sporting event or at a party? It’s very difficult to synchronise the audio using MPD as this isn’t really what it’s designed for, resulting in the audio being slightly out of sync as you walk from room to room. This is where Snapcast comes in to the picture.
Snapcast’s README file says:
Snapcast is a multi-room client-server audio player, where all clients are time synchronized with the server to play perfectly synced audio.
This sounds ideal for our purposes, however it was the next sentence that really grabbed my attention:
It’s not a standalone player, but an extension that turns your existing audio player into a Sonos-like multi-room solution.
So here we have OpenSource software that’s designed to help you synchronise your media around the house across multiple rooms. That sounds exactly what I’m after.
Further investigation revealed that not only are there pre-existing Debian packages (I run Ubuntu or Raspian on my devices, so this means I don’t need to compile it myself), but there are “armhf” packages meaning that it will run on the Raspberry Pi and related small computers, and an Android App too allowing me to control/reconfigure the system and even listen to a selected stream on my mobile device.
I’m running out of small computers at the moment as I have a BananaPi running OpenHAB and a RaspberryPi 2B+ running Plex (although it struggles in a major way and needs to be replaced with a proper home media PC, but that’s another blog post!) however I do have an original Raspberry Pi, so I thought I’d play with this as the server and use Android devices as the simulated clients until I can get my hands on some more computers!
So how does all this work?
The first thing to do is decide on how many rooms your solution will cover as this will determine the number of Mopidy processes and client devices you require. I decided on the Lounge, Dining Room, my wife’s craft room, my workbench in the garage and my kid’s rooms as well as our bedroom even though I don’t have all of the devices for them yet.
The next step is to install Mopidy on your server as well as the Moped web interface and the SQLite Backend, and then configure a Mopidy process for each zone. This allows you to play different streams in each room – I’ll cover how to play the same stream in each room later in the tutorial.
Configuration of Mopidy to run multiple instances isn’t really supported as the general feeling is that you should have a proper muti-zone amplifier and use that to switch the audio channels, however, these can run into thousands of pounds very quickly and so it rules them out for my limited budget.
I use Ansible to configure my home automation platform, however, the best way I’ve found to configure Mopidy to run multiple instances is as follows:
- Create a file in /etc/mopidy/ called “core.conf” with the following content:
library = sqlite
scan_flush_threshold = 100
media_dir = /media/nas/Music
- For each of the rooms, create a file with the following content (change the port numbers for each room)
hostname = ::
port = 660X
hostname = ::
port = 668X
zeroconf = mopidy-<room_name>
output = audioresample ! audio/x-raw,rate=48000,channels=2,format=S16LE ! audioconvert ! wavenc ! filesink location=/tmp/snapfifo-<room_name>
- Start the Process for each room as follows:
mopidy –config /etc/mopidy/local.conf:/etc/mopidy/room_name.conf &
(At some point, I plan to write a systemd service to automatically start these properly, but for now this will suffice)
The next step is to install and configure Snapcast.
Snapcast relies on Avahi (also known as the “Bonjour” protocol) to discover other nodes on the network, so make sure that avahi-daemon is installed and running.
Download the latest packages from the git repo for your platform and install them. Now create a file in /etc/default called “snapserver” with one audio sink per room, named the same as the ones in your Mopidy config:
SNAPSERVER_OPTS=”-d -s pipe:///tmp/snapfifo-room_1?name=room_1&sampleformat=48000:16:2&codec=flac -s pipe:///tmp/snapfifo-room_2?name=room_2&sampleformat=48000:16:2&codec=flac -s pipe:///tmp/snapfifo-room_3?name=room_3&sampleformat=48000:16:2&codec=flac”
Then restart the snapserver service.
Finally, we install snapclient on all of our media devices in the various rooms and start them.
Install the app on an Android device (it’s available from the same place you downloaded the debian packages, although you may need to put your Android device into developer mode first to install unauthorised packages) and then launch it. You should see a tab for each room across the top of the screen and a list of clients attached to the first room.
Click on the three dots to the right of each client and you can rename them and assign them to a room as appropriate.
Now browse to the various Moped web interfaces and start the music playing, each of the clients should start playing the appropriate music based on the tracks selected in Moped.
But what about broadcasting one audio stream throughout the house?
I’ve cheated a little bit here. I’ve defined a Snapcast audio sink called “Whole House”, and this appears as a tab in the android client. If I need to stream the same audio throughout the house, I just move all the clients into this “room” and they all immediately receive that audio stream.
Next up will be constructing the audio “clients”, configuring OpenHAB to control all of the Mopidy devices and adding them to the sitemaps for the various rooms.
Finally, I’ll investigate using the OpenHAB TCP binding to manage which devices are connected to which audio streams, allowing me to fully control how the audio is routed from the same remote I use to control the music playing and the volume of each room.