Network Audio with PulseAudio
I have wanted to get remote sound sinks working ever since it saw it in action during a local Linux user group meeting. It was a bit beautiful in its simplicity – once you connected to the Wi-Fi the remote sink for the wireless speakers would magically appear, you select it as your sound output and you’re done. No cords, no passwords, no awkward pairing, and no noticeable delay.
With the help of a Raspberry Pi and a few spare moments during the holidays I was able to get everything up and running.
Overview⌗
There are really two services that come together to make the process seamless.
The first is Avahi, an mDNS/DNS-SD system which publishes the remote sound sink
with a service record. The second is PulseAudio which runs a daemon listening
on port 4713
.
The PulseAudio client, configured with the ZeroConf module uses mDNS to search
for service records for the sound server. You can search for these records
manually on your network with the avahi-browse
command.
avahi-browse -r _pulse-server._tcp
Once the client finds a remote sound server it will connect to the port specified in the service record, discover remote sinks and present them in the UI.
Server Setup⌗
I already had a Raspberry Pi running the latest Raspbian so I will omit those directions for brevity.
First you’ll want to install and start Avahi.
# This is technically all you need.
apt install avahi-daemon
# For debugging you might also want the browsing tools.
apt install avahi-utils
# Raspbian automatically enables services when they're installed so this
# shouldn't be neccessary but just in case.
systemctl enable --now avahi-daemon
Then you’ll need to install PulseAudio and the required modules.
apt install pulseaudio pulseaudio-module-zeroconf
The PulseAudio package doesn’t include a service file for running it in system mode so we’ll have to provide one. Nothing particularly fancy is needed. We disallow runtime module loading on the recommendation of the developers for security purposes.
# /etc/systemd/system/pulseaudio.service
[Unit]
Description=PulseAudio System Daemon
[Service]
Type=simple
ExecStart=/usr/bin/pulseaudio --system --disallow-module-loading
[Install]
WantedBy=multi-user.target
The main configuration for PulseAudio when run as a system daemon is
/etc/pulse/system.pa
. The syntax for this file is odd for a freedesktop project
but largely straightforward. Add the following lines to the end. You should
change 192.168.0.0/16
to your local subnet.
# Make sinks available over the network.
load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;192.168.0.0/16
# Publish sound sinks using Avahi.
load-module module-zeroconf-publish
Finally add port 4713
to the firewall and start the PulseAudio daemon.
firewall-cmd --permanent --add-port 4713/tcp
firewall-cmd --reload
systemctl enable --now pulseaudio
Client Setup⌗
The name of the packages you’ll need to install will largely depend on how your
distribution organizes things but other than PulseAudio itself I needed to
install pulseaudio-zeroconf
.
The main configuration file for daemons not running in system mode is
/etc/pulse/default.pa
. Add the following lines to the end and restart the
daemon (logging out and back in will do the trick).
load-module module-zeroconf-discover
Then without any other prompting the sound sink should appear in your sound settings. Select it as the output and start listening to your music.