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
- automatically accept new connections
- 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 12+ "Bookworm"
- snapserver v0.31+
- librespot-java
- java
- librespot-api-1.6.5.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 9+ (Debian 12 "Bookworm") or DietPi Bookworm test images)
- 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
- gettext (for
envsubst) - 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)
Configuration files for each zone (and for all services) are generated by first
expanding variables in the master config.json and then substituting the data
into template files using chevron.
Adapt example.config.json for your purposes.
make [config_in=config.json] [output_dir=build] [install_dir=/etc/multizone-config]Where the optional variables to make are:
config_in: the master config fileoutput_dir: the temporary output dir for generated filesinstall_dir: the eventual installation directory
Occurrences of literal $output_dir and $install_dir as well as any
variables specified in a .env file will be substituted in to the config.json
when generating the intermediate $output_dir/config.out.json.
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.txtGenerate configs and start all services:
make dev install_dir=$(pwd)/test # requires an absolute path
make dev-install install_dir=$(pwd)/test # this will overwrite files in ~/.config/systemd/user!
make startTo start the services for just one zone:
# study only
make HOST=study start-hostRequirements: see #software.
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-installFor all client hosts:
git clone https://github.com/markferry/multizone-audio.git /etc/multizone-audio
cd /etc/multizone-audio
git checkout $your_branch # your customizationsThen 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