nicokaiser / rpi-audio-receiver

Raspberry Pi Audio Receiver with Bluetooth A2DP, AirPlay 2, and Spotify Connect
MIT License
1.4k stars 148 forks source link
a2dp airplay-receiver alsa audio bluetooth raspberry-pi raspbian shairport-sync spotify

Raspberry Pi Audio Receiver

A simple, light weight audio receiver with Bluetooth (A2DP), AirPlay 2, and Spotify Connect.

Features

Devices like phones, tablets and computers can play audio via this receiver.

Requirements

Again: do not try to use the internal Bluetooth chip, this will only bring you many hours of frustration.

Installation

The installation script asks whether to install each component.

wget https://raw.githubusercontent.com/nicokaiser/rpi-audio-receiver/main/install.sh
bash install.sh

Note: the installation process is not reversible, there is no uninstall. The script is meant to be run on a clean device that is not used for anything else.

Basic setup

Lets you choose the hostname and the visible device name ("pretty hostname") which is displayed as Bluetooth name, in AirPlay clients and in Spotify.

Bluetooth

Sets up Bluetooth, adds a simple agent that accepts every connection, and enables audio playback through ALSA. A udev script is installed that disables discoverability while connected.

AirPlay 2

Installs Shairport Sync AirPlay 2 Audio Receiver.

Spotify Connect

Installs Raspotify, an open source Spotify client for Raspberry Pi.

Additional steps

Enable HiFiBerry device

When using a HiFiBerry or similar I2C device, a device tree overlay needs to be enabled in /boot/firmware/config.txt (replace dacplus with the overlay that fits your hardware):

...
dtoverlay=hifiberry-dacplus

To enable the software volume mixer, /etc/asound.conf needs to be created:

defaults.pcm.card 0
defaults.ctl.card 0

pcm.hifiberry {
  type hw
  card 0
  device 0
}
pcm.dmixer {
  type dmix
  ipc_key 1024
  ipc_perm 0666
  slave.pcm "hifiberry"
  slave {
    period_time 0
    period_size 1024
    buffer_size 8192
    rate 44100
    format S32_LE
  }
  bindings {
    0 0
    1 1
  }
}
ctl.dmixer {
  type hw
  card 0
}
pcm.softvol {
  type softvol
  slave.pcm "dmixer"
  control {
    name "Softvol"
    card 0
  }
  min_dB -90.2
  max_dB 0.0
}
pcm.!default {
  type plug
  slave.pcm "softvol"
}

Read-only mode

To avoid SD card corruption when powering off, you can boot Raspberry Pi OS in read-only mode. This can be achieved using the raspi-config script (in the "Performance" section).

Disable Wi-Fi power management

Disabling Wi-Fi power management might resolve some connection issues:

sudo nmcli connection modify preconfigured wifi.powersave 2

Disable internal Bluetooth and Audio

When an external audio device (HDMI, USB, I2S) is used, the internal audio can be disabled in /boot/firmware/config.txt (replace hifiberry-dacplus with the overlay which fits your installation):

...
dtoverlay=disable-bt
dtparam=audio=off
dtoverlay=vc4-kms-v3d,noaudio
dtoverlay=hifiberry-dacplus

Add Bluetooth devices

The device should be visible for new Bluetooth connections, but in some cases you might need to pair them manually:

sudo bluetoothctl
power on
agent on
# Now search for available bluetooth devices from your device
# Once paired note down the MAC address of your device 
trust 00:00:00:00:00:00 # Put device MAC address here so after reboot it can automatically re-connect again

Disable Wi-Fi when Bluetooth is connected

Dislaimer: You really might want to use a Bluetooth USB dongle. The internal Bluetooth module of the Raspberry Pi (all versions) is very limited and using it for audio transmission will most certainly lead to problems and unexpected behaviour, see raspberrypi/linux/#1402.

If you really want to use the internal Bluetooth module, you almost certainly need to disable Wi-Fi.

Modify /usr/local/bin/bluetooth-udev and remove the comments (#) around the ifconfig calls:

...
if [ "$action" = "add" ]; then
    ...
    # disconnect wifi to prevent dropouts
    ifconfig wlan0 down &
fi

if [ "$action" = "remove" ]; then
    # reenable wifi
    ifconfig wlan0 up &
    ...
fi

Bluetooth A2DP volume

To enable A2DP volume control, add the --plugin=a2dp parameter to the bluetoothd command line. This helps setting the volume via Bluetooth, but does not work on all setups.

# Enable A2DP volume control
mkdir -p /etc/systemd/system/bluetooth.service.d
cat <<'EOF' > /etc/systemd/system/bluetooth.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/libexec/bluetooth/bluetoothd --plugin=a2dp
EOF

Bluetooth Fast Connectable

Using the FastConnectable flag may lead to faster Bluetooth connections, but may also lead to poor sound quality. You can try and see if it works for you. See #70

Add the flag to the General section in /etc/bluetooth/main.conf:

[General]
...
FastConnectable = true
...

Bluetooth pairing with PIN

To enable pairing with a PIN code instead of Simple Secure Pairing mode, the following steps are required:

  1. Change sspmode 1 to sspmode 0 in /etc/systemd/system/bt-agent@.service
  2. Add --pin /etc/bluetooth/pin.conf to the ExecStart line in /etc/systemd/system/bt-agent@.service
  3. Add a file /etc/bluetooth/pin.conf which contains PIN code for the devices:

AA:BB:CC:DD:EE:FF 1234 (replace AA:BB:CC:DD:EE:FF with your Bluetooth devices's Mac address or * to use PIN 1234 for all devices)

Notes

So you need to try yourself if this works with your setup.

Limitations

Disclaimer

These scripts are tested and work on a current Raspberry Pi OS setup on Raspberry Pi. Depending on your setup (board, configuration, sound module, Bluetooth adapter) and your preferences, you might need to adjust the scripts. They are held as simple as possible and can be used as a starting point for additional adjustments.

Upgrading

This project does not really support upgrading to newer versions of this script. It is meant to be adjusted to your needs and run on a clean Raspberry Pi OS install. When something goes wrong, the easiest way is to just wipe the SD card and start over. Since apart from Bluetooth pairing information all parts are stateless, this should be ok.

Updating the system using apt-get upgrade should work however.

Contributing

Package and configuration choices are quite opinionated but as close to the Debian defaults as possible. Customizations can be made by modifying the scripts, but the installer should stay as simple as possible, with as few choices as possible. That said, pull requests and suggestions are of course always welcome. However I might decide not to merge changes that add too much complexity.

Related projects

There are many forks and similar projects that are optimized for more specific requirements.

References

License

MIT