MPD to Sonos with Icecast


Before I switched to Sonos as my primary way of listening to audio I've used MPD for years. As such I collected a fair amount of audio files that Rdio, Tidal or Spotify claim I'm not allowed to stream in my region. And while Sonos is great, there's not really a way to control it the way you can control an MPD server for which there are many clients and libraries. Whereas for Sonos your tied to the official apps, there's a webfrontend (WIP) and several reverse engineered libraries. I've actually spent quite some time hacking this gem .

What's harder than play/pause is to actually export your audio files.

I've toyed around with an SMB share, but, SMB... Also, there's still no way to actually control the queue.

So in this blogpost I'll show how to stream your audio through MPD and Icecast to Sonos, while you can control it with any MPD client.

Icecast

Sonos has support for listening to radio stations, which are in fact just .m3u streams. It just so happens that MPD has a shout output to Icecast. Which in turn creates a stream we can subscribe to.

Note that MPD also has an httpd output but that's just an MP3 stream which the Sonos controller app doesn't connect to, so trying to cut Icecast out of the equation didn't work.

So let's setup our mpd.conf:

audio_output {
    type        "shout"
    encoding    "mp3"
    name        "Shout Stream (mp3)"
    host        "icecast"
    port        "8000"
    mount       "/mpd.mp3"
    password    "hackme"
    quality     "0" # highest
    format      "44100:16:1"
}

Note that you can also create an ogg encoded stream, but sadly Sonos doesn't like that. So we'll just use mp3 at highest quality (which oddly enough is 0).

There's actually nothing to setup on the Icecast side to just get things up and running. You may want to tweak some default settings (like hostname), but the only thing you should really change are the passwords.

That's all there is to it. Start the icecast service followed by mpd. Point your favorite client to the server and off you go. You can verify the stream is created and broadcast by going to your Icecast server.

Now add the radio station to the Sonos controller:

Manage -> Add Radio Station...

Fill in http://icecast/mpd.mp3.m3u as the streaming url and give it a name, like MPD. You can then find it in:

Radio by TuneIn -> My Radio Stations -> MPD

Docker

My previous MPD host was a lower-power 300 mHz appliance running OpenBSD hooked up to my deskside speakers. Which sufficed just fine. However it turned out not to be capable enough to transcode the audio into two streams (ogg and mp3) and serve as an Icecast station.

Since this setup consists of two discrete components it's actually a good fit to move it into Docker containers.

Icecast container

Dockerfile:

FROM ubuntu:15.04
MAINTAINER Jasper Lievisse Adriaanse <j@jasper.la>

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update -qq && \
    apt-get upgrade -qqy && \
    apt-get install -y --no-install-recommends icecast2

COPY icecast.xml /etc/icecast2/

USER icecast2

ENTRYPOINT ["/usr/bin/icecast2", "-c", "/etc/icecast2/icecast.xml"]

EXPOSE 8000

icecast.xml

MPD container

Dockerfile:

FROM nfnty/arch-mini:latest
MAINTAINER Jasper Lievisse Adriaanse <j@jasper.la>

RUN pacman -Sy
RUN pacman -S --noconfirm reflector
RUN reflector --verbose -l 5 --sort rate --save /etc/pacman.d/mirrorlist
RUN pacman -S --noconfirm mpd

COPY run.sh /run.sh
COPY mpd.conf /etc/mpd.conf

VOLUME /var/mpd /audio

ENTRYPOINT ["/run.sh"]

EXPOSE 6600

mpd.conf and run.sh

If you're feeling lazy, here's also the docker-compose.yml:

icecast:
  build: icecast
  ports:
    - "18000:8000"

mpd:
  build: mpd
  links:
    - icecast
  ports:
    - "6600:6600"
  volumes:
    - /mnt/audio:/audio
    - $PWD/mpd/data:/var/mpd
  • Note that I've mounting the /audio volume from the host. That's because for some odd reasons I couldn't get my container to mount the NFS share from my NAS.
  • I'm using port 18000 for Icecast since I have another container on the host that's using port 8000.
  • If your audio collection is particularly large you also may want to use the /var/mpd volume to store the database. Otherwise it'll get re-indexed every time your (re)start the container.
  • The reason I'm using an Arch image is because that was the only distribution with MPD 0.19.9 (latest).

Wrapping up

While all this works great we've created a sort of split brain situation where we can control the queue with MPD, but not with the Sonos apps. Still, the private audio collection is usable again with Sonos-grade speakers.

Perhaps there's an idea in there for an mpc-like application that controls the MPD queue and the Sonos volume.