Multiroom Audio Streaming with Snapcast

3 minute read

Build and install snapcast

sudo apt install build-essential cmake
sudo apt install libasound2-dev libpulse-dev libvorbisidec-dev libvorbis-dev \
    libopus-dev libflac-dev libsoxr-dev alsa-utils libavahi-client-dev \
    avahi-daemon libexpat1-dev

cmake -B build
cmake --build build --parallel
sudo make -C build install

# airplay
sudo apt install -y shairport-sync
sudo systemctl disable --now shairport-sync

cat /usr/local/etc/snapserver.conf

[http]
# enable HTTP Json RPC (HTTP POST and websockets)
enabled = true
bind_to_address = 0.0.0.0

# which port the server should listen to
port = 1780

# serve a website from the doc_root location
# disabled if commented or empty
doc_root = /usr/local/share/snapserver/snapweb

# TCP RPC #####################################################################
#
[tcp]
# use the address of a specific network interface to just listen to and accept
# connections from that interface
bind_to_address = 0.0.0.0

# which port the server should listen to
port = 1705

# Stream settings #############################################################
#
[stream]
# address to listen on, can be specified multiple times
# use "0.0.0.0" to bind to any IPv4 address or :: to bind to any IPv6 address
# or "127.0.0.1" or "::1" to bind to localhost IPv4 or IPv6, respectively
# use the address of a specific network interface to just listen to and accept
# connections from that interface
bind_to_address = 0.0.0.0

# which port the server should listen to
port = 1704

source = airplay:///shairport-sync?name=airplay&devicename=Snapcast&port=5000
source = pipe:///tmp/snapfifo?name=default

Phicomm R1 Speaker Configuration

WiFi Configuration

adb connect 192.168.43.1
adb push ~/Downloads/adb-join-wifi.apk /data/local/tmp/
adb shell /system/bin/pm install -t /data/local/tmp/adb-join-wifi.apk
adb shell am start -n com.steinwurf.adbjoinwifi/.MainActivity \
    -e ssid avocado -e password_type WPA -e password yourpassword

Install snapcast client

adb push Snapcast-signed-v0.29.0.2.apk /data/local/tmp/
adb shell /system/bin/pm install -t /data/local/tmp/Snapcast-signed-v0.29.0.2.apk
adb shell am start de.badaix.snapcast/.MainActivity

For webclient head to snapweb, download latest release and unzip to /usr/local/share/snapserver/snapweb, and the URL is http://ip.add.re.ss:1780 if SSL not enabled.

DLNA support

shairport-sync does not support video cast, sometimes I want to listen to news from video app, for this case snapcast+shairport-sync does not work, so DLNA is a good option, I use mopidy and upmpdcli to fit my situation.

# Install mopidy etc
sudo apt install \
    python3-gst-1.0 \
    gir1.2-gstreamer-1.0 \
    gir1.2-gst-plugins-base-1.0 \
    gstreamer1.0-plugins-good \
    gstreamer1.0-plugins-bad \
    gstreamer1.0-plugins-ugly \
    gstreamer1.0-tools

python3 -m pip install --upgrade mopidy
sudo apt install mopidy-mpd

sudo add-apt-repository ppa:jean-francois-dockes/upnpp1
sudo apt install upmpdcli

sudo service mopidy start
sudo service upmpdcli start

mopidy configuration

mopidy has two different config files, one for command line, which is:

$HOME/.config/mopidy/mopidy.conf

and the other is for systemd service, which is:

/etc/mopidy/mopidy.conf

Here is my configuration set audio output for snapcast:

sudo cat /etc/mopidy/mopidy.conf
[audio]
output = audioresample ! audioconvert ! audio/x-raw,rate=48000,channels=2,format=S16LE ! filesink location=/tmp/snapfifo

Besides the configs I set above, all current config can be viewed with:

# For systemd service
sudo mopidyctl config
# For command line
mopidy config

If the configuration is changed, a restart is needed:

sudo systemctl restart mopidy
sudo systemctl restart upmpdcli

The following error can be safely ignored, it works anyway:

Feb 02 15:31:13 BayLabs mopidy[1945435]: error: XDG_RUNTIME_DIR not set in the environment.
Feb 02 15:31:13 BayLabs mopidy[1945435]: WARNING  [MainThread] mopidy.audio.gst GStreamer warning: Could not initialise Wayland output

The default UPnP/AV Media Renderer maybe a little bit longer, change it in upmpdcli config file /etc/upmpdcli.conf:

avfriendlyname = Snapcast

Meta stream

For using both airplay and dlna, a meta stream should be added, see this github issue for detail, here is the full configration I used at the moment:

[http]
# enable HTTP Json RPC (HTTP POST and websockets)
enabled = false
bind_to_address = 0.0.0.0
port = 1780

# serve a website from the doc_root location
# disabled if commented or empty
doc_root = /usr/local/share/snapserver/snapweb

# TCP RPC #####################################################################
#
[tcp]
bind_to_address = 0.0.0.0
port = 1705

# Stream settings #############################################################
#
[stream]
# address to listen on, can be specified multiple times
# use "0.0.0.0" to bind to any IPv4 address or :: to bind to any IPv6 address
# or "127.0.0.1" or "::1" to bind to localhost IPv4 or IPv6, respectively
# use the address of a specific network interface to just listen to and accept
# connections from that interface
bind_to_address = 0.0.0.0
port = 1704

source = airplay:///shairport-sync?name=Airplay&devicename=Snapcast&port=5000
source = pipe:///tmp/snapfifo?name=default
source = meta:///Airplay/default?name=Meta

Updated: