Network audio with PulseAudio made (somewhat) easy

I figured it was long past time to buckle down and learn how to make PulseAudio do my bidding and redirect audio across a network link. And I was surprised to learn that it's actually not hard to set up. In fact you don't need to touch any config files in /etc. Which you would never know, from reading most of the documentation that is out there.

While network audio is still kind of flaky at times, you only "pay" for it if you use it (people complain about PulseAudio a lot, but in my experience it works very reliably when used locally), and it can come in very handy.

Background

Throughout, I'll refer to the two computer roles as audio source and audio sink (where audio data is generated/decoded and where the speakers are attached, respectively). Note that these may differ from the PulseAudio concepts of the same names.

Ubuntu ships with PulseAudio, and many apps (among the common graphical apps and music players) understand how to talk to PulseAudio now (possibly through a compatibility layer). Except maybe Flash, but everyone who uses Flash is already used to it not being a proper citizen. The default setup is to have a per-user instance of PulseAudio running alongside the X session. This means that someone has to be logged in to X on both ends. If your audio sink is headless then you might have a single system-wide PulseAudio instance instead. Configuring that is not covered here.

PulseAudio runs as a service on port 4713. We need to first make that service discoverable on the machine with the audio sink, and then provide a way for the machine with the audio source to authenticate to the sink (so that you're not just letting anyone on your network play their crappy music).

Initial steps

On the machine with the audio sink:

  • Install and run paprefs &
  • Go to the Network server tab.
  • Check Enable network access to local sound devices and Allow other machines on LAN to discover local sound devices. Autodiscovery uses Avahi, which you'll need to re-enable, if you ever disabled it.

(You might have to restart PulseAudio or X for the settings to take effect.)

I will describe two ways you can get the machine with the audio source to supply credentials to the sink so it can play music. The first one is likely to be more generally useful.

Using .pulse-cookie

The ~/.pulse-cookie file is a shared secret that can be used for authentication. Just copy that file from either machine (sink or source) to the other so that they are the same on both ends.

At the audio source, install padevchooser and run it (padevchooser &). A menu will appear in your notification area. Under Default server you should see an entry for the sink, assuming it is on the same local network (it should be named username@hostname). Select it.

Now run the application of your choice and play some audio!

Piggybacking on X11 forwarding

This method has the advantage of not requiring working autodiscovery. So you can use it on a LAN without Avahi running, or over a non-local network. All you need is to be able to SSH from the sink to the source. We will forward the audio from the source to the sink on a TCP port.

For this method, we'll transfer the credentials that the source will need by writing them to the X11 root window. PulseAudio supplies a program that does exactly this. On the machine with the audio sink, run:

sink$ start-pulseaudio-x11

(You can double-check that this is working by running xprop -root | grep PULSE and checking that there is an entry for PULSE_COOKIE, among others.)

Now initiate an SSH connection to the source, tunneling a port of your choice on that end over to your local PulseAudio server:

sink$ ssh -X -R 9998:localhost:4713 source

Run the application of your choice and play some audio! As you are doing so, set the PULSE_SERVER variable, which now enables your remote application to talk to your local audio hardware via the tunneled port.

source$ PULSE_SERVER=localhost:9998 rhythmbox &

Conclusion and caveats

Et voila, now you've decoupled your music player from your speakers. So you can play music from your laptop using the speakers at your desktop. Or you can play music from your desktop using the speakers in your living room. Some things to watch out for.

  • You may need to kill and restart pulseaudio (or X) to get it to pick up some of those configuration changes.
  • PulseAudio will not move a stream while it is running, so if you use the menu to change the destination, the change will not take effect until the next song begins, unless you pause and restart playback in your audio application.
  • PulseAudio is kind of finicky and some of it still feels like black magic at times. You may need to restart it if you suddenly get errors about things not working, especially if they were just working a minute ago.

Sources and further reading: pulseaudio-discuss, ArchLinux wiki, Ubuntu forums

3 comments:

  1. ...interesting...

    I have achieving similar results with pipes http://www.debian-administration.org/articles/145 but that is messy.

    By the way paprefs options were greyed out because of missing libraries. Resolved with

    sudo ln -s /usr/lib/pulse-1.0 /usr/lib/pulse-1.0.0

    *note extra zero

    ReplyDelete
  2. Back in the early times of pulseaudio it was possible to configure a network (remote) audio sink and dynamically switch between one sink and the other an audio stream that was being played.

    Meaning I could send the audio from Rhythmbox from my computer A to computer B and audio from Skype to computer C.

    I could do the same with sources by redirecting mic input.

    I then had no more time experimenting with pulseaudio and now I don't see how to do those things again.

    Or is it the "copy cookie" option?

    SSH tunnelling is good.. but it is not that flexible...

    Anyway I prefer to do this:

    Computer A: my source (where I want to run the rhythmbox and I keep my music library)
    Computer B: the one with headset I use working

    I prefer to run the application (rythmbox) on computer A and hear it on computer B, here's what I do:

    From computerA:
    ssh myComputerBUser@computerBIP -L 9998:localhost:4713 -fN

    Tunnel is now open and if I access port 9998 from computerA it is automatically redirected on port 4713 (pulseaudio server) on computer B

    So executing (from computerA)
    PULSE_SERVER=localhost:9998 rhythmbox

    will send the audio directly to computer B

    ReplyDelete
  3. Please write in a manner which would be understood by common people...

    I am getting X11 forwarding ... vlc player is displayed and plays music on the remote computer on which i store music (the same machine on which music is stored). I receive "Connection refused by pulse audio messages in the machine in which I am running the X11 forwarding session...

    ReplyDelete