Skip to content
ArtMG edited this page Nov 16, 2024 · 24 revisions

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
    • Dedicated headless music player distro based on MPD - see intro below
    • snapcast volume web ui
  • Media Centre
    • Full media centre solutions for Pi, rather than simple audio
  • Audio Hub
    • looks at software for playing audio files, especially music
  • lubuild Music and Multimedia
    • 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
    • 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 <<EOF! | sudo tee /etc/default/snapclient 
# defaults from installed /etc/default/snapclient file
START_SNAPCLIENT=true
USER_OPTS="--user snapclient:audio"

# run sudo snapclient --help to see options available
# and sudo snapclient --list to see PCM devices for soundcard option

SNAPCLIENT_OPTS="--soundcard 1 --host localhost"
EOF!

Arch Linux

For regular ArchLinux the package is also available from AUR at https://aur.archlinux.org/packages/snapcast/ (see https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages) but that would likely not work on ArchinuxArm.

# Build snapcast from source
# credit - https://github.com/badaix/snapcast/blob/master/doc/build.md

sudo pacman -S git

git clone https://github.com/badaix/snapcast.git
cd snapcast/externals
git submodule update --init --recursive

cd ..

sudo pacman -S base-devel
sudo pacman -S alsa-lib avahi libvorbis flac alsa-utils

# either build and install both

make

sudo make installserver
sudo make installclient

# or just make and install client

cd client
make

sudo make install
cd ..

SnapOS

This is a BuildRoot-based embedded OS created by the SnapCast author. Buildroot allows you to created a custom embedded OS image from a linux PC.

For instructions see:

https://github.com/artmg/MuGammaPi/wiki/buildroot#snapos

Client

For the client, that's it. There is a config file /etc/default/snapclient but it should not need tweaking. It normally finds the host using bonjour, but if you have multiple hosts you can specify which in there.

Lubuntu manual control

If you have installed on Ubuntu derivatives using the instructions above, this will create a service to run automatically as the snapclient user, but that might not give you the control you want.

If you want to change the user context

sudo editor /etc/default/snapclient
sudo systemctl restart snapclient.service 

However that still doesn't make it easy to start, stop and change audio settings (volume and output) on the fly, so you can create a shortcut for a manual start in your own context:

#disable the service
sudo systemctl disable snapclient.service 

# create the icon
cat <<EOF > .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
# 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. 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 to authenticate your Spotify account.

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 notsudo chown -R snapserver:snapserver /var/lib/snapserver
Shairport sync

The Shairport-sync project 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 <<EOF!
music_directory "${FOLDER_MUSIC}"
#music_directory "/var/lib/mpd/music" # was default
playlist_directory "${FOLDER_PLAYLIST}"
#playlist_directory "/var/lib/mpd/playlists" # was default

user "mpd" # was default
#user "pi" # this failed as installed granted perms to user mpd
#bind_to_address "localhost" # was default
bind_to_address "any" # was default
#group "audio"

log_file "syslog"
#log_file "/var/log/mpd/mpd.log" # was default
#log_level "default"
db_file "/var/lib/mpd/tag_cache" # was default
pid_file "/run/mpd/pid" # was default
state_file "/var/lib/mpd/state" # was default
sticker_file "/var/lib/mpd/sticker.sql" # was default
zeroconf_enabled "yes"
zeroconf_name "${BONJOUR_NAME}"

#filesystem_charset "UTF-8" # was default
#id3v1_encoding "UTF-8" # was default

# snapcast help - https://github.com/badaix/snapcast/blob/master/doc/player_setup.md#mpd

audio_output {
    enabled "yes"
    type "fifo"
    name "${BONJOUR_NAME} MPD to Snapserver"
    path "/tmp/snapMPDfifo"
    format "48000:16:2"
    mixer_type "software"
}

playlist_plugin {
    name "m3u"
    enabled "true"
}
EOF!
 
sudo systemctl restart mpd
 

#### Test mpd

# Now try to connect with a client.
# You may need to 'Refresh Database' before you see any content
Bluetooth sink

