Sound players: Adventures with Ampache, mpd, pulseaudio, Raspberry Pi, and Logitech Media Server

I finally decided it was about time to get my whole-house sound project off the ground. As an added bonus, I’d like to be able to stream music from my house to my Android phone.

Some Background

It was about 2.5 years ago that I last revisited the music-listening picture on Linux. I used Spotify for awhile, but the buggy nature of its support for local music eventually drove me up the wall. I have a large collection of music that will never be on Spotify (local choirs, for instance) and this was an important feature.

When Google Play Music added the feature of uploading your local collection, I used that; it let me stream music from my phone in my car (using the Bluetooh link to the car). I could also listen at home on a PC, or plug my phone into various devices to play. But that was a hassle, and didn’t let me have music throughout the house.

Google Play is reasonable for that, but it has a number of really glaring issues. One is that it often gets album artwork wrong; it doesn’t use the ID3 tags embedded in the files, but rather tries to “guess”. Another is that the “sync” is only “add”. Move files to another place in your collection, or re-rip them to FLAC and replace your old MP3s, and suddenly they’re in Google Play twice. It won’t ever see updated metadata, either — quite a hassle for someone that uses Musicbrainz and carefully curates metadata.

My Hardware

I already have an oldish PC set up as a entertainment box running MythTV. It is a diskless system (boots PAE over the network and has NFS root) and very quiet. It has video output to my TV, and audio output via S/PDIF to my receiver. It is one logical audio frontend.

My workstation in my office is another obvious place.

My kitchen has a radio with a line in jack, and I also have a small portable speaker with a line in jack to make the last two options. I also have a Raspberry Pi model B that I bought awhile ago and was looking for a purpose, so I thought – this should be cheap and easy, right? Well. Cheap, yes. Easy, not so much.

First attempt: Ampache

The Ampache project produces quite a nice piece of software. Ampache has matured significantly in the last 2.5 years, and the usability of its web-interface — with HTML5 and Flash players as options — is quite impressive. It is easily as usable as Google’s, though its learning curve is rather more steep. There are multiple Android apps for Ampache to stream remotely. And, while most are terribly buggy and broken, there is at least one that seems to work well.

Ampache can also output m3u/pls files for a standalone player. It does on-the-fly transcoding. There are some chinks in the armor, however. The set of codecs that are transcoded or passed through is a global setting, not a per-device setting. The bitrates are per-account, so you can’t easily have it transcode FLAC into 320Kbps mp3 for streaming on your LAN and 128Kbps MP3 for streaming to your phone. (There are some hacks involving IP address ranges and multiple accounts, but they are poorly documented and cumbersome.)

Ampache also has a feature called “localplay” in which it drives local players instead of remote ones. I tried to use this in combination with mpd to drive music to the whole house. Ampache’s mpd interface is a bit odd; it actually loads things up into mpd’s queue. Sadly it shares the same global configs as the rest. Even though mpd is perfectly capable of handling FLAC audio, the Ampache web player isn’t, so you have to either make it transcode mp3 for everything or forego the web player (or use a second account that has “transcode everything” set). Frustratingly, not one of the Android clients for Ampache is even remotely compatible with Localplay, and some will fail in surprising ways if you have been using Localplay on the web client.

So let’s see how this mpd thing worked out.

Ampache with mpd for whole-house audio

The primary method here is to use mpd’s pulseaudio driver. I configured it like so:


audio_output {
type "pulse"
name "MPD stream"
#server "remote_server" # optional
sink "rtp" # optional
mixer_type "software"
}

Then in /etc/pulse/system.pa:


load-module module-null-sink sink_name=rtp format=s16be channels=2 rate=44100 sink_properties="device.description='RTP Multicast Sink'"
load-module module-rtp-send source=rtp.monitor

This tells Pulse to use multicast streaming to the LAN for the audio packets. Pulse is supposed to have latency synchronization to achieve perfect audio everywhere. In practice, this works somewhat poorly. Plus I have to install pulse everywhere, which inserts its tentacles way too deeply into the ALSA stack for my taste. (alsamixer suddenly turns useless by default, for instance.)

But I gave it a try. After much fiddling — Pulse is rather poorly documented and the interactions of configuration tools with it even more so — I found a working configuration. On my MythTV box, I added:


load-module module-rtp-recv
load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;x.x.x.x

The real annoyance was getting it to set the output through the S/PDIF digital port. Finally I figured out the magic potion:


set-card-profile 0 output:iec958-stereo+input:analog-stereo

This worked reasonably well. The Raspberry Pi was a much bigger challenge, however.

I put Raspbian on it easily enough, and installed Pulse. But apparently it is well-known in the Pulse community that Pulse’s RTP does not work well with wifi. Multicast itself works poorly with wifi in general, and Pulse won’t do unicast RTP. However, Pulse assumes very low latency and just won’t work well with wifi at all.

Morever, pulseaudio on the rpi is something of a difficult beast to tame. It has crackling audio, etc. I eventually got it working decently with:

daemon.conf:


realtime-scheduling = yes
realtime-priority = 5
resample-method = src-sinc-fastest
default-sample-rate = 44100
default-fragments = 4
default-fragment-size-msec=20

and in system.pa, commented out the module-udev-detect and module-detect, and added:


load-module module-alsa-card device_id=0 tsched=0 fragments=10 fragment_size=640 tsched_buffer_size=4194384 tsched_buffer_watermark=262144

plus the rtp-recv and tcp protocol lines as before. This got it working with decent quality, but it was always out of sync by at least a few tenths of a second, if not a whole second, with the other rooms.

Brief diversion: mplayer

Many players besides pulseaudio can play the RTP streams that pulseaudio generates. mplayer, for instance, can. I found this worked on the Raspberry Pi:


mplayer -really-quiet -cache 64 -cache-min 95 -demuxer rawaudio -rawaudio format=0x20776172 rtp://224.0.0.56:46510

But this produced even worse sync. It became clear that Ampache was not going to be the right solution.

Logitech Media Server

I have looked at this a few times over the years, but I’ve somehow skipped it. But I looked at it again now. It is an open source (GPL) server, and was originally designed to work with Logitech hardware. There are now all sorts of software clients out there. There is a helpful wiki about it, although Logitech has rebranded the thing so many times, it’s not even consistent internally on what the heck it’s called (is it LMS? or Squeezebox Server? or Slimserver? The answer is: yes.)

LMS does no web-based streaming. At all. But I thought I’d give it a try. Installation is a little… weird (its .deb packages up binary perl modules for things that are already in Debian, for half a dozen architectures and many Perl versions.) I had some odd issues but eventually it worked. It scanned my media collection. I installed squeezelite on my workstation as my first player, and things worked reasonably well out of the box.

I proceeded to install squeezelite on the Raspberry Pi and MythTV server (where I had to compile libsoxr for wheezy, due to an obscure error I couldn’t find the cause of until I used strace). Log in to the LMS web interface, tell it to enable synchronization, and bam! Perfect synchronization! Incredible.

But I ran into two issues: one was that it used a lot of CPU even on my workstation (50% or more, even when idle). Strangely, it used far less CPU on the pi than did pulseaudio. Secondly, I’d get annoying clicks from it from time to time. Some debugging and investigation revealed that they were both somewhat related; it was getting out of sync with the pi and correcting. Initially I assumed this to be an issue with the pi, but tracked it down to something else. I told it to upsample to 48kHz and this made the problem go away. My command on PC hardware is:


squeezelite -a 200:10 -o dmix -u hLX -z

And on the Raspberry Pi:


squeezelite -a 800:10:16:0 -n kitchen -z

It is working perfectly now.

LMS even has an Android remote control app that can control all devices together, queue up playlists, etc. Very slick.

The Raspberry Pi

The Raspberry Pi, even the model B+, apparently has notoriously bad audio output. I noticed this first as very low volume on the output. I found a $11 USB DAC on Amazon that seems to do the trick, so we will see. I am also using the $10 Edimax USB Wifi and it seems to work well.

Other Options

The big-name other option here is Sonos. They have perfect sync audio already working. But they’re pricy, closed, and proprietary; you have to buy Sonos speakers, transmitters, etc. for the entire house. Their receivers start at $200, and it’s at least $350 to integrate an existing stereo into the system. I’d be shelling out over $1000 to use Sonos for this setup. As it is, I’ve bought less than $100 of equipment (a second Pi and its accessories) and getting output that, while no doubt not quite as pristine, it still quite nice and acceptable. Quite nice.

Update: LMS with Apache

It turns out that Logitech Media Server can automatically save created playlists to a spot where Ampache can find them. So an Ampache streaming player can be used to access the same collection LMS uses, with full features. Nice!

12 thoughts on “Sound players: Adventures with Ampache, mpd, pulseaudio, Raspberry Pi, and Logitech Media Server

  1. If you are not restricted to stuff in debian, you should check out subsonic[1], a Free player written in Java. There is a fork with the licensing code removed, so you can use the api.

    It has a very good Android player that can control either the jukebox (ie, playing on the server) or play locally. Streaming format is requested by the remote end, and the Android app has a setting for high quality on wifi and low quality on cell network.

    I’ve been trying to migrate away from subsonic to groovebasin (in jessie), but it is not ready yet.

    [1]http://www.subsonic.org/pages/index.jsp

    Reply

    John Goerzen Reply:

    Yep. In fact, Ampache supports the Subsonic API, so the Subsonic mobile player works with it (actually a lot better than many of the native ones!)

    The thing that bugged me about Subsonic then as now is that it doesn’t have a very good browser interface. It is based around the filesystem only, not tags, and lacks the handy Album / Artist / Genre browser that I am used to seeing elsewhere. I also don’t think it would do the whole-house sync that I’m looking for.

    Reply

  2. hey there. nice post. i bought the $11 usb DAC and noticed an improvement in sound. have you figured out how to enable the optical out?

    Reply

    John Goerzen Reply:

    I haven’t tried, but probably aplay -L would list the outputs that you could then select.

    Reply

  3. Hi John,

    thanks for posting this. You’ve got me thinking that maybe I shouldn’t give up on my Squeezebox Receiver quite yet (although Logitech has terminated support for it…). Which Logitech Media Server package did you use? Last time I checked the Logitech-provided package contained a number of Perl libraries (as opposed to using system-provided versions of those libraries) among other oddities. Are you aware of any proper Debian packages?

    Cheers,

    Rene

    Reply

  4. Interesting article.

    I have been on a similar quest, and have often been close to buying a Sonos system. But I didn’t want their speakers—I already have three adequate stereo systems, so the “Connect” would have been my best bet, but three ugly plastic boxes for $950 (3 × $350) just didn’t sound reasonable.

    Eventually I found a perfect solution:
    I installed MPD on my main computer, and on a couple older computers (14+ years). I am using Arch Linux, and it installed fine on these old machines and runs MPD without any issues. I use an iPod touch as a control device, and all my music is coming from my file server. There is a free iOS app (MPoD) that has a great and fast user interface and allows me to setup several connections to MPD servers. To simplify playlists and radio streams, I simply linked all the “playlists” folders of MPD to a folder on the file server, where all the playlists etc. are stored.

    If I wanted to, I could also open up my router’s port and make the music accessible over the internet, or simply setup a icecast-like stream.

    Personally, I think MPD is very capable and is a great Sonos alternative. If one needs more features (e.g. spotify integration), there is also Mopidy, which uses the same protocol as MPD.

    I cancelled my Spotify subscription—I have no need for it anymore, especially after finding great commercial free internet radio stations like those from soma.fm. The worst thing about spotify was the slow interface—once I had more than 100 albums in my collection, it was practically impossible to scroll through the list, it took forever to flip just a few pages.

    In the end I spent $200 for the iPod touch, and nothing more. Most people probably have some old laptop around which could perfectly serve as an MPD server, and most people probably already have a stereo system. This was my case, and my mission has been accomplished—do it yourself, save money, get all the benefits of open-source software and learn something along the way…

    Reply

  5. This is great, thanks for sharing your experience here. I was just about to start down the LMC/Squeezebox route and this will help a lot. I may try to substitute the raspberry pi with an old android phone just because I have so many of the things laying around and they tend to be pretty reliable. I just have to see if I can find a stable squeeze client for android that supports synchronization.

    It’s too bad Sonos is so greedy — I would pay $200 for a Connect, but not $350.

    Reply

  6. Hi guys,

    Thanks for the posts and comments.

    I have a Raspberry PI as LMS server connected via LAN cable, and then another PI, one laptop and 2 android phones as clients around the house, all connected via W-Fi. While everything works well, they are never perfectly synced. i was thinking of abandoning LMS and jump on to MPD, but I understand sync will also be a problem.

    I have not tried on installing the LMS server on a laptop instead and see if that helps syncing the players, and I am quite reluctant to lay wire around teh house (as the phones would not make use of that either) so I wondered if anyone has any strong opinion regarding hosting LMS server on a pi and successfully syncing using WiFI.

    Many thanks

    Reply

  7. I’d like to leave a pointer to volumio.org – it runs on a rpi or other small system. It uses Debian & MPD under the hood and provides a nice web interface that can be controlled from a phone or tablet etc. It knows about SMB and NFS network shares, plus USB sticks and internet radio.

    Regarding getting digital audio out of the Pi, one can use the HDMI port direct into an HDMI port on an A/V receiver, or connect into a magic box that presents the audio on a TOSLINK interface (“google://hdmi+convert+to+toslink”).

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *