When I first heard about Sonos I was impressed. Completely synchronized music playing in every room is something I’ve always wanted, but the price seemed ridiculous, especially if you like the speakers you already own. Most of their products have a speaker integrated into them, forcing you to ditch any Hi-Fi equipment you might already own. Also I like keeping my own library of digital music and Sonos steers users towards using streaming services.1
For a while I was convinced there wasn’t a good open-source solution that could
rival Sonos, but then I started playing with
forked-daapd. It’s like
iTunes but better. It scans your music library and allows you to
stream it to Airplay receivers around the house. It also accepts audio via
pipe so you can hook it up to receive audio from other sources and
send it to your speakers.
For receivers, Volumio is a great OS that you can install on a Raspberry Pi. It has Airplay reception built in, with plugins for Spotify and other services. This combined with hardware from HiFiBerry gets you a high-quality output in the format of your choice for under $100.
For example I bought some cheap but awesome Edifier speakers for our home office and these are connected via an optical cable to a HiFiBerry Digi+ on a Raspberry Pi 3.
In the living room I have an older Onkyo TR-NX414 receiver that receives audio from via the optical out on a Behringer UCA202 connected to an Intel NUC. Eventually I’ll upgrade the receiver to something that has Airplay built in, but the point is that with DIY-ing this yourself you have the flexibility to use whatever hardware you have. My dad’s old beat-up but otherwise great-sounding Bose 301s still find use in the garage with this system.
My server is an old PC running Ubuntu which runs everything to do with home automation
and home audio with Docker. My full config for this machine is kept here. The
relevant piece is the
daapd ├── Dockerfile ├── forked-daapd.conf └── start.sh
I couldn’t find a good pre-built Docker image for forked-daapd but writing my
own was pretty simple. To set this up copy the
daapd directory and add a
docker-compose.yml with the following:
daapd: container_name: daapd build: daapd network_mode: host volumes: - /mnt/pool/tunes:/mnt/pool/tunes:ro - ./daapd/forked-daapd.conf:/etc/forked-daapd.conf environment: - MEDIA_SERVER_NAME=Home - PUID=1000 env_file: - ./daapd.env restart: always
Be sure to adjust the
/mnt/pool/tunes volume to where your music is stored. You can reference the forked-daapd.conf in the project repo for its available options and their defaults.
streaming spotify around the house
Despite what I think about streaming music sometimes you just want to throw Spotify on and have it play through the whole house during a party or when you can’t be bothered to queue up a bunch of music manually. Thankfully there’s the librespot2 open source client which you can pipe right into forked-daapd. One thing that isn’t built in is metadata, which is just a nice thing to have instead of blank album art and empty current track info. A PR was opened but wasn’t accepted for some reason, so I keep a fork of librespot with this feature added.
Like forked-daapd, copy the contents of the
librespot folder and add the following to your
spotify: container_name: spotify restart: always build: librespot depends_on: - daapd volumes: - /mnt/pool/tunes/spotify:/data env_file: - ./librespot.env restart: always
/mnt/pool/tunes to point to your music. You will also need to create a
librespot.env file with your Spotify username, password and a name for the streaming destination.
SPOTIFY_NAME=Home SPOTIFY_USER=myusername SPOTIFY_PASSWORD=mypassword
streaming other audio from macs and phones
Sometimes you need audio from places that aren’t your library or Spotify, like playing from the Bandcamp app, website or from YouTube. Luckily there’s also an open-source Airplay receiver called shairport-sync3 we can pipe into forked-daapd.
The setup for shairport-sync is a lot simpler, just add the following to your
shairport: container_name: shairport image: kevineye/shairport-sync network_mode: host depends_on: - daapd volumes: - /mnt/pool/tunes/airplay:/output - /mnt/pool/tunes/airplay.metadata:/tmp/shairport-sync-metadata environment: - AIRPLAY_NAME=Home command: --metadata-pipename=/tmp/shairport-sync-metadata -o pipe -- /output restart: always
Start Docker with
sudo docker-compose up -d and enjoy your more-capable, cheap, whole-home audio system.
I learned alot about running all this stuff from Benoit Beauchamp’s excellent post about setting up his own whole-home music setup, which differs a bit with the use of mopidy as a music manager, but everything else is the same. This video by James Petersen gave me some cool ideas about how to control the system from Home Assistant.
You can add local music via an app running on a computer, but it’s limited to 65,000 tracks. Amateur hour. ↩
This is also the software the Volumio devices use for Spotify streaming under the hood ↩
This is also the software the Volumio devices use for Airplay reception under the hood. Everything works together. ↩