Start by setting up the Bluetooth Audio Sink using the instruction block in Bluetooth audio sink # Legacy Rpi Audio Receiver. This makes it ready to receive sound to the internal headphone jack. Then you need to configure it to go to snapcast instead.

sudo tee -a /etc/modules <<EOF!
# add alsa loopback module for bluealsa-aplay to send bluetooth to snapcast
snd-aloop
EOF!


# direct the bluealsa sound into the loopback device

sudo sed -i.orig 's/--pcm=default/--pcm=plughw:0,0,0/' /etc/systemd/system/bluealsa-aplay.service


### Now set the source(s) you want in snapserver

sudo tee /etc/snapserver.conf <<EOF!
# help - https://github.com/badaix/snapcast/blob/master/doc/player_setup.md
# and - https://github.com/badaix/snapcast/blob/master/doc/configuration.md

# Name is what will appear when choosing the stream using snapcast API

[stream]
# when you send to device 0,0,0 it will loop back on the next device 0,1,0
# to hear a bluetooth stream appears to need a silence trigger
source = alsa://?name=Bluetooth&device=hw:0,1,0&silence_threshold_percent=0.1
EOF!


### and reboot ready to Test it out

sudo reboot 0
# you need to restart so the loopback device gets card #0


#### diagnostics
# list the alsa devices
aplay -l
# list the devices connected through bluetooth
bluealsa-aplay -l

SYSTEMD_PAGER=
service bluealsa-aplay status
service snapserver status

sudo service snapserver stop
snapserver --logging.filter debug

Previous configs used or tried

### Create and use a 'PCM.bluetooth' device
#
# this is an alternative to using --pcm=hw:0,0,0 in bluealsa-aplay
# https://github.com/badaix/snapcast/blob/master/doc/configuration.md#alsa
#
# see section needing debugging below

sudo sed -i.orig 's/--pcm=default/--pcm=bluetooth/' /etc/systemd/system/bluealsa-aplay.service

sudo tee /etc/asound.conf <<EOF!
# /etc/asound.conf
# systemwide equivalent of the per-user .asoundrc files
#
# This prepares the PCM settings going into the alsa loopback device
# credit https://github.com/badaix/snapcast/issues/379#issuecomment-830112664
#
# prefer this over the fifo pipe solution proposed in snapcast player docs
# https://github.com/badaix/snapcast/blob/master/doc/player_setup.md#alsa
#
# with snd-aloop module pre-loaded the loopback device comes first

pcm.snd_card {
    type hw
    card 0
    device 0
    subdevice 0
}

ctl.snd_card {
    type hw
    card 0
    device 0
    subdevice 0
}

# this is the device we name in the bluesalsa-aplay command
pcm.bluetooth {
    type plug
    slave.pcm "snd_card"
}
EOF!
sudo tee /etc/asound.conf <<EOF!
# credit https://github.com/badaix/snapcast/blob/master/doc/player_setup.md#alsa
pcm.!default {
    type plug
    slave.pcm rate48000Hz
}

pcm.rate48000Hz {
    type rate
    slave {
        pcm writeFile # Direct to the plugin which will write to a file
        format S16_LE
        rate 48000
    }
}

pcm.writeFile {
    type file
    slave.pcm null
    file "/tmp/snapfifo"
    format "raw"
}
# left the pipe path as this is the default in snapserver
# you should choose alternative names for other services in a multiple-source configuration
EOF!

Example config for sources above
sudo tee /etc/snapserver.conf <<EOF!
# help - https://github.com/badaix/snapcast/blob/master/doc/player_setup.md
# and - https://github.com/badaix/snapcast/blob/master/doc/configuration.md

# Name is what will appear when choosing the stream using snapcast API

[stream]
source = alsa://?name=Bluetooth&device=hw:0,1,0&silence_threshold_percent=0.2
source = pipe:///tmp/snapMPDfifo?name=MPD
source = airplay:///shairport-sync?name=Airplay&devicename=My%20Play%20TEST%20air&port=5050
source = spotify:///librespot?name=Spotify&username=myUserName&password=myPassWord&devicename=MyServer&bitrate=320&volume=40&params=--device-type%20avr
EOF!

