Airplay Whole House Audio with Shairport-Sync and Forked-Daapd

This is a guide for Apple airplay users who wish to setup whole-house audio, with the ability to use the forked-daapd integration of homeassistant for automations and speaker selection, etc. This is working for me currently with Home Assistant core-2021.1.5, supervisor-2021.01.7 and Home Assistant OS 5.10 running on raspberry pi 4.
This documents how I have setup the forked-daapd server on the same rpi4 as homeassistant, and added shairport-sync so my iphone audio apps can be sent to multiple airplay speakers (ie “whole-house”), getting around the single speaker limitation of iOS/iPadOS/tvOS with airplay 1 speakers.
I rely on the portainer hassio addon to setup forked-daapd and shairport-sync docker containers.

These are sparse notes, I recommend reading up on how to use forked-daapd and shairport-sync in their respective github repositories.

Here are the docker-compose files for these, which can be pasted as “stacks” in portainer . In addition to pasting the docker-compose, be sure to name and deploy the stacks.

setup forked-daapd docker-compose:

version: "2"
services:
  daapd:
    image: linuxserver/daapd
    restart: always
    container_name: daapd
    network_mode: host
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/New_York
    volumes:
      - /mnt/data/supervisor/share/daapd:/config
      - /mnt/data/supervisor/share/music:/music

Add your music and playlist files to the /share/music directory (I use the hassio samba addon to do this). Edit the forked-daapd.conf file in /share/daapd, I use samba hassio addon and VScode editor. Uncomment the following to allow piped audio to autostart:

pipe_autostart = true

setup shairport-sync docker-compose:

version: "2"
services:
  shairport:
    image: mikebrady/shairport-sync
    restart: always
    container_name: shairport-sync
    network_mode: host
    devices: 
      - /dev/snd
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=America/New_York
    volumes:
      - /mnt/data/supervisor/share/music:/music
      - /mnt/data/supervisor/share/shairport:/config

Once deployed, open a console window for the running shairport-sync container (you need to select /bin/sh as the command type). Copy the shairport-sync.conf file to your /share/shairport directory so you can edit as needed to enable pipe support and any other changes such as the shair-port name:

cp /etc/shairport-sync.conf /config

Edit the file to enable pipe support and pipe metadata support. Again, I use the samba hassio addon to access the file for editing (I use VScode editor in Windows). I use the filenames “shair” and “shair.metadata” for the two pipe files in the shairport-sync.conf file.
Uncomment and edit the pipe and metadata entries, here’s a partial example of the changes to make, make sure both the open and close (not shown) brackets for each section are uncommented:

general =
{
	name = "Whole House"
output_backend = "pipe"
pipe =
{
name = "/music/shair";
metadata =
{
enabled = "yes";
pipe_name = "/music/shair.metadata";

Once the edits are made, copy back the file:

cp /config/shairport-sync.conf /etc

Now create the shair and shair.metadata files in the “music” directory, by executing each of these commands, one at a time:

cd music
mkfifo shair
mkfifo shair.metadata
chmod 777 shair*

Restart both the forked-daapd and shairport-sync containers (using portainer).
Now you should be able to add the forked-daapd server to homeassistant, and control your airplay speakers. You can access the forked-daapd web interface at port :3689. You should now see a shairport-sync speaker with the host name or whatever you named it in the shairport-sync.conf file (ie “Whole House”). Now you can send music from iOS/iPadOS/tvOS apps to multiple speakers you select in forked-daapd.

Hopefully this is a useful starting point for others!

5 Likes

This is very interesting that you can make this work on HassOS when the addon will not work. The addons are nothing more than glorified docker containers. If a normal docker container works, the addon should too… Hmm…

Yeah, I was wondering the same thing! I don’t know the subtleties that distinguish hassio addons from traditional docker containers???

Thanks for the write up. I might give this a go.

Do you guys reckon it would work with Modipy? I’d like to connect to soundcloud and stream to airplay devices.

There are very few differences between a hass.io addon and a docker container. It’s basically a docker container with a proprietary public config file which does essentially what a docker compose config does, and another private config by the developer to set the options they don’t want to expose. The container technology itself is just docker, nothing more.

@currest2620 have never tried mopidy, but it sounds like something that would be integratable. The addon already has airplay streaming, Spotify and last.fm scrobling so maybe they already rolled it in.

Thanks. I don’t think forked-daapd has support for Soundcloud as far as I can see.

I’m not too sure how it all fits together TBO. I gather that forked-daapd is needed to stream audio to airplay devices such as a HomePod. I’m not sure what shairport-sync does or how to integrate mopidy as a source.

I think it can be done though.
http://recycledspace.com/2018/04/my-music-setup-at-home-with-mopidy-forked-daapd-and-shairport-sync.html

As I understand it, shairport-sync was designed primarily to act as an airplay receiver/speaker so you can send airplay audio to a linux computer hooked-up to a speaker. I don’t use it for this primary purpose, but I could attach a speaker to my rpi4 and it should work as any airplay speaker.

shairport-sync also has the interesting ability to “pipe” audio to compatible programs that are able to receive the pipe, such as forked-daapd. Select the shairport-sync “airplay speaker” from your iOS/iPadOS/tvOS/iTunes audio app and forked-daapd treats the pipe like a song and it can be sent to multiple airplay devices, similar to how itunes works on windows or mac.

Mopidy may be able to create a similar audio “pipe” as shair-port sync. If this is the case, forked-daapd would connect to the mopidy pipe and send the audio to your airplay speakers.

1 Like

OK, the way I read that is shairport-sync is needed to stream audio to existing airplay devices on the local network, while forked-daapd emulates itunes.

So if I want to use mopidy instead, I don’t need to install forked-daapd.

-or-

forked-daapd can stream to existing airplay devices so it IS needed to stream content and I DON’T need to install shairport-sync.

-or-

I need both forked-daapd AND shairport-sync to stream to multi-room devices simultaneously (IF audio devices DO NOT support airplay 2).

Forked-daapd acts like itunes, so it can send audio (songs, playlists, internet radio web links…) to multiple airplay speakers on its own. I mention the use of shairport-sync only as a way to output audio from iOS apps to multiple airplay 1 speakers.

1 Like

Right, that makes sense. I think I’m misunderstanding the roles of music servers, streamers and DACs.

I think I’ll give this a go this afternoon. Just as an aside, I have a media folder that is used with the Media Browser in Home Assistant. Could that folder be used instead of the “music” folder in the docker config?

If so, can I assume that it’s path would be /mnt/data/supervisor/share/media:/media?

Thanks for the write up.

Use these as the volumes

- /mnt/data/supervisor/share/daapd:/config
- /mnt/data/supervisor/media:/music
1 Like

Thanks very much. Wasn’t very sure about the syntax.

Hey, just wanted to say thanks. I following your instructions and it appears to be working. Looking forward to seeing what I can do with it. Would never have been able to do that without your instructions. Thanks a bunch.

Quick question though. When I access the daapd server on port 3689, I keep getting a remote paring request from pyatv when ever I load the server page. Not really sure where this is coming from, but its the same IP address as the HA server and seems to be associated withe daapd server. If I load the apple TV integration, the dialogue shows “Aborted, Unexpected error”.

From the daapd server:

Apple TV integration:

Any ideas about what to do about this? Where do I obtain the pairing code?

*** Fixed after I restarted Home Assistant ***

2 Likes

Hey, does anyone else find the forked-daapd gets ‘stuck’ on the shair port stream / input? I’ve tried clearing the queue and removing it but when is select another track it just goes back to shair.

I find I have to go to portainer and restart the forkeddaapd and shairportsync containers to reset it.

Anyone else encountered this and/or has a way to clear the queue so it’ll play selected tracks? Not a biggie, but maybe I am missing something.

The only time mine ever got stuck was when I gave it bad playlist names. Other than that, it’s rock solid. But I use standard airplay devices, not shairport.

I started to have problems (requiring a restart of the forked-daapd and shairport-sync containers from time to time) after one of the Home Assistant OS updates.
I have switched to using a Debian 10 install of Home Assistant Supervised on my RPI4 and all is working well. This is a bit of work to switch from Home Assistant OS to Debian, so you will have to decide if it is worth it.

I now also switched to this method via Portainer, now that the addon no longer works. Thanks for the instructions! One question I still have: how to update forked-daapd to a newer version (in case it’s available)?

Here’s what I do to update, but I am not sure if it is the best way, using portainer:

  1. In “Containers” remove the forked-daapd container
  2. In “Images” remove the forked-daapd image
  3. In “Stacks” select forked-daapd, go to the “Editor” tab and click the “Update the stack” button

This will pull the latest version of the image from the repository, in this case it is the version at linuxserver/daapd, you can check the latest version at:

1 Like

OK, but its specifically related to the shairport input. Same happens when attempting to select another playlist or track directly within the forked-daapd web interface. It’s not a biggie, something I’m just wondering about.