Zack Hobson

Become an internet DJ using pulseaudio Tuesday May 26, 2020

This is a tutorial on how to use pulseaudio to stream the audio output of any program as an internet radio station.

I arrived at this solution because I have kind of a weird music set up: My collection of mostly Ogg Vorbis files are on a network-attached storage device in my apartment, exposed to the local network as a DAAP service. I can use rhythmbox to browse and play my music via this service.

When I became interested in internet radio, I learned that my setup wasn’t conducive to streaming. Most tools that make broadcasting easy are designed to work with local files, but I specifically wanted to keep using rhythmbox and DAAP to play my music, even when broadcasting. It turns out that if you’re already using pulseaudio, this is not that difficult to do! In fact, it comes with a significant upside: You can stream the sound from any program you want, and even include a microphone monitor!

Obviously there are a lot of ways to do this, but if you want to do things exactly as I did, this is what you’ll need:

  • the radio station: an internet-accessible host for running icecast2, I use a Linode VPS
  • the recording studio: a computer that uses pulseaudio for sound, I use Ubuntu on a Thinkpad X1 Carbon
  • an audio player of your choice, I use rhythmbox but anything will do
  • the command-line tool darkice for streaming pulseaudio to icecast
  • the GUI tool pavucontrol (Pulse Audio Volume Control) for managing the inputs and outputs

The radio station

The first thing you’ll need is an internet-accessible host for running your radio station. For this, I’m using a cheap Linode VPS with the name radio.butts.team pointed at it, on which I install icecast2 as root:

# as root on the icecast host
apt install icecast2

By default, icecast2 will start automatically and only needs to have the config updated to add the password we will use to authenticate when broadcasting:

# as root on the icecast host
vim /etc/icecast2/icecast.xml # edit authentication block to set passwords
service icecast2 restart

That’s it! Your internet radio station is now waiting for you to start streaming. It’s worth mentioning that at this point you can easily use a conventional player like Internet DJ Console to broadcast, and skip the rest of this tutorial.

If you want the flexibilty of using pulseaudio instead, what follows is a method for configuring your workstation to do just that.

The recording studio

NOTE The remainder of these examples are meant to be run on the machine you use to play music.

Step 1: broadcasting music

The trick to streaming via pulseaudio while still having normal use of your computer audio is to create a new sink specifically for your radio stream:

pactl load-module module-null-sink sink_name=Radio sink_properties="device.description='Radio'"

In pulse, sound comes from a source and outputs to a sink. This command creates a null sink named “Radio” that will be used to isolate the radio stream from other audio on the computer.

In order to stream that audio to your radio station for broadcasting, we’ll use darkice:

sudo apt install darkice
cp /etc/share/darkice.cfg.gz .
gunzip darkice.cfg.gz
vim darkice.cfg

In darkice.cfg update the input section to use pulse:

[input]
device = pulse
# ...

Also, update the icecast2 config:

[icecast2-0]
server = <radio station hostname>
password = <radio station password>
# ...

The remaining config blocks in the file (for streaming to other types of service) can be deleted.

With this done, you can start darkice to enable streaming to your radio station:

darkice -c darkice.cfg

Now that we have an audio sink and a streaming source we can use pavucontrol to configure them:

sudo apt install pavucontrol
pavucontrol

In the “Recording” tab of pavucontrol (make sure “All Streams” are showing) you’ll see a new device that streams all audio to your radio station. Set it to monitor the “Radio” sink that you created earlier.

Then, in the “Playback” tab of pavucontrol find the app that you want to stream from and set it to output to “Radio”.

That’s it! If everything worked, the audio from your seleted app is now streaming over the internet!

Step 2: the microphone monitor

At this point, we can use any app as an audio source for our internet radio station, but we don’t yet have a way to use our microphone! To enable it, we need a way to use the microphone as an audio source that can be pointed at the Radio sink. This is accomplished by adding a loopback interface:

pactl load-module module-loopback latency_msec=1 sink=Radio sink_dont_move=true

Now in the “Recording” tab of pavucontrol there is another entry for the loopback interface, which you can then point at your microphone. You’ll want to leave it muted except when you’re broadcasting your mic, or your microphone audio will always be broadcast on the stream, probably not what you intended!

Step 3: make it permanent

Once all this is done, you might not want to re-do all of this the next time you restart your computer, so be sure to add your pulseaudio config to the end of /etc/pulse/default.pa:

# at the end of /ect/pulse/default.pa
load-module module-null-sink sink_name=Radio sink_properties="device.description='Radio'"
load-module module-loopback latency_msec=1 sink=Radio sink_dont_move=true

This will ensure that pulseaudio is configured on system start, but you will still need to start darkice and use pavucontrol to resume streaming.

Listening to the radio

Visiting your radio station host and port with a web browser will show you a useful interface for accessing your stream. Here’s the icecast UI for my own radio station: radio.butts.team. I recommend using VLC, but any media player should be able to stream it.

Caveats

The default Ubuntu volume controls will mess up your stream if you touch them! If you don’t stick with pavucontrol exclusively when you’re streaming, a volume change will likely reset your music program to output to your speakers. This can probably be alleviated with the right pulseaudio settings but I haven’t figure this out yet.

It’s probably too easy to broadcast your mic accidentally, I might be able to alleviate this as well by setting it mute by defaut or something similar. I haven’t figured this out yet either.