Wednesday, January 2, 2013

AirPlay HTTP MP3 streaming server

I recently got myself a Raspberry Pi. Even though not knowing what I should use it for. It is just such a nice peace of cheap hardware that I had to have it. The plan was that a use for it will show itself eventually. And now it has...

A few years ago I got myself a Reciva based internet radio (Argon Inet) to have in the kitchen. It has internet radio, podcasts, http streaming, mp3 playing and even line in. But it does not have AirPlay.

Lately I have been using AirPlay together with my Enigma2 based Vu+ Duo satelite receiver. The satelite receiver is connected to the hifi amplifier and AirPlay has been a great way to get spotify music from my iPhone to the living room speakers. So ofcourse now I want to do the same to the kitchen radio.

This is where the Raspberry Pi comes in. By combining Shairport and VLC to set up an HTTP MP3 stream the radio can tune in on Pi's adress and play the audio received via AirPlay.

Installing Shairport

Shairport is an open source implementation of Apples AirPlay protocol. I think I have read somewhere that it is not compatible with iOS 6. But I still have iOS 5.1 on all my Apple devices so it is no problem.

Since I'm using the Pi headless I opted to use the Arch Linux distribution. I installed it on an uSD card and set up the environment according the installation instructions on their webpage. I then used this article to install the Shairport daemon. The article mentions workarounds with systemd and requiring manual installation of perl-net-sdp. I ended up also installing initscripts to write my own rc.d scripts:
systemctl enable avahi-daemon
echo snd-bcm2835 > /etc/modules-load.d/snd-bcm2835.conf
tar -zxvf perl-net-sdp.tar.gz
cd perl-net-sdp
makepkg -s --asroot
pacman -U perl-net-sdp-0.07-1-any.pkg.tar.xz
pacman -S initscripts
I think it is nice to be able to play both to line out and to an HTTP MP3 stream. So by adding the following line to the shairport script in /etc/rc.d, a Shairport daemon starts up at boot and will play to line out by selecting AirPi as output on the iPhone:
$daemon_name -d -a AirPi
Installing VLC and other tools

Using pacman I installed VLC:
pacman -S vlc
With this i ended up with VLC version 2.0.5.

Some other  tools are also needed:
pacman -S screen
pacman -S netcat (select freebsd version) 
The tool screen is used to start Shairport and VLC from init scripts and later be able to attach to the screen and read any output. The tool netcat (nc) is used to echo command to VLC remote control interface.

Connecting it all together

Shairport has a function to stream the received AirPlay audio as raw pcm stream to a names unix pipe. VLC can open this unix pipe and play it as long as there is data. But when the iPhone disconnects from the Shairport server the data stops. So Shairport needs to tell VLC to start playing again when the iPhone connects. By selecting a different server name and port than the line out Shairport daemon the two different way of playing can coexist. To accomplish this, Shairport is started with the following parameters: -a AirPi2 -o 5012 --pipe=/tmp/airpi --play_prog="echo play | nc localhost 7070"
To read the pcm stream, VLC needs to be told exactly what the format is. This is done with the following VLC parameters:
--demux=rawaud --rawaud-channels 2 --rawaud-samplerate 44100 /tmp/airpi
To be able to tell VLC to restart play when an AirPlay client connects it is started with the remote control interface i used:
-I rc --rc-host localhost:7070
To make vlc transcode the pcm stream to MP3 and the making it available on http the following parameters are used:
:sout='#gather:transcode{acodec=mpga,ab=128,channels=2,samplerate=44100}:http{mux=dummy,dst=:8080/sound.mp3}' :sout-keep
The final script which I placed in /usr/local/bin is:
screen -S sp -X quit
screen -S vlc -X quit
screen -d -m -S sp -a AirPi2 --pipe=/tmp/airpi -o 5012 --play_prog="echo play | nc localhost 7070"
screen -d -m -S vlc su - user -c "/usr/bin/vlc -v -I rc --rc-host localhost:7070 --demux=rawaud --rawaud-channels 2 --rawaud-samplerate 44100 /tmp/airpi :sout='#gather:transcode{acodec=mpga,ab=128,channels=2,samplerate=44100}:http{mux=dummy,dst=:8080/sound.mp3}' :sout-keep :repeat"
By making an rc.d script shairport2 which calls the above script, the server is automaticaly started at boot.

Please comment if there are errors or something is unclear.


  1. I want to ask an irrelevant question.
    I am searching for an enigma 2 rom based on openpli for Raspberry Pi.
    Would make a top class enigma 2 receiver with a DVB-S2 and DVB-T usb Tuners.
    Did you see anything close?

    1. No I have not. Sorry. I imagine it would be cool.

  2. Thank you very much for this tutorial, but the last step ist noch working for me: I can see AirPi2 and AirPi. AirPi is working: Audio to Line Out. AirPi2 is not working, nothing available in my browser, when I go to pi url: http://myPiIp:8080/sound.mp3.
    Any hints?!