Oh yes, very nerd

Oh yes, very nerd

© 2020

Multi-room audio with Snapcast and Raspberry Pi

Snapcast is an open-source project that streams audio over network so it can be played synchronously, like Sonos. I recently set it up at home with some Raspberry Pis to play Spotify around my apartment. Here’s how I did it. I tried to show my work, so hopefully people can follow along (I’m no Raspberry Pi/Linux expert myself).

Table of Contents:

Software and hardware overview

Here are the software projects involved:

  • Snapcast
  • Snapdroid - Android app, available on Google Play.
  • Snap.Net - Windows snapcast client
  • Librespot - Spotify client
  • Raspberry Pi Tools - For cross compiling for Raspberry Pi Zero W.
  • Raspbian
  • balenaEtcher - For programming Raspbian onto the memory card.
  • Windows Subsystem for Linux - For Windows users, to SSH into the Raspberry Pis, and to compile Librespot. It might be possible without (using Putty, and compiling natively in Windows), but the instructions assume a Linux environment, and I did it in WSL.
  • Spotify - For the Spotify setup to work, you need a paid Spotify account. Snapcast work with lots of other audio stream sources as well (see the docs).

And the hardware I used:

  • Raspberry Pi Zero W - Get the ‘h’ variant to avoid soldering. Any other Raspberry Pi will also work. You need one Pi for each speaker setup and one to serve as an snapcast server. I happened to have an old Raspberry Pi 1 lying around that I used as a server, but using one of the Zeros as both a server and a client should work OK, I tried it at one point with the Raspberry Pi 1.
  • Micro SD cards for the Raspberry Pis. I use 32 GB, but 16 GB should work as well (8 GB might give you trouble).
  • HifiBerry DAC+ Zero - DAC (audio) shield for the Raspberry Pi Zero since it doesn’t have build in audio. You don’t need a DAC if you have built in audio, although it might give you slightly better sound.
  • Exibel X50 - Radio with line in (3.5 mm jack) and USB power. But you can use anything that can receive audio.
  • Audio cables (the HifiBerry gives RCA out, so I’m using an RCA to jack cable, check what your speaker setup needs).
  • USB power sources and cables for the Pis.
  • Memory card reader to program Raspbian onto the Raspberry Pis.

Prepare the software

Snapcast

Snapcast consists of two different programs: snapserver and snapclient. Both are available in Raspbian’s package manager, but the versions are outdated (currently 0.15.0), so we will instead download the newest release from Github (currently 0.19.0). Download the “_armhf.deb” variant of both snapserver and snapclient.

Librespot

Librespot unfortunately doesn’t have builds available, so we need to compile it ourselves. Don’t worry though, I found this pretty straightforward to do. It’s written in Rust, which has a very streamlined build environment.

We need to compile it for the Raspberry Pi, but we don’t want to compile it on the Raspberry Pi because it takes too long. I tried on my Raspberry Pi 1 (comparable to the Zero), and gave up after it had been compiling for 2-3 hours. This means we need to “cross compile”, which just means we compile it on a different architecture (regular computer - x86) than we run it on (Raspberry Pi - ARM).

  1. Get the Librespot source code from Github (link above).
  2. If using the Raspberry Pi Zero or a Raspberry Pi 1 as the audio server, you also need to do the following (because those models have an older version of ARM):
    1. Get Raspberry Pi Tools from Github (see above).
    2. Edit .cargo/config as specified here. Remember to edit the path to the linker to match where you placed the raspberrypi-tools repo. Go ahead and remove the target = "arm-unknown-linux-gnueabihf" line, it gave me trouble. We will instead specify the target when compiling, see below.
  3. Follow Librespot’s compiling guide. We will be using the Pipe backend which does not require any “features”:
    cargo build --release --no-default-features --target="arm-unknown-linux-gnueabihf"
    

    This took about 13 minutes on my cheap laptop, and should give you a single executable file called “librespot” somewhere inside the “target” folder (e.g. target/arm-unknown-linux-gnueabihf/release).

Prepare the Raspberry Pis

Download the latest Raspbian from the link above. For this project, you just need the simplest one (E.g. Raspbian Buster Lite).

Now you need to flash Raspbian onto the SD card. The download page has a link to a guide for this, which you can follow.

This is how I did it (though there looks to be even simpler methods available):

Insert the SD card into the reader. Download balenaEtcher from the link above. Open it and choose the Raspbian Zip file you downloaded and the SD card to flash, and start the process (Click “Flash!”).

