Live radio streaming with MPD, part 2: multicast RTP

The previous article was introducing basic streaming principles based on Icecast. The issue with this, of course, is lag and overhead of HTTP-based connexions. In this article we introduce RTP-based streaming system, (unfortunately) based on Pulseaudio and multicast.

(Update: there was a rant here about Pulseaudio (PA) that I have moved out of this post because it's not what I was aiming to talk about. Those wanting to answer that troll are welcome to join the flamewar here.)

A word on multicast

I took the opportunity of trying out Multicast (it's actually IP multicast, to be more precise), since I wanted to have only minimal configuration to perform on the client side. Plus, since the RTP frames are raw 44khz 16 bit audio, the traffic is actually quite heavy, 1.4mbps, to be more precise (punch in 44kHz * 16bit/Hz * 2 in the excellent Qalculate to see why), so I didn't want bandwidth to explode as more listeners joined in. As a comparison, also note that the Icecast Vorbis stream is around 64 or 128kbps depending on quality.

Multicast allows packets to be sent only once for multiple listeners on the same network. It's actually quite cool, but doesn't work very well over the wider internet, for reasons that are still unclear to me. I presume that the fact there is virtual monopoly over traditional broadcasting systems (e.g. television and radio) means that multicast hasn't really kicked in yet... I hope this will make sense over the Montreal mesh, although the quality would probably need to be dialed down, or the audio streamed encoded instead of be sent as raw samples.

So why PA? VLC/pipe failures

That aside, it seems that to stream through RTP, I have no choice. I have tried to use VLC as a pipe to stream data out of MPD as RTP, but somehow this config snippet just failed:

audio_output {
   type            "pipe"
   name            "RTP"
   command         "cvlc -q - --sout '#rtp{dst=239.72.72.144,port=5004}'"
   encoder         "vorbis"                # optional, vorbis or lame
   format          "44100:16:2"
}

I don't know why - the multicast port wouldn't open properly and MPD would even hang when restarting. It seems the pipe plugin is somewhat broken. Note that the vlc command above actually works fine to stream audio content out through multicast, which is a good way to test if multicast works in the first place...

Shoving PA down MPD's throat

Instead, I had to go to the clunky PA-way (also know as "my way or the highway"). The first step was to configure the default.pa to enable RTP streaming. I copied over the default /etc/pulse/default.pa file into ~mpd/.pulse/default.pa and uncommented the following lines:

# just to get the PA announced
load-module module-zeroconf-publish
# we need a null sink, no clue why, but without this glue, it fails
load-module module-null-sink sink_name=rtp format=s16be channels=2 rate=44100 sink_properties="device.description='RTP Multicast Sink'"
# port is specified otherwise it is random (?!)
# loop=1 is to broadcast locally too
# other useful setting: destination (defaults to 224.0.0.56)
load-module module-rtp-send source=rtp.monitor port=5004 loop=1

See the rtp-send module documentation for more information here.

Then we need MPD to connect to that sink:

audio_output {
    type            "pulse"
    name            "Pulsaudio RTP"
    sink            "rtp"
}

Also, now that we got into the PA kitchen sink, we are kind of forced to use it for the local sound card output too, so we'll add this as a sink to:

audio_output {
    type            "pulse"
    name            "Pulseaudio sound card"
    sink            "alsa_output.pci-0000_00_1b.0.analog-stereo"
}

(Take a moment to admire the nice sink name. Yours may be different, have fun finding it in the output of pacmd list-sinks, but that works only once PA is started!)

So now you need to restart MPD for those changes to take effect. Note that if the mpd user has already started PA, you're in luck: it won't restart it by itself, and you need to:

service mpd stop
killall pulseaudio
service mpd start

... yep. Basically because pulseaudio just detaches completely from the parent process when spawned automatically. Lots of fun.

Testing and listening

Of course, you can listen to the stream using... Pulseaudio. I assume this would magically show up on the network thanks to avahi, if you run Pulseaudio on (say) your laptop. Since I still want to stay away from it, I would rather use a straight commandline tool to listen to the stream. According to this page, there aren't that many clients that could listen to such a funky stream. I chose VLC, since its commandline options actually make sense.

Here's the magic mantra to repeat every night before you go to bed:

cvlc rtp://@224.0.0.56:5004

Yes, that's all. Drop the c if you want a GUI.

With mplayer, it's more complicated - you need to specify a bitmask using a hexadecimal string (fun stuff):

mplayer -demuxer rawaudio -rawaudio format=0x20776172 rtp://224.0.0.56:5004

Yes, good old 0x20776172...

Results! We want results!

All this work reduced the lag from 15 seconds to around 1 second. It's still present, and confusing to listen to, but maybe more acceptable. It seems most of the lag is in the vlc client buffering, when I enable debugging, I see:

[0x963c7bc] main input debug: Stream buffering done (1001 ms in 976 ms)

I was able to reduce that delay significantly by using the --rtp-caching option of vlc, as such:

cvlc --rtp-caching=48  rtp://@224.0.0.56:5004

The value is in miliseconds. Anything below 48ms introduces audible artifacts (probably buffer underruns). With that setting, there's still a noticeable delay, especially with isolated sounds that are naturally more noticeable. With more harmonious music, it sounds more like an echo.

I have also tried to fiddle with similar settings with mplayer and simply failed to get any results. --no-cache simply drops samples like crazy. --cache 64 is the lowest I could push it down to, and it still has noticeable delay, which I couldn't measure, but I would assume would be around 400ms at least.

Also note that contrarily to the previous setup I had, based on Icecast, VLC will automatically resume streaming from the RTP stream as it is stopped or started, which is also very nice - as it allows me to disable remote RTP streams easily and harmlessly.

Troubled areas

Speaking of insane nonsense, here are a few pitfalls to avoid.

Take care to disable the ALSA output, if it's not yet commented out, because MPD will freak out with the following error message:

Feb 03 20:25 : output: "Sound card" [alsa] failed to play: Resource temporarily unavailable

I have not been able to find a way to make PA let go of the audio sound card. I would have prefered MPD to open ALSA directly if PA wasn't needed (I need it only for RTP streaming), but it seems that PA assumes you'll want to play stuff locally.

I have tried commenting out the following in default.pa:

load-module module-udev-detect

Seems like it's not enough. Also note that PA is designed with "dumb users" in mind (read: you need a GUI to operate it), so in the context of MPD, it's really annoying to debug things unless you can actually fire up a X11 session as the MPD user (which strikes me as a crazy idea) to configure PA properly with paprefs and all the graphical gizmos.

I just gave up and went with PA all the way, and just added the RTP sink through the commandlines. Other guides can show you screenshots to clikety your way through inane graphical interfaces to do the above, if you are into that kind of stuff.

With PA, you will want to get familiar with the pacmd and pactl commands. Why there are two different commands to basically do the same thing is completely beyond me.

Reference and more reading

I got a lot of information in the Pulseaudio MPD wiki page and the Pulseaudio user documentation. The VLC manual about RTP streaming (server) (client) was also useful for debugging.

The Pulseaudio Network documentation has a set of recipes for using pulseaudio for everything. This Ask Ubuntu question explains how to clikety your way through paprefs to essentially do the above.

Commentaires

Portrait de anarcat

#1 anarcat : liquidsoap jumps in the fray

Note that I have improved my radio setup with the help of Liquidsoap. See my radio configuration wiki page for more information.


Portrait de R.

#2 R. : Can't make it work.

Mpd doesn't seems to use pulse output

If I run pacmd list-sinks
I got "No PulseAudio daemon running, or not running as session daemon." as an answer

In ps i got pulseaudio on mdp user

mpd 3001 1 0 80 0 - 22553 poll_s 18:01 ? 00:00:00 /usr/bin/pulseaudio --start --log-target=syslog

Any idea?

Regards,

Regis


Portrait de R.

#3 R. : Got some errors in

Got some errors in logs

first

Feb 13 18:21:51 raspberrypi pulseaudio[3204]: [pulseaudio] server-lookup.c: Unable to contact D-Bus: org.freedesktop.DBus.Error.NotSupported: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11

Got an answer from
http://ubuntuforums.org/showthread.php?t=1878868&page=2
Make the script and run the four commands.

The line had disappeared from the log.
The other lines are :

Feb 13 18:32:53 raspberrypi pulseaudio[3298]: [alsa-sink] alsa-sink.c: ALSA woke us up to write new data to the device, but there was actually nothing to write!
Feb 13 18:32:53 raspberrypi pulseaudio[3298]: [alsa-sink] alsa-sink.c: Most likely this is a bug in the ALSA driver 'snd_bcm2835'. Please report this issue to the ALSA developers.
Feb 13 18:32:53 raspberrypi pulseaudio[3298]: [alsa-sink] alsa-sink.c: We were woken up with POLLOUT set -- however a subsequent snd_pcm_avail() returned 0 or another value < min_avail.

Regards,


Portrait de R.

#4 R. : Got problem with "zero

Got problem with "zero config" i put back the line in commentary and got it working.
Got a delay 1 sec between the sound played on mpd server and the vlc on an other computer.


Portrait de anarcat

#5 anarcat : Have you tried changing the

Have you tried changing the --rtp-caching option?


Portrait de R.

#6 R. : Hi, Thanks for your answer.

Hi,

Thanks for your answer. On the PC I played with the network caching (round 280ms), on the Mac i finaly found where the option where hidden.
But the delay seems to vary...

Is a RPi could be master and slave for mpd ntp stream?

Regards,


Portrait de anarcat

#7 anarcat : uh?

> Is a RPi could be master and slave for mpd ntp stream?

I don't understand your question.


Portrait de R.

#8 R. : The Mpd computer is set to

The Mpd computer is set to stream to other computer.
What i was thinking is enabling mpd to an other mpd machine and localy play this stream.
Each mpd can act as a server or a listener, don't know if it's possible?


Portrait de anarcat

#9 anarcat : Sorry, I don't know if MPD

Sorry, I don't know if MPD can be an RTP client. I don't think so, according to the documentation...

(which you should have read before asking :P)


Portrait de anarcat

#10 anarcat : I moved the Pulseaudio troll to a separate post

So as I mentionned in an edit in the post, there used to be a rant/troll about Pulseaudio in the body of the text, but since that seemed to be generating more responses than the actual subject of the post, I thought it was better to move the discussion to a separate post. Comments were moved along and were of course not edited in any shape or form.


Portrait de ecc

#11 ecc : does "path" (fifo) work any better than "pipe"?

I haven't tried this, but my mpd.conf manpage says it will output to a fifo with the "path" audio_output option. Maybe that will work better than a pipe and allow you to avoid PA.


Portrait de Martijn

#12 Martijn : Nice article. My home setup

Nice article. My home setup is similar to yours, but one things that seems to be a problem, is that my WiFi access point keeps choking on the multicast traffic.

I'm not sure if this is a problem with WiFi access points in general, or just with my rather old Linksys WAP54G.

So until I have a way of keeping the multicast away from my AP (I currently thinking of using a Raspberry Pi as a bridge, filtering the multicast to the wireless network), I use plain old TCP in PulseAudio, which is okay if you only have one or two listeners.


Portrait de anarcat

#13 anarcat : It depends on your network

It depends on your network setup, but some multicast addresses are specifically designed to avoid going out of the LAN. This is what the default PA multicast address does, so if you're PA multicast sender is on a wired LAN, the wifi network should not be seeing multicast traffic unless the interfaces are bridged or some other weird thing.

Or are you saying that the mere presence of multicast on the wired interface of the router breaks it?