# Multi-room audio ## Intro Although there are some projects with capabilities for sharing or sending playlists between players based in different rooms, or zones, of your house (or office, etc) the problem is usually that some play with a very slight delay, which is off-putting to the human ear. This article looks at technologies for local streaming of audio from one room to another, especially where the timing can be syncronised see also: * [Volumio and MPD](Volumio-and-MPD) * Dedicated headless music player distro based on MPD - see intro below * snapcast volume web ui * [Media Centre](Media-Center) * Full media centre solutions for Pi, rather than simple audio * [Audio Hub](Audio-hub) * looks at software for playing audio files, especially music * [lubuild Music and Multimedia](https://github.com/artmg/lubuild/blob/master/help/use/Music-and-multimedia.md) * Common clients for audio server software * options for remote control * architecture of DLNA / UPnP * how to create and manage playlist files * lots of other useful info * [Audio & Video diagnostics](https://github.com/artmg/lubuild/blob/master/help/diagnose/audio-video.md) * troubleshooting devices and configuration for Audio and Video input and output ## Snapcast This uses a project called SyNchronous Audio Player, which transmits chunks of your music across your home network and ensures they are all played simultaneously. Snapcast is specifically designed for multi-room audio, actively keeping clients playing in sync. On the master device you configure your player to pipe the audio out to SnapServer, then it plays through SnapClient both on the master and on any secondary devices. This makes it a self-managing networked Audio Repeater. See [[#Volume Controller]] below for how to balance volume levels between nodes. Additionally you can use it to switch between multiple audio sources, like a virtual AVR - see [[#Snapserver sources]] below. ### Install #### Raspberry Pi OS install If you don't mind a couple of versions ago, use the debian package: ``` sudo apt install snapserver sudo apt install snapclient ``` ##### Install latest version package These are command line instructions for setting up both the client and the server on Raspbian Lite. They have been tested as working up to Raspberry Pi OS Bullseye in 2022 and since Raspbian Jesse Nov 2016. Before then we had to build from source. - not currently available in Debian * [https://github.com/badaix/snapcast#install-debian-packages] * Notes on package architecture * Raspbian is a port of Debian for `armel` * Pi 3 supports debian `armhf` (hard float) * Check and set the version * Set True or false whether you want the server as well ``` ### Prepare # check if you need to enter sudo password sudo echo # check the latest version at # [https://github.com/badaix/snapcast/releases/latest] SNAPCAST_VERSION=0.26.0 # only set this next one if the DEB has a -1 suffix on the version number SNAPCAST_DEB_SUFFIX=${SNAPCAST_VERSION}-1 # Omit or set these to false if you don't want to... SNAPCAST_INCLUDE_SERVER=TRUE SNAPCAST_INCLUDE_CLIENT=TRUE ``` ``` ### Download # download packages for Raspberry Pi architecture if [[ $SNAPCAST_INCLUDE_SERVER = TRUE ]] ; then ( wget https://github.com/badaix/snapcast/releases/download/v$SNAPCAST_VERSION/snapserver_${SNAPCAST_DEB_SUFFIX:-$SNAPCAST_VERSION}_$(dpkg --print-architecture)_$(lsb_release --codename --short).deb ) ; fi if [[ $SNAPCAST_INCLUDE_CLIENT = TRUE ]] ; then ( wget https://github.com/badaix/snapcast/releases/download/v$SNAPCAST_VERSION/snapclient_${SNAPCAST_DEB_SUFFIX:-$SNAPCAST_VERSION}_$(dpkg --print-architecture)_$(lsb_release --codename --short).deb ) ; fi ### Install packages and dependencies if [[ $SNAPCAST_INCLUDE_SERVER = TRUE ]] ; then ( sudo apt install -y ./snapserver_${SNAPCAST_DEB_SUFFIX:-$SNAPCAST_VERSION}_$(dpkg --print-architecture)_$(lsb_release --codename --short).deb #sudo dpkg -i snapserver_${SNAPCAST_DEB_SUFFIX:-$SNAPCAST_VERSION}_armhf.deb ) ; fi if [[ $SNAPCAST_INCLUDE_CLIENT = TRUE ]] ; then ( sudo apt install -y ./snapclient_${SNAPCAST_DEB_SUFFIX:-$SNAPCAST_VERSION}_$(dpkg --print-architecture)_$(lsb_release --codename --short).deb #sudo dpkg -i snapclient_${SNAPCAST_DEB_SUFFIX:-$SNAPCAST_VERSION}_armhf.deb ) ; fi # add any missing dependencies #sudo apt update #sudo apt -f install -y ``` You may get a warning at the end, `.deb couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied)`. In most cases you can ignore this, especially if the snapcast component installation was carried out. Ideas to avoid the error altogether include switching to dpkg install or downloading the .deb into the more permissive location `/tmp`. An example client configuration ``` cat < .local/share/applications/snapclient.desktop [Desktop Entry] Encoding=UTF-8 Type=Application Name=SnapCast client Exec=lxterminal --title="SnapCast client" --command="snapclient" Terminal=false Categories=AudioVideo;Player;Audio;Mixer Comment=Start the SnapCast client GenericName=Synchronised Audio Player Icon=sound Keywords=Player;snapclient;snapcast EOF ``` #### Lubuntu Pulse If you have issues with audio volume, first check the log or command output to see ``` ServerSettings - buffer: 1000, latency: 0, volume: 100, muted: 0 ``` which should not be muted - if in doubt also check the any multiroom volume control app you may have set up. Otherwise try diagnosing using the `pavucontrol` GUI audio settings app, or using `pactl` on the command line. ``` # find the current sink inputs pactl list sink-inputs # see which client is snap pactl list short clients # see full details pactl list clients ``` #### macOS Snapclient build ``` ### Install Prerequisites # credit https://github.com/badaix/snapcast/blob/master/doc/build.md#macos-native # 1. command line to for xcode tools $ xcode-select --install # accept when prompted to Install around 130 MB of command line dev tools # 2. installed homebrew from http://brew.sh/ # 3. required libraries $ brew install flac libsoxr libvorbis boost opus ### Obtain Source # 4. load the source version you want $ git clone https://github.com/badaix/snapcast/ # no longer using... # git submodule update --init --recursive $ cd snapcast/ $ git checkout develop $ git branch -v ### Build Snapclient $ cd client $ make TARGET=MACOS # this gave only one warning (macos support is experimental) and created: # snapclient browseZeroConf player decoder # and controller.o time_provider.o client_connection.o stream.o snapclient.o $ sudo make install TARGET=MACOS # echo macOS # macOS # install -s -g wheel -o root snapclient /usr/local/bin/snapclient # install -g wheel -o root snapclient.1 /usr/local/share/man/man1/snapclient.1 # install -g wheel -o root etc/snapclient.plist /Library/LaunchAgents/de.badaix.snapcast.snapclient.plist # launchctl load /Library/LaunchAgents/de.badaix.snapcast.snapclient.plist ``` Note that this installs the program as a launchd 'service' so you would control it using the following commands: ``` # suspend the service launchctl unload /Library/LaunchAgents/de.badaix.snapcast.snapclient.plist # rei launchctl unload /Library/LaunchAgents/de.badaix.snapcast.snapclient.plist ``` see [[#macOS Snapclient diagnostics]] below for troubleshooting tips ### Server Snapserver not only feeds audio streams to numerous synced clients, but it can also 1. switch between multiple sources 2. control master volume (as well as volume to specific clients) In this way it is similar to an Audio Amplifier unit (an 'amp' in 1970s hifi terms) or an Audio Video Reciever (an 'AVR' in 2000's home cinema terms). Look for the [[#Volume controller]] section below - we will look at sources after some tech notes #### technical notes Snapcast server reads PCM chunks from the named pipe /tmp/snapfifo, so can transmit any PCM audio you can send to this file. The Snapcast transmissions use TCP port 1704, previously registered to IANA as bcs-broker, from knoware.nl. The developer still hopes to publish details of the Snapcast binary streaming protocol. The Snapcast Control protocol uses TCP port 1705, previously registered to IANA as Slingshot, a financial market data feed protocol from the nineties. The developer has published the API details at https://github.com/badaix/snapcast/blob/master/doc/json_rpc_api/v2_0_0.md #### Snapserver sources Here are some suggested sources of audio input for snapcast: * Spotify - using the librespot free library, - providing you have a paid Spotify subscription - there are various packages using librespot, or you can compile using Rust Cargo * Music Player Daemon * the classic linux way to network your music uPnP style * mpd package makes it easy to 'sink' your audio into snapcast's 'fifo pipe' * mopidy wraps mpd and also makes it easy * Bluetooth * the easy way to throw audio from most devices * the simplest way to make the back-end can vary * now using custom combined auto-configure script for BlueZ + ALSA combo * Airplay * for your Apple (and compatible) devices * Shairport-sync is a mature and packaged project * cornrow works but has less docs and community power * Some audio players are installed as a service, but it can be useful (where possible) to have sources executed directly by Snapcast, so that it grabs their audio output directly via `stdout`. ##### Spotify source using librespot The simplest way to connect to a spotify source is using the excellent `librespot` library, which is well-supported in snapserver. Unfortunately for debian-based systems like RaspberryPi there are no direct packages from the developers, but it is quite straightforward to build and install librespot using the rust cargo toolchain. ``` # use the recommended command to install the rust compiler and its package manager curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh ``` * when prompted, press Enter for default installation type * that might take a while, then you continue ```bash # source the environment into your current shell . "$HOME/.cargo/env" # install the dependencies recommended by librespot https://github.com/librespot-org/librespot # (so also-sys build finds 'alsa.pc' and compiles without errors) sudo apt install -y build-essential libasound2-dev cmake libclang-dev # now get the librespot package and dependencies and compile them cargo install librespot # that command may take some time to download and compile over 300 individual crates # finally, place the binary you just compiled into a common system path sudo cp ~/.cargo/bin/librespot /usr/local/bin/ ``` There were some tribulations behind getting that neat code - all the messing around is documented in [Snacast issue #1035](https://github.com/badaix/snapcast/issues/1035). The cmake and libclang-dev requirement came from 'ring' dependency 'aws-lc-sys' and from 'bindgen'. Other options were used previously, but they have now been moved below for posterity. ###### Spotify headless OAuth Spotify has deprecated password login, so we suggest you use the new [Headless OAuth](https://github.com/librespot-org/librespot/wiki/Options#headless-oauth) to authenticate your Spotify account. ```shell sudo -u snapserver librespot --cache /var/lib/snapserver --enable-oauth --oauth-port 0 ``` - copy the `Browse to:` url to into any browser from where you can access the Spotify account - You are asked to 'Allow Spotify', so click the button to 'Continue to the app' - you **WILL** get a 'Connection Refused' error, which is fine :) - now simply copy the entire url from your browser address bar and paste it back into the command line where prompted `Provide redirect URL` - wait for the authentication to show in the command line - CTRL C to break - the credentials should now be in place with snapserver having access - to check `sudo ls -la /var/lib/snapserver/` - to correct if not`sudo chown -R snapserver:snapserver /var/lib/snapserver` ##### Shairport sync The [Shairport-sync project](https://github.com/mikebrady/shairport-sync) now has debian packages, making it an easy install. ``` sudo apt install -y shairport-sync # disable the service as snapcast runs the process itself sudo systemctl disable --now shairport-sync ``` ##### mpd source ``` FOLDER_MUSIC=/path/to/Music/ FOLDER_PLAYLIST=/path/to/Playlists/ BONJOUR_NAME="My MPD Player" ``` ``` ### mpd sudo apt install -y mpd sudo cp /etc/mpd{,.old}.conf sudo tee /etc/mpd.conf <