Once the flashing is complete, you should be able to open the SD card as a drive, possibly called “boot”. Before removing the SD card, open the “boot” drive and do the following to simplify the setup process:

  1. Create an empty file called “ssh” in the top level. This will cause SSH to be enabled on bootup, so we can access the Raspberry Pi remotely. Otherwise, you need to hook up a screen and keyboard.
  2. Create a “wpa_supplicant.conf” file in the top level with info about your Wifi network, as described Raspberry Pi’s guide. This will allow the Raspberry Pi to connect to Wifi on its first boot, which is also needed for remote access.
  3. If you have a HifiBerry, edit config.txt as described in HifiBerry’s guide. This enables the HifiBerry sound card.

Note that the “boot” drive shows up the /boot/ folder on the Raspberry Pi once it boots up.

Assemble the hardware

Plug in the SD card and mount the HifiBerry. If your Zero doesn’t have headers (the double row of pins for mounting the HifiBerry shield), you need to solder them on first, I used this video to guide me. If you get the “Zero Wh” variant it has the headers already soldered on.

Plug in the power and wait for the Pi to boot up, which might take some extra minutes the first time.

You can go ahead and plug in the audio cables now if you want to, though there’s a bit more to do before we have sound.

Configure the Raspberry Pis

Do the following for each Raspberry Pi you set up, both clients and server.

The Raspberry Pi should now have booted and connected to the Wifi network. To continue, we need the IP address of the Raspberry Pi. You could use something like nmap, but I had limited success with that. Usually, you can log into your router and see all the devices connected to it. If there are a lot, look for the ones called “raspberrypi” or something like that, or diconnect the Raspberry Pi and see which entry disappears.

When you have the IP address, SSH into it:

ssh pi@<IP address>

For example ssh pi@10.0.0.5 (pi is the username). The password should be “raspberry”.

You should now run raspi-config and set a new password (for security, since SSH is enabled) and hostname (to distinguish different Pis from each other later, like when using Snapcast).

Also, do

sudo apt update
sudo apt upgrade

to get the latest software updates.

Install Snapcast and Librespot

From earlier, you should now have snapserver, snapclient and librespot ready.

Exit SSH now if you haven’t:

exit

Clients

Do the following for each client device.

Use scp (“copy over SSH”) to copy snapclient (note the colon after the IP address).

scp <path to download folder>/<snapclient name> pi@<IP address>:

Note that you can access the C:\ drive from WSL via /mnt/c/.

Now SSH back in and install the package.

sudo apt install ./<snapclient name>

Now we need to configure snapclient a tiny bit. Modify SNAPCLIENT_OPTS in /etc/default/snapclient to add the HifiBerry as the sound device:

SNAPCLIENT_OPTS="-s sndrpihifiberry"

To edit the file in a terminal, do sudo nano <filename> (you need sudo for files in /etc/). The name “sndrpihifiberry” I found by calling aplay -l:

$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: sndrpihifiberry [snd_rpi_hifiberry_dac], device 0: HifiBerry DAC HiFi pcm5102a-hifi-0 [HifiBerry DAC HiFi pcm5102a-hifi-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

If you have some other setup than the HifiBerry, check aplay -l for the name of the sound card. That’s what I did to use my MG10XU as one of the clients.

Restart the client to read the new configuration.

sudo service snapclient restart

Now exit SSH.

Server

Do the following for the server device.

Copy snapserver and librespot using scp:

scp <path to download folder>/<snapserver name> pi@<IP address>:
scp <path to librespot build>/librespot pi@<IP address>:

SSH back in and install the packages.

sudo apt install ./<snapserver name>
sudo mv librespot /usr/local/bin/librespot

To configure snapserver to use librespot, add a stream entry to /etc/snapserver.conf (fill in your Spotify user name and password):

stream = librespot:///librespot?name=Spotify&username=<spotify username>&password=<spotify password>&devicename=Snapcast&bitrate=320&nomalize=true&autoplay=false

Also remove any streams added by default (just write a # before the line to remove it).

Restart the server to read the new configuration.

sudo service snapserver restart

Play music

At this point, the server should show up as “Snapcast” in your Spotify under “Devices available” (should be a button located close to the play bar when playing music). If you choose “Snapcast” and play a song, you should hear sound from all your clients, et voilà! There might be a short delay, and also a bit of sputtering as the sound synchronizes.

Snapdroid

I recommend installing Snapdroid (available on Google Play) to have better control and overview over the system. It allows you to see the names of the available clients, and to tweak the individual names, volumes and latencies for each client. It also allows you to listen to the stream.

Snap.Net

You can also install Snap.Net (get the installer from releases on Github) which does the same as Snapdroid, but on a Windows machine. I use both, Snapdroid to control from anywhere and to debug issues, Snap.Net as a client in my office.

Enjoy!