Today I found a solution to integrate spotify in my multi-room audio setup, as it took some time to get it working I want to share it here. But let me present the whole system. It is modular and can be realized with any hardware and only free software (except the spotify client).
Here is the outline:
- 4 zones (kitchen, bath, terace, living) have a stereo speaker output
- the audio output is generated on a 7.1 soundcard in the server, where the 8 channels are mapped to 4 stereo groups
- the analog audio goes to individual amplifiers (matching rooms & speakers)
- the server runs openHAB, mpd, a spotify client and many other software on linux
- each family member has its own instance of mpd on the server (but also access to the others)
- each mpd has the 4 output zones and a stream output configured
- the mpd’s are controlled by clients on the families mobile phones, the openHAB mpd binding (rules use KNXs switch signal for control, a HABpanel shows most of the controls)
- any spotify client in the home network can use the spotify client on server as a output device.
- the spotify audio stream is looped back from the HDMI soundcard to a local stream on server, that is than played back by any of the mpd’s in any or multiple zones
The main advantages for me of this setup are:
- audio in all zones is in perfect sync
- centralized hardware, no RasPi or something like that hidden in corners of rooms
- modular hardware, I can choose the DSP by bying the soundcard I want, I can choose the amp and the speakers
- no closed (expensive) hardware, eg. Sonos, Russound etc. (which support do you get in some years? How do play different hardwares together?)
- no additional traffic for audio in local network (audio goes via speaker cable), thus no connection loss/problems
- central managed software (mpd, openhab, one mp3 storage)
- can run without spotify premium
- will work similar with any kind of streaming software
- allows any aditional audio (e.g. door bell) to mixed to the active outputs, too
Here is a scheme of my actual audio setup:
The re-mapping of the 8 channels is done in alsa ( /etc/asound.conf
):
# the mixer provides the mixing of the 8 channels
pcm.dmixer {
type dmix
ipc_key 1099
ipc_perm 0660
slave {
pcm "hw:1,0"
rate 96000
channels 8
periods 128
period_time 0
period_size 1024
buffer_size 4096
}
bindings {
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
}
}
# here is the HDMI soundcard, which is used as default output from spotify
pcm.!default {
type plug
slave.pcm "mystream"
}
pcm.mystream {
type plug
slave {
pcm "hw:0,0"
rate 48000
channels 2
}
}
# here I map the channels of the 7.1 sound card to 4 x 2.0 stereo channels
pcm.wohnzimmer {
type plug
slave {
pcm "dmixer"
channels 8
}
ttable.0.0 1
ttable.1.1 1
}
pcm.bad {
type plug
slave {
pcm "dmixer"
channels 8
}
ttable.0.2 1
ttable.1.3 1
}
# ... repeat with similar logic for the other two zones (channels: 0.4, 1.5, 0.6, 1.7) !
Four copies of mpd are running in parallel (actually it could be any number ). Rename the instances to mpd1
, mpd2
, … each with its own config (mpd1.conf
, …). My files look like this:
music_directory "/myfolder/Musik"
playlist_directory "/myfolder/software/mpd/playlists"
db_file "/myfolder/software/mpd/mpd.db"
log_file "/myfolder/software/mpd/mpd1.log" #and mpd2.log, mpd3 ...
pid_file "/myfolder/software/mpd/mpd1.pid" #and mpd2.pid, mpd3 ...
state_file "/myfolder/software/mpd/mpd1.state" #and mpd2.state, mpd3 ...
sticker_file "/myfolder/software/mpd/sticker.sql"
user "mpd"
port "6601" #and 6602, 6603, 6604
gapless_mp3_playback "yes"
auto_update "yes"
zeroconf_enabled "yes"
zeroconf_name "User 1" #and 2, 3, 4
input {
plugin "curl"
}
audio_output {
type "alsa"
name "mpd1-Kitchen" #and mpd2-kicthen, mpd3- ...
device "kitchen"
mixer_type "software"
mixer_control "PCM"
}
audio_output {
type "alsa"
name "mpd1-Living" #and mpd2-Living, mpd3- ...
device "Living"
mixer_type "software"
mixer_control "PCM" # optional
}
audio_output {
type "alsa"
name "mpd1-Bath" #and mpd2-Bath, mpd3- ...
device "bath"
mixer_type "software"
mixer_control "PCM" # optional
}
audio_output {
type "alsa"
name "mpd1-Terrace" #and mpd2-Terrace, mpd3- ...
device "terrace"
mixer_type "software"
mixer_control "PCM" # optional
}
audio_output {
type "httpd"
name "mpd1-Stream" #and mpd2-Stream, mpd3- ...
encoder "vorbis"
port "8001" #and 8002, 8003, 8004
bitrate "128" # do not define if quality is defined
format "44100:16:1"
always_on "yes" # prevent MPD from disconnecting all listeners when playback is stopped.
tags "yes" # httpd supports sending tags to listening streams.
}
filesystem_charset "UTF-8"
id3v1_encoding "UTF-8"
The mobile phones run MPD control as clients. We like the easy access to the outputs. Most other mpd apps hide this well, and thus switching of zones becomes unpractical.
The server runs the normal spotify linux client and its output will go to the default audio sink (here alsa’s pcm.!default
), which is mapped to my second sound hardware - the HDMI card. Normally the speaker is muted by the monitor hardware, thus the music can not be heard in the server cabinet . The audio from this soundcard is looped back into an mp3-stream that the mpd’s can use as a input. I found this solution in the internet:
The command:
pacmd list-sources | grep name
shows device name to use, for me alsa_output.pci-0000_00_03.0.hdmi-stereo.monitor
A streaming software like VLC can form this into a stream file, e.g.:
cvlc -vvv pulse://alsa_output.pci-0000_00_03.0.hdmi-stereo.monitor --sout '#transcode{acodec=mpga,ab=128,channels=2}:standard{access=http,dst=localhost:8005/spotify.mp3}'
Other VLC transcode options should also work. My mpd plays back the stream from http://localhost:8005/spotify.mp3
. I experience a delay of roughly 1-2 seconds between an action at the spotify app and the audible speaker output. This is OK for me, because all four zone outputs are in perfect sync and will be like this, ever!