A config generator for a multizone audio system based on snapcast, Mopidy and MQTT.
- support for common audio streaming protocols
- SpotifyConnect
- track transitions (crossfade and automix)
- player controls
- Airplay
- Mopidy/MPD
- Kodi
- Bluetooth
- SpotifyConnect
- seamless switching between protocols in each zone
- high-priority announcement streams (alarms, doorbells)
- invisible, automatic party reconfiguration
- no clashing audio streams
- no snapcast controls visible to end-users(!)
- eliminate unnecessary software volume controls
- replaygain support
Almost all media services run on a central media server.
Each media player is its own zone and there are also multiple (logical) "party zones" which group the real zones together. For more on logical zones see the snapcast-autoconfig README
The media server runs:
- one mopidy instance per zone (providing mpd + iris)
- snapserver
- mosquitto mqtt broker
Snapserver is configured with:
- per-zone mopidy, shairport-sync and librespot streams
- per-zone master meta streams
The snapserver itself runs and manages the librespot
and shairport-sync
media services.
snapcast-autoconfig manages the snapcast groups (including, for the benefit of Iris, naming them!).
- USB audio capture device with S/PDIF input - Startech ICUSBAUDIO7D ~£28 at Amazon UK
See BUILDING for notes on building some of these from sources.
- Debian 10+ "Buster"
- snapserver v0.27+
- librespot-java
- java
- librespot-api-1.6.3.jar
- default install dir is assumed to be
/opt/librespot
- shairport-sync
- 3.3.8-OpenSSL-Avahi-ALSA-stdout-pipe-soxr-metadata-mqtt-sysconfdir:/etc
- build with mqtt
- Mopidy
- Mopidy 3.2.0
- Mopidy-Iris 3.59.1
- Mopidy-Local 3.2.1
- Mopidy-MPD 3.2.0
- Mopidy-MQTT-NG 1.0.0
- Mopidy-Spotify 4.1.1
- Mopidy-TuneIn 1.1.0
- mosquitto MQTT broker
- snapcast-autoconfig
Each media player runs:
- snapclient
- nginx, proxying
http://<hostname>/
tohttp://<media-server>:66xx/iris
- kodi, if-and-only-if the player has a screen or projector attached
While snapcast meta streams are neat for auto-switching between audio services it's still confusing when, say, both a spotify and airplay stream attempt to play to the same zone. Instead, when one service starts playing we want the others (in the same zone) to pause.
To accomplish this each media service (mopidy, librespot, ...) is configured to notify via MQTT when playback starts.
See:
- mopidy-mqtt-ng
- shairport-sync MQTT support
librespot --onevent librespot-event.sh...
- kodi2mqtt
Each media service (except librespot) can also be controlled via MQTT.
The idea for this came from hifiberry which implements control of concurrent playback streams via MPRIS.
- RPi1 / RPi2 / RPi3
- Generic USB stereo sound card - UGREEN USB external sound card
- snapclient v0.25+
- nginx
- dietpi
- OSMC / Kodi v19+
- kodi2mqtt
- install by manually extracting the zip in
~/.kodi/addons/
on the client - Kodi v20 "Nexus" requires kodi2mqtt v0.22
- Kodi v19 "Matrix" requires kodi2mqtt v0.21 (or use the python2.7 patch by tspspi)
- install by manually extracting the zip in
The pausing of media streams is done by a simple MQTT service - though it could be implemented as:
- an extension to hifiberry's audiocontrol2,
- a HomeAssistant automation.
For end-users only (per-service) soft-volume control is available.
Hardware volume levels are preset by snapcast-autoconfig.
Each snapclient is configured to use an alsa hardware mixer (if available).
While librespot
and shairport-sync
can both be configured to control a
hardware mixer the snapserver can't be, nor does it create a virtual mixer.
These requirements are sufficient to customize the configurations for your setup:
- GNU make
- python3
- chevron
chevron
is a python implementation of the mustache templating language.
On first run if chevron
isn't found, make
will create a python virtual environment and install it for you.
The services are configured by generating systemd service files. Many of them are
template unit files
so that multiple instances can be started on a single host. (e.g. systemctl start mopidy@study
)
Configurations for each zone (and for all zones) are generated by merging the
config.json
data into the template files using chevron
.
You will need to adapt my existing json config for your purposes.
See also ALL_HOSTS
in the Makefile
.
../snapserver.conf |
---|
make
All the services (except for nginx
) can be run and tested locally as an unprivileged user.
To install and run mopidy in a python venv you will need:
sudo apt-get install libspotify-dev
.venv/bin/pip install -r requirements.txt
Generate configs and start all services:
make dev
make dev-install # this will overwrite files in ~/.config/systemd/user!
# set `SYSTEMCTL_USER := --user` in the Makefile
make start
To start the services for just one zone:
# study only
make HOST=study start-host
Requirements: see #software.
/etc/snapserver.conf |
---|
On your production system, as root:
git clone https://github.com/markferry/multizone-audio.git /etc/multizone-audio
cd /etc/multizone-audio
git checkout $your_branch # your customizations
make live-install
For all client hosts:
git clone https://github.com/markferry/multizone-audio.git /etc/multizone-audio
cd /etc/multizone-audio
git checkout $your_branch # your customizations
Then run the client-specific-install make $os-$host-install
Where $os
is one of: debian
, dietpi
.
And $host
is a host defined in config.json
.
e.g.:
make dietpi-library-install
- @badaix - snapcast maintainer
- @kingosticks - pimusicbox developer
- @frafall - snapcast metadata contributor and kodi snapcast service developer
- @ahayworth - snapcast-autoconfig maintainer
- skalavala multi-room audio - multi-zone but single-stream
- spocon - librespot-java packaged for Debian