Local network broadcast with PulseAudio

PulseAudio has been the standard sound system in Ubuntu for several versions now, and seems to be replacing, or rather supplementing, ALSA and OSS. Its main benefits (for me) are: per application sound levels, and streaming to a remote PulseAudio instance over network.

At home, I have a HTPC running Xubuntu with XBMC hooked up to my stereo. Because I usually control XBMC using my Android phone, I have no mouse or keyboard attached. When I want to listen to music, I fire up Spotify and stream the audio to my HTPC. Why? Because the speakers in my laptop suck.

Ubuntu

Setting up Ubuntu to accept PulseAudio network connections should be easy under Ubuntu. Just:

root# apt-get install paprefs

and you should be ready to go. Alas, there is a bug in most recent Ubuntu versions, which prevents paprefs from configuring the network settings of PulseAudio. paprefs is looking in the wrong directory for PulseAudio, and therefor fails to detect the network part. To fix this, create a symlink as root:

root# cd /usr/lib
root# ln -s pulse-1.0 pulse-1.0.0

The Network Access and Network Server tabs should now be available. The first allows you to detect and use remote PulseAudio devices locally. If you enable this option, but don’t seem to get any new devices in your sound options, you should probably install Avahi and enable it. Also don’t forget to add firewall rules to allow UDP port 5353 and 51952.

The latter allows you to expose your PulseAudio devices on the network. You should probably select the top three options. If other network devices can’t find your PulseAudio server, don’t forget to install Avahi and open the ports I mentioned earlier. If it still can’t find it, run sudo restart avahi-daemon and check again.

Multiple sound outputs

One other cool feature of PulseAudio, is that you can bundle multiple outputs (sinks) into one, and send sound to them all at once. In my situation, this allows me to send audio to my local speakers, and the remote speakers on my HTPC. Useful for broadcasting music through your house. To do this, I assume you can already output sound to a remote PulseAudio sink. First you need the address of your local speakers and the remote ones:

user$ pacmd list-sinks

Welcome to PulseAudio! Use "help" for usage information.
>>> 2 sink(s) available.
    index: 0
    name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
    driver: <module-alsa-card.c>
    flags: HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
    state: RUNNING
...
    index: 1
    name: <tunnel.razengan.local.alsa_output.pci-0000_00_01.1.hdmi-stereo>
    driver: <module-tunnel.c>
    flags: NETWORK HW_MUTE_CTRL HW_VOLUME_CTRL LATENCY 
    state: RUNNING
...
>>> 

Look after the name entry, on my machine the relevant devices are: _alsa_output.pci-0000_00_1b.0.analog-stereo_ (local speakers) and _tunnel.razengan.local.alsa_output.pci-0000_00_01.1.hdmi-stereo_ (remote speakers). We can combine these two using the combine module of PulseAudio. Note that you are not limited to just two devices, but I will only use two.

user$ pacmd load-module module-combine sink_name=combined-net slaves="tunnel.razengan.local.alsa_output.pci-0000_00_01.1.hdmi-stereo,alsa_output.pci-0000_00_1b.0.analog-stereo"
user$ set-default-sink combined-net

The first command creates a new PulseAudio device that sets the two sinks we selected as slaves. The second command actually sets this sink as default. For every program we start from now on, this will be the default sound output. You can also skip the second command, and decide per application which sound output it should use. To do this, install pavucontrol.

root# apt-get install pavucontrol

On the first tab you can find a dropdown per application, to set which sound output it uses.

Persist between reboots

I have not yet found a way to make the addition of this PulseAudio sink permanent, it seems you have to run the commands on every boot. I tried creating a custom default.pa file in ~/.pulse, but this file seems to get loaded before networking has started and Avahi has detected the remote sink. Instead, I created a simple script which I start whenever I want to use the setup.

#!/bin/bash

echo "Restarting Avahi..."
sudo restart avahi-daemon

echo "Waiting 10 sec to discover remote PulseAudio sinks..."
sleep 10s

echo "Create combined-net sink"
pacmd load-module module-combine sink_name=combined-net slaves="tunnel.razengan.local.alsa_output.pci-0000_00_01.1.hdmi-stereo,alsa_output.pci-0000_00_1b.0.analog-stereo" 2>&1 1>/dev/null

echo "Set sink as default"
pacmd set-default-sink combined-net 2>&1 1>/dev/null

Uncomment the last line if you want to set the new sink as default. If someone knows how to achieve the above automatically on every boot, drop me a comment below.

  • Can’t you simply add the pacmd directives in /etc/pulse/default.pa? I’m pretty sure you can. Nice article btw.

    • Lord_Gaav

      I actually tried that, but that either didn’t work or kept PulseAudio from starting. I added a simple script to the article which at least enables me to use this setup when I want to.

  • Brian Fahrlander

    I know it would make for CRAZY security problems, but something I’ve always wanted since first seeing the networking of PulseAudio has been something sometimes called “ShipWide”: the ability to speak/play and have it hear at all locations in the house or aboard the trailer.

    You’re write-up gets me most of the way there! I appreciate trailblazers that ‘mark their paths’. 🙂

    • Lord_Gaav

      As long as every speaker you have is connected to a Unix box with PulseAudio, and you enable sharing on that box, you can probably do exactly as you want. I have noticed however that there may be a small delay between the speakers, but you might be able to fix this by tweaking the buffer sizes.