For more help on configuring sources see https://github.com/badaix/snapcast/blob/master/doc/player_setup.md

Diagnosing Snapserver issues

# check the status
sudo service snapserver status

# stop for tests
sudo service snapserver stop

# test until you get it working
snapserver --logging.filter debug

# now restart the service
sudo service snapserver start

Sources no longer used

Cornrow

Cornrow has been suggested as a lightweight bluetooth (AND AirPort) sink. It defaults to using Alsa, but can also output an IP stream. https://github.com/badaix/snapcast/discussions/911

# help https://github.com/mincequi/cornrow
# check version https://github.com/mincequi/cornrow/releases/latest/
VERSION=0.8.1
wget https://github.com/mincequi/cornrow/releases/download/v${VERSION}/cornrowd_${VERSION}_armhf.deb
sudo apt install -y ./cornrowd_${VERSION}_armhf.deb
sudo systemctl unmask cornrowd.service
sudo systemctl enable cornrowd.service

sudo tee /etc/cornrowd.conf <<EOF!
# This is a TOML document.

[bluetooth_source]
codecs = [ 0x0 ]        # As defined in the A2DP specification (SBC (0x0) is ma$
sample_rates = [ 44100, 48000 ]

#[airplay_source]
#name = "myAirplay"
# port = 0              # port to listen on (0 for auto select)
# buffer_time = 2000    # in ms (defaults to 2000ms)

#[alsa_sink]
#device = "default"

[tcp_sink]
host = "127.0.0.1"
port = 4953
EOF!

sudo systemctl start  cornrowd.service

And added the following to /etc/snapcast.conf:

source = tcp://127.0.0.1:4953?name=Bluetooth&sampleformat=44100:16:2

It is very simple, and doesn't have much built-in logging or diagnostics, but you could diagnose Bluetooth issues with bluetoothctl. Note that the cornrow package makes itself mutually exclusive with

Bluetooth via PulseAudio

NicoKaiser's RPi Audio Receiver was as turnkey as you could get. See Bluetooth audio sink # Rpi ready install if you want to know the rights and wrongs in choosing this solution. Or just use it...

wget https://raw.githubusercontent.com/artmg/rpi-audio-receiver/master/install-bluetooth.sh
sudo ./install-bluetooth.sh

Now you can add your source to the snapserver.conf [streams]

source = pipe:///tmp/snapBTfifo?name=Bluetooth
general Bluetooth configuration
BLUETOOTH_DEVICE_NAME="My Bluetooth Sink"

# set pretty name
# credit https://github.com/artmg/lubuild/blob/master/help/diagnose/hardware.md#bluetooth-devices
sudo tee /etc/machine-info <<EOF!
PRETTY_HOSTNAME=${BLUETOOTH_DEVICE_NAME}
EOF!

If you get PIN/passkey errors it might be because previous connections are getting in the way. Try to run bluetoothctl and list devices, then specify the MAC addresses to remove. To diagnose issues with PulseAudio try pacmd list-sources or pacmd list-sinks

If you want both snapserver and snapclient on the same device, and therefore need to configure ALSA in different ways for each, you could use a separate user with a .asoundrc file that sends the output to a special bluetooth pipe.

Multiple sources - auto install

There is a very handy collection of install scripts for various different audio sources: bluetooth, airplay, spotify, upnp, etc

https://github.com/nicokaiser/rpi-audio-receiver

This installs most items as a service, however we want Bluetooth and Spotify to be executed directly by Snapcast so that it grabs the audio from those sources via stdout.

However we are currently using our own fork, whilst waiting for upstream PR to be accepted, to allow Shairport variables before reverting to upstream.

Update PR now accepted, use upstream instead

Clone
sudo apt install -y git

git clone https://github.com/artmg/rpi-audio-receiver.git
cd rpi-audio-receiver
Shairport prep
# for latest release see https://github.com/mikebrady/shairport-sync/releases
export SHAIRPORT_VERSION=3.3.5 
# make sure Shairport install will run with alternative settings
export SHAIRPORT_CONFIGURE="--with-stdout --with-metadata --with-avahi --with-ssl=openssl --with-soxr"
Begin installation

./install.sh

Bluetooth

NB: If you later wish to alter the 'pretty name' that Bluetooth announces, then see https://github.com/artmg/lubuild/blob/master/help/diagnose/hardware.md#bluetooth-devices

Shairport after
# not sure this is needed any more
# sudo usermod -a -G pulse-access shairport-sync

# disable the service as snapcast runs the process itself
sudo systemctl disable --now shairport-sync 

(if it needs Pulse audio then see the config option output_backend = "pa";)

example snapserver config
sudo tee -a /etc/snapserver.conf <<EOF!
# help - https://github.com/badaix/snapcast/blob/master/doc/player_setup.md

# Name is what will appear when choosing the stream using snapcast API

[stream]
source = pipe:///tmp/snapfifo?name=Bluetooth
source = pipe:///tmp/snapMPDfifo?name=MPD
source = airplay:///shairport-sync?name=Airplay&devicename=Kitchen%20sink%20airplay&port=5050
source = spotify:///librespot?name=Spotify&username=userIdNotEmail&password=NotSureHowToEncodeSpecialChars&devicename=MyAudioIn&bitrate=320
EOF!
librespot-dev

Many articles propose Raspotify as a 'thin wrapper' around librespot, to run it as a daemon, but we don't actually need that (as snapcast runs it).

One pre-compiled package for vanilla librespot is the snap package librespot-dev

# if you have not installed `snapd`
# see https://snapcraft.io/install/librespot-dev/raspbian

sudo snap install librespot-dev

you would then need to address snapcast.conf to the location of the snap executable:

source = librespot:///snap/librespot-dev/current/bin/librespot?name=Spotify&username=myuser&password=mypass&devicename=Spotify%20for%20Sanpcast&bitrate=320

The issue with this is that librespot-dev package still appears to be version 0.2 from 2021

other Spotify alternatives
  • say No to install script
    • do not use rpi-audio-receiver version
    • that installs spotifyd as a service
    • we want to run librespot from snapserver
  • For now we use https://github.com/dtcooper/raspotify/
    • we might consider using the cargo package
wget https://dtcooper.github.io/raspotify/raspotify-latest.deb

sudo dpkg -i raspotify-latest.deb
sudo apt-get -f install

sudo systemctl disable --now raspotify # disable the service as snapcast runs the process itself

old mpd

After the server install the following is in /etc/mpd.conf

# Audio Output ################################################################
audio_output {
        type            "alsa"
        name            "alsa"
        device          "hw:0,0"
}

audio_output {
    type            "fifo"
    enabled         "no"
    name            "multiroom"
    path            "/tmp/snapfifo"
    format          "44100:16:2"
}

  • editor /etc/mpd.conf
  • Set enabled "yes"
    • should alsa section be commented out?
  • set format to 48000:16:2
    • this dramatically reduces dropouts by avoiding resampling
  • try mixer_type "software"
    • this allows you to control master volume with MPD
    • does not appear to control it with volumio web interface
  • sync and reboot

For more help see

old notes on Bluetooth sources

For snapcast Bluetooth sources:

See more for using Bluetooth A2DP as a source in Bluetooth-audio-sink

other old snapcast notes

Here's an example config for snapcast, but the PulseAudio configuration was not complete

#wget https://raw.githubusercontent.com/nicokaiser/rpi-audio-receiver/main/install-bluetooth.sh
#sudo ./install-bluetooth.sh

# additional pulse config for snapserver
# credit https://github.com/badaix/snapcast/blob/master/doc/player_setup.md#pulseaudio
sudo tee -a /etc/pulse/default.pa <<EOF!
load-module module-pipe-sink file=/tmp/snapBTfifo sink_name=SnapcastBT format=s16le rate=48000
update-sink-proplist Snapcast device.description=Snapcast
EOF!

Auto switching requirement?

Although these solutions can provide snapserver with a bluetooth A2DP source as an input, would it be feasible to automatically switch sources?

How could we satisfy the following use case:

  • play an MPD-controlled source by default
  • accept incoming bluetooth A2DP connections
  • automatically switch snapserver over to the BT when connected
  • automatically revert to the MPD source when disconnected
  • could MPD player status be used in the logic (e.g. do not switch to BT Sink when MPD is playing)

Snapcast diagnostics

If you get no audio on clients, check server status quickly via Android app

Log onto server and check with sudo service snapserver status

If you are not sure what is happening, or whether your conf file is even valid, stop the service and run the server in command line diagnostic mode:

snapserver --logging.filter debug

For clients use snapclient for both the service and the debug mode.

macOS Snapclient diagnostics

which snapclient
snapclient --version
snapclient --help

sudo launchctl unload /Library/LaunchAgents/de.badaix.snapcast.snapclient.plist
snapclient

snapclient --logfilter *:debug

if that doesn't stop the service use

ps -a | grep snap
sudo launchctl list | grep snap
sudo launchctl remove de.badaix.snapcast.snapclient

Now you will be able to see the detailed Info logs on the console

# this DOESN'T show much
log show --style syslog  --predicate 'senderImagePath contains[cd] "snap"' --info --last 48h

Volume controller

Snapcast has an API for balancing the volume between different 'rooms' playing snap streams.

Android APK

There is a simple and quick Android client. Thanks to the efforts of other developers, badaix has integrated their APK generation upstream to create the Play Store app:

https://play.google.com/store/apps/details?id=de.badaix.snapcast

As well as for tweaking volume and listening, this can be a useful tool for diagnosing the status of Snapcast deployment on your network.

Note that you also appear to be able to create groups and add members with this app. Not sure where else this can be done.

Home Assistant plugin

See https://github.com/artmg/MuGammaPi/wiki/home-automation

This easy to use plug in scans as startup to find all snapclients in your network and for each one it allows you to control volume, mute and source.

It also finds any defined groups, and allows you to control them in the same way, although I have not yet found if it can also manage group memberships.

snapcast-volumio-ui

For this Dancer2 application, written in perl, ready to be deployed onto volumio's plack web engine, see Volumio and MPD

Integrations

Other players

As well as the sound sources above, including Spotify, here are some integrations with other audio players.

Volumio

For Volumio instructions see:

  • [https://volumio.org/forum/multiroom-audio-output-from-volumio-with-snapcast-t3217.html]
  • [https://volumio.org/forum/how-get-multi-room-sync-audio-working-t4685.html]
Kodi
  • although the logical requests have been made
    • e.g. [https://discourse.osmc.tv/t/multiroom-audio-via-snapcast/16836]
  • the limitation on Snapcast with Kodi is that it's linux only
    • [http://forum.kodi.tv/archive/index.php?thread-285516.html]

Example builds

Arch Linux Arm

This is a build with MPD and snapcast


#### Base OS install

MEDIA_DEVICE=sdbX
MEDIA_LABEL=mySDcard
IMAGE_FILENAME=/path/to/ArchLinuxARM-rpi-2-latest.tar.gz
NEWHOSTNAME=myHostname
USER_NAME=mpd
USER_GROUP=mpd
USER_DESC="Music Player Daemon"
USER_PWD=secret
ROOT_PWD=stronger

# NB: Wired Ethernet for now!

# follow instructions in [https://github.com/artmg/MuGammaPi/wiki/arch-linux-install]

#### Audio hardware

sudo pacman -S alsa-utils
# for changes to /boot/config.txt see
# [https://archlinuxarm.org/wiki/Raspberry_Pi]
sudo tee -a /boot/config.txt <<EOF!
dtparam=audio=on
## If you experience distortion using the 3.5mm analogue output:
#audio_pwm_mode=2
EOF!

# if you have a DAC you may need further changes, see
# [https://github.com/artmg/MuGammaPi/wiki/Audio-Hub#dac-drivers]
# NB DACs use I2S (streaming, fire and forget) NOT I2C (Command)


#### Install Music software

##### MPD, ympd - not currently adding upmpdcli

sudo pacman -S mpd 
sudo pacman -S ympd 
sudo pacman -S nfs-utils

PACKAGE_NAME=snapcast
# see [https://github.com/artmg/MuGammaPi/wiki/arch-linux-install#aur-packages]

sudo systemctl enable mpd
sudo systemctl enable ympd
sudo systemctl enable snapserver
sudo systemctl enable snapclient


#### configure

##### nfs

# NB instead of using FQDN either
# a) work out why DHCP client does not pick up suffix
# b) add suffix e.g. via /etc/dhcpcd.conf with `option domain-name "domain1.com";`

# nfs variables
NFS_SERVER=MyNAS.fqdn
NFS_EXPORT=Music
LOCAL_MOUNT=NasMus
# credit [https://github.com/artmg/lubuild/blob/master/help/configure/Networked-Services.md#nfs]
sudo mkdir -p /mnt/nfs/$LOCAL_MOUNT
cat <<EOF | sudo tee -a /etc/fstab
$NFS_SERVER:/srv/exports/$NFS_EXPORT /mnt/nfs/$LOCAL_MOUNT nfs  defaults,timeo=14,soft   0   0
EOF
# arch alternative - no export root and additional options
# $NFS_SERVER:/$NFS_EXPORT   /mnt/nfs/$LOCAL_MOUNT   nfs   rsize=8192,wsize=8192,timeo=14,_netdev	0 0

NFS_SERVER=MyNAS.fqdn
NFS_EXPORT=PlayRw
LOCAL_MOUNT=NasPlayRw


### snapcast

cat <<EOF! | sudo tee /etc/default/snapclient 
# defaults from installed /etc/default/snapclient file
START_SNAPCLIENT=true
USER_OPTS="--user snapclient:audio"

# run sudo snapclient --help to see options available
# and sudo snapclient --list to see PCM devices for soundcard option

SNAPCLIENT_OPTS="--soundcard 1 --host $NEWHOSTNAME"
EOF!

##### mpd

sudo mkdir -p /var/lib/mpd/

# to use user mpd...
sudo touch /var/log/mpd.log
sudo chown mpd.mpd /var/log/mpd.log 
sudo gpasswd -a mpd audio

cat <<EOF! | sudo tee /etc/mpd.conf
# /etc/mpd.conf uses spaces NOT tabs
user        "mpd"

# defaults from installed /etc/mpd.conf
pid_file    "/run/mpd/mpd.pid"
db_file     "/var/lib/mpd/mpd.db"
state_file  "/var/lib/mpd/mpdstate"

# ready for debugging
#log_file           "/var/log/mpd.log"

# local locations
music_directory     "/mnt/nfs/NasMus/Music/"
playlist_directory  "/mnt/nfs/NasPlayRw/Playlists/"

# snapcast server integration
audio_output {
    type            "fifo"
    enabled         "yes"
    name            "my multiroom (snapcast)"
    path            "/tmp/snapfifo" 
    format          "48000:16:2"
    mixer_type      "software"
}

## test direct to alsa in case of issues
#audio_output {
#    type            "alsa"
#    name            "Default Audio Device"
##    device          "bcm2835"
#    mixer_type      "software"
#}

playlist_plugin {
    name "m3u"
    enabled "true"
}
EOF!



## later if required ...
sudo pacman -S upmpdcli
sudo systemctl enable upmpdcli

See also:

  • tips and tricks from Archphile [http://archphile.org/howto/mpd-configuration]
  • list of roll your own software & config [http://krazedkrish.com/blog/2017/01/04/diy-music-server-with-archlinux-raspbery-pi-or-anywhere/]
  • Arch wiki on MPD [https://wiki.archlinux.org/index.php/Music_Player_Daemon]

Issues

audio problems

#### mpd errors

# check card name & device
sudo aplay --list-pcms

#### snapclient issues

# check devices
sudo snapclient --list

sudo snapclient -s 1 -h myHostname

#### silence

# devices muted by default
sudo amixer sset PCM unmute

# set output device
sudo amixer cset numid=3 1 
# 0 for Auto
# 1 for Analog out
# 2 for HDMI
# set volume level high
sudo amixer cset numid=2 1
# -10000 = MIN, 400 = MAX, 0 = MUTE

# test with pink noise output
sudo speaker-test -c 2

# check current settings
sudo amixer contents
# set manually
sudo alsamixer
Clone this wiki locally