Build your own headless Raspberry Pi audio player

published: / last edited:

For a hassle-free solution, have a look at HiFiBerryOS, Volumio, piCorePlayer, RoPieee or similiar solutions. These notes describe how you can build your own headless player step by step by installing all the software yourself and configure it via the command line.

NOTE: this is from 2020. It may no longer be up to date. I may revisit and update this in the future, in the meantime you are on your own.

You can read more about this project here.

##

1. Hardware

If you want the most low budget solution, use a Raspberry Pi 3 with the onboard audio. Or you can use a Raspberry Pi Zero, with a cheap USB audio adapter, or use audio over HDMI if you connect directly to a soundbar or your TV or something like that. I won't cover those use cases here, but you can find out how to play audio on your own and then jump to 4. headless Spotify Connect player

I'm using a Raspberry Pi Zero W because it is the smallest of the Raspberry Pis, it's cheap and powerful enough.

There are a lot of audio hats you can use:

I used the Allo MiniBoss, the Pimoroni pHAT DAC, the Adafruit I2S Audio Bonnet and the Raspiaudio Audio+. All work without problems.

On a non-zero pi you can use the 3.5mm audio jack, or use the HDMI output directly with a Soundbar or a HDMI to Cinch converter.

The 3.5mm audio jack and the onboard dac are not that great, so a special dac shield or audio over HDMI is a better solution if you want high quality audio.

Use a decent power supply; the more expensive your audio shield is, the more expensive the power supply should be.

2. Get the Raspberry Pi Running

I'm using a Raspberry Pi Zero W, but any Rasberry Pi should work.

(Note: for updated notes on how to install Pi OS on a headless server, read the notes on "Raspberry Pi OS Headless Install" and then continue with updating the Raspberry Pi; my old notes for the installation are still here, but may no longer be accurate)

Download the latest Raspberry Pi OS Lite and extract the zip file. We use the lite version, because we want to run our Pi in headless mode without a gui and no monitor or keyboard connected to the pi.

Flash the extracted iso file to an microSD-card (a small 4GB card is enough; you could even get away with a 2GB card, but then updating the kernel may be a bit tricky) using Etcher, or another tool.

Mount the sd-card and add an empty file called ssh to the /boot partition so that the ssh server will be enabled at boot.

If you want to use wifi, add a text file called wpa_supplicant.conf in the /boot partition with the following content:

ctrl_interface=/var/run/wpa_supplicant
update_config=1
country={COUNTRY}

network={
    ssid="{SSID}"
    psk={PSK}
}

Exchange {COUNTRY} with the two-letter-code of your country of your country. This is needed so that the pi knows on which bands it can send its wifi signal.

Exchange {SSID} with the name of your wifi.

Exchange {PSK} with a psk string. This is a encrypted version of your wifi password. You can generate this string on this website or using the command line using wpa_passphrase (when using the command line, watch out for special characters and spaces in your SSID or password).

You can add multiple network options if you want to save more than one set of wifi credentials.

Then unmount the sd card, put it to your pi, connect the pi to power. Wait some time (until the LED stops blinking), the pi will boot, expand the partition to the full size of the sd-card and then reboot.

If the info in your wpa_supplicant.conf was correct, the pi should automatically connect to your wifi. Otherwise, you can use an ethernet connection.

Open a terminal, ssh into the pi (look here at 4. Set up your client for more information; we took care of steps 1.–3. with the wpa_supplicant and the ssh file in the boot partition); the default user is pi and the default password is raspberry.

Update your pi with sudo apt update && sudo apt upgrade -y.

Start raspi-config with sudo raspi-config and under System Options, change the Password and the Hostname. Under Localisation Options, change the Timezone.

Reboot your pi, reconnect via ssh (when rebooting, you get disconnected automatically) - if you changed your hostname, you now need to use ssh pi@{NEW_HOSTNAME}.

You maybe want to disable low power mode for wifi by running sudo iwconfig wlan0 power off so that the device will always be available. This is not needed when using Ethernet. To make this change consist over reboots, add this to /etc/rc.local before the final exit 0 line: /sbin/iwconfig wlan0 power off.

3. Get the Audio Output Running

If you use a shield for audio, see the corresponding manual how to set up audio output.

If you want to use the 3.5mm audio jack (on a big pi) or audio over HDIM, use raspi-config to select your audio output (System Options - Audio).

You can use sudo aplay /usr/share/sounds/alsa/Front_Center.wav to test the audio output and sudo alsamixer to set the volume level

4. Headless Spotify Connect Player

We use raspotify as a spotify connect client. To install it, we use the script provided on the webpage: curl -sL https://dtcooper.github.io/raspotify/install.sh | sh (you can see what the script does by typing wget -qO- https://dtcooper.github.io/raspotify/install.sh or opening the URL in a browser; this is generally a good idea before executing some script downloaded from the internet).

After installing, open the config file /etc/default/raspotify in an editor of your choice, for example in nano by running sudo nano /etc/default/raspotify (in nano, you can press [CTRL] + [X] and then [Y] to close and save the changes you made).

Change the line #DEVICE_NAME="raspotify" to DEVICE_NAME="{name}" (removed the # at the beginning and change the name; this is what the device will be called in Spotify)
You can also remove the # in front of OPTIONS and add your username and password. This is not required, your device will be visible to all devices in your wifi running Spotify by default, but if you add your username and password you can also access your device over the internet.

After changing and saving the options file, restart raspotify by typing sudo systemctl restart raspotify

If you use a firewall on your pi, you may want to open some ports for Spotify Connect to work correctly; see this post for details.

Now you should be able to open Spotify on another device and connect to this new Spotify Connect client. If you have problems, have a look at the raspotify GitHub page.

5. Headless AirPlay Player

We use shairport-sync as a AirPlay client. To install it, run sudo apt install shairport-sync -y; this will install an older version, which is good enough, but if you want to run the newest version you can follow these instructions.

After installing, open the config file /etc/shairport-sync.conf in an editor of your choice, for example in nano by running sudo nano /etc/shairport-sync.conf (in nano, you can press [CTRL] + [X] and then [Y] to close and save the changes you made).

In the general area, remove the // in front of name = "%H"; and change %H to a name of your choice; this is the name that will appear in the AirPlay client select screen of your iOS device.

In the sessioncontrol area, remove the // in front of allowsessioninterruption = "no"; and change the no to yes, if you want to be able to allow another device to interrupt playing.

Run sudo systemctl enable shairport-sync to start shairport-sync automatically when booting, and then sudo systemctl start shairport-sync to start the AirPlay client. You can use sudo systemctl status shairport-sync.service to see if the service is running

Now you should be able to see the client in the AirPlay device selection dialog on an iOS device. If you have problems, have a look at the shairport-sync GitHub page.

6. Headless Plexamp Player

NOTE: I don't seem to get this to run reliably; as soon as you listen to something via Plexamp, the Spotify and AirPlay client stop working and you need to reboot the system. I stopped using the headless plexamp player and just use plexamp on my phone or tablet, with AirPlay. I might revisit this problem in the future, in the meantime the old solution is still here, but you have been warned. Here be dragons:

When running a Plex Media Server for your music and have a Plex Pass you can use Plexamp to listen to your music collection in high quality.

We use this tutorial which is based on this forum post:

Get the correct nodejs version and install it by running wget https://nodejs.org/download/release/v9.11.2/node-v9.11.2-linux-armv6l.tar.gz and then sudo tar -C /usr/local --strip-components=1 -xzf node-v9.11.2-linux-armv6l.tar.gz (after that, you can removed the downloaded archive with rm node-v9.11.2-linux-armv6l.tar.gz

Download the PlexAmp Raspberry Pi Beta by running wget https://files.plexapp.com/elan/Plexamp-v2.0.0-rPi-beta.2.tar.bz2, then unpack it with bunzip2 Plexamp-v2.0.0-rPi-beta.2.tar.bz2 followed by tar -xvf Plexamp-v2.0.0-rPi-beta.2.tar (remove the original archive with rm Plexamp-v2.0.0-rPi-beta.2.tar)

Open the /home/pi/plexamp/plexamp.service file in an editor and change the ExecStart=/usr/bin/node /home/pi/plexamp/server/server.prod.js to ExecStart=/usr/local/bin/node /home/pi/plexamp/server/server.prod.js to make sure that the correct node version is used

Now it get's a bit tricky - we need a server.json file that contains the authorization information. This file was generated by plexamp v.1 and v.2, the current plexamp v.3 doesn't generate this file anymore. I found an old Windows installer for v.1.1.0, which generates a server.json and places it in C:\Users\{USERNAME}\AppData\Local\Plexamp\Plexamp. Copy this file to your pi at /home/pi/.config/Plexamp/server.json. The server.json looks something like this:

{
  "player": {
    "name": "{NAME}",
    "identifier": "{????}"
  },
  "user": {
    "id": {????},
    "token": "{????}"
  },
  "server": {
    "identifier": "{????}",
    "library": "/library/sections/{????}"
  }
}

copy the service file with sudo cp /home/pi/plexamp/plexamp.service /lib/systemd/system/plexamp.service, then reload the service files with sudo systemctl daemon-reload, enable the plexamp service with sudo systemctl enable plexamp and start it with sudo systemctl start plexamp. You can use sudo systemctl status plexamp.service to see if it is running.

Now you should be able to select the pi plexamp client in the plexamp player.

(You may need to also open port 32500)

7. Overlay Filesystem

We can protect the SD-card by using an overlay filesystem. As long as the overlay filesystem is active, the SD-card is read-only and nothing gets written to it, and after a reboot every change you made is gone.
You can use raspi-config to enable/disable the overlay filesystem: start raspi-config with sudo raspi-config and then go to Performance Options - Overlay File System (you do not need to make the boot partition write-protected). After enabling it, the pi needs to reboot.
Don't forget to disable the overlay filesystem before making any changes to the config files or installing new software.

----------
Have a comment? Drop me an email!