Shairport on Synology NAS

Shairport simulates an Airport Express. A Synology NAS box can output through use of a USB audio adapter (I am using a TerraTec AureonDualUSB stick). Since a NAS tends to be running 24/7 anyway, using it as an AirPlay bridge is an obvious choice.

Fair warning though: This is indeed not for the faint-hearted. It turned out to require quite a bit more fiddling and I had expected it to be.

First, you need to get Perl 5.10 running on the NAS. I’ve put up a separate entry on how I did this. Alternatively, you can try to fix the C version for shairport, or try to get my attempted 5.8 port to work).

shairport may require a number of libraries via optware – for example libao. I don’t remember what exactly I had to install.

The next problem is avahi. Synology includes avahi-daemon and uses it internally, but it doesn’t include the avahi-publish client, which shairport uses to announce itself. Further, the included avahi-daemon is compiled without dbus support, so we can’t send commands to it anyway. There are two options at this junction:

  • Statically define a service for shairport in /usr/syno/avahi/services/
  • Replace the builtin avahi-daemon with the optware package.

Both of those are imperfect solutions and both will probably need to be re-applied after a DSM upgrade. The first will not involve any editing of system scripts, but would then announce shairport even if it isn’t running, so I went with the second solution.

First, let’s install avahi and dbus. If we create the groups and users that are required up-front, we will have less problems later:

$ addgroup netdev
$ adduser avahi (errors can be ignored)
$ ipkg install avahi
$ ipkg install dbus

Possible error messages by adduser about lack of a home directory may be ignored. To test, shutdown the builtin avahi-daemon (/usr/syno/etc/rc.d/S99avahi.sh stop), and start the optware one: /opt/sbin/avahi-daemon . “avahi-browse -a” should show sensible information now. If it doesn’t, make sure dbus is running. Possibly, you need to delete the pid file (rm /opt/var/run/dbus/pid), then try starting it again (/opt/etc/init.d/S20dbus start).

To replace the builtin avahi-daemon, what I did was edit the file /usr/syno/etc/rc.d/S99avahi.sh to make the DAEMON variable point to /opt/sbin/avahi-daemon, and then I symlinked /opt/etc/init.d/S20dbus into /usr/syno/etc/rc.d/, so that dbus will start before avahi.

Another problem: shairport, at the time of this writing, uses 5000 as a default port, which will already be in use on your Synology NAS. You need to edit shairport.pl and choose a different port.

At this point, you should be able to run shairport, and see it appear as an AirPlay target in iTunes. (As an aside, the command line I have to use is: $ LD_LIBRARY_PATH=/opt/lib /usr/local/bin/perl /path/to/shairport.pl
the full path to perl ensures that the right version is used, and /opt/lib contains required libraries and is not searched by the default).

Actually playing any audio probably doesn’t work yet. shairport is going to complain “could not open ao device”. On my device, I can play audio via /dev/dsp4. I identified that device by using “lsof | grep mplayer | grep dev” (lsof shows open files and can be installed via optware). You can also use the preinstalled /usr/syno/bin/mplayer to test your audio out from the console. Using “mplayer -v” will make mplayer show the device is is using.

We can tell shairport this by calling it like so:

$ LD_LIBRARY_PATH=/opt/lib /usr/local/bin/perl /path/to/shairport.pl --ao_driver=oss --ao_devicename=/dev/dsp4

It shairport still complains about not being able to open the device, the problem might be that have an older version of libao. You then need to edit shairport’s hairtunes.c and modify one of the calls to ao_append_option() so that the –ao_devicename option is applied using the key “dsp”, rather than “dev”.

To start shairport at boot, I’m using the following the following script, saved as /opt/etc/init.de/S90shairport:

#!/bin/sh
APNAME="Sonos: Bei Michael"
PIDFILE=/opt/var/run/shairport.pid
SHAIRPORT="/usr/local/bin/perl /opt/local/shairport/shairport.pl"

shairport_start() {
        if [ "$(ps | grep shairport.pl |grep -v grep)" > /dev/null ]; then
                echo "shairport already running, use restart instead"
        else
           echo "Starting shairport..."
           export PATH=/opt/bin:$PATH   # for shairport to find the avahi-publish-service executable
           echo LD_LIBRARY_PATH=/opt/lib $SHAIRPORT --ao_driver=oss --ao_devicename=/dev/dsp4 --apname="$APNAME" -d --writepid="$PIDFILE" | at now + 1 minutes
        fi
}

shairport_stop() {
        echo "Stopping shairport..."
        kill `cat $PIDFILE`
        rm $PIDFILE

}

shairport_restart() {
        shairport_stop
        sleep 1
        shairport_start
        }

case "$1" in
'start')
        shairport_start
        ;;
'stop')
        shairport_stop
        ;;
'restart')
        shairport_restart
        ;;
*)
        echo "Usage: start, stop, restart"
esac

Unfortunately, this script is full of hacks and problems. When running the script from a SSH session, when you exit, the audio stops playing (even thought the shairplay.pl process continues to run). I’m not sure why. If shairport is run as part of the boot process, this is not a problem.

Also note that I am piping the command into the at-daemon, to delay the start by a minute. Unfortunately, optware’s /opt/etc/init.d/* scripts seem to run *before* the stuff in /usr/syno/etc/rc.d/, so this is to ensure that avahi-daemon is already running by the time shairport starts.

Also, dbus makes trouble: Because it never clears out it’s pidfile on shutdown, after a reboot, dbus will not come up. I fixed this by strategically placing a rm -f $PIDFILE in /opt/etc/init.d/S20dbus. The correct way of course would be check whether the pidfile is stale before deleting it, but I fail at shell.

So there it is. You may just want to go and buy an Airport Express.

11 thoughts on “Shairport on Synology NAS

  1. thx a lot for this, very helpfull !

    the c version seems to be fixed today and works quite well (no pb with ssh).

    Like

  2. very interesting but still a little bit too technical…
    could you please add more detailled instructions on how to set up on a synology without having to mess a lot with terminal?

    Like

    1. I guess somebody could package it up as an SPK, but that somebody won’t be me, sorry.

      Also note that Synology has announced some form of AirPlay support for the next DSM version (the beta is already out). I’m not sure if it allows receiving content, or just streaming to other AirPlay devices.

      Like

  3. the spk will be difficult to make especially the avahi replacement i think. perhaps i’ll give it a try this w.e. if i’m bored.

    ps : The C part isn’t really fixed, ipv6 need to be disabled on the syno so osx can stream. (it works with ipv6 enabled from ios & win).

    another thing, shairplay should work with multiple streamers, it doesn’t work here with the C one. it works with the perl version ?

    Like

  4. I’m not sure how multiple streamers would work; Would it play all streams simultaneously? The Perl version doesn’t support it, and neither does an actual Airport Express.

    Like

  5. yup simultaneously,it works on a linux box with the integrated sound card…

    on the git page :
    “It supports multiple simultaneous streams, if your audio output chain (as detected by libao) does so.”

    Like

  6. Ah, I missed, that Interesting.

    Still, OSS/the /dev/dsp4 device on the Synology might not support it. I certainly remember not being able to use shairport when AudioStation was in USB mode.

    Like

  7. I do not see how you got shairplay compiled in the first place… I suppose you have to have to have toolchain installed, plus some dev libraries on your NAS. I’d rather not buy airport express though, did some things change?
    Did you try some java implementations of airplay? RPlay etc

    Like

    1. Good point. While I was using the Perl version, it still requires compilation of the hairtunes library. I certainly didn’t use any Synology toolchain, so I must’ve installed gcc/make etc. via ipkg.

      Like

  8. What’s the status of your solution now? Are you using it? I’ve tried AirReceiver(https://github.com/fgp/AirReceiver) and it starts up (I have Java embedded on my synology), but crashes when I try to play a song. There are also Python implementations
    Although, I suppose the C version should be fastest, especially in embedded environment.

    Like

  9. I’m not using it anymore. While it mostly worked, it was never perfect, and at this point, I have switched NASes and don’t currently use iOS; so I never bothered to set it up again.

    Like

Leave a comment