This gist will show how to setup Raspbian Stretch as a headless Bluetooth A2DP audio sink. This will allow your phone, laptop or other Bluetooth device to play audio wirelessly through a Rasperry Pi.
A quick search will turn up a plethora of tutorials on setting up A2DP on the Raspberry Pi. However, I felt this gist was necessary because this solution is:
- Automatic & Headless - Once setup, the system is entirely automatic. No user iteration is required to pair, connect or start playback. Therefore the Raspberry Pi can be run headless.
- Simple - This solution has few dependencies, readily available packages and minimal configuration.
- Up to date
- Raspbian Stretch - I used the Lite version as this is a headless setup. See the official guide if you need help.
- Bluez-alsa - Available in the Raspbian package repo. This software allows us to stream A2DP audio over Bluetooth without PulseAudio.
- Raspberry Pi with Bluetooth - The Raspberry Pi 3 has integrated Bluetooth, however there is a known bug when the WiFi is used simultaneously. Cheap USB Bluetooth dongles work equally well.
If you are using a separate USB Bluetooth dongle, disable the integrated Bluetooth to prevent conflicts.
To disable the integrated Bluetooth add the following
# Disable onboard Bluetooth
dtoverlay=pi3-disable-bt
to /boot/config.txt
and execute the following command
sudo systemctl disable hciuart.service
First make sure the system is up to date using the following commands.
sudo apt-get update
sudo apt-get upgrade
Then reboot the Pi to ensure the latest kernel is loaded.
Now install the required packages.
sudo apt-get install bluealsa python-dbus libasound2-dev
To get the latest features and HD sound quality I recommend to compile and install bluealsa manually.
(Enable AAC on macOS sudo defaults write bluetoothaudiod "Enable AAC codec" -bool true && sudo defaults read bluetoothaudiod
)
First install libfdk-aac
sudo apt-get install autoconf libtool -y
mkdir ffmpeg
cd ffmpeg
wget -O fdk-aac.zip https://github.com/mstorsjo/fdk-aac/zipball/master
unzip fdk-aac.zip
cd mstorsjo-fdk-aac*
autoreconf -fiv
./configure --prefix="$HOME/ffmpeg_build" --disable-shared
sudo make
sudo make install
export PKG_CONFIG_PATH=/home/pi/ffmpeg_build/lib/pkgconfig
Upgrade bluez to latest version
sudo apt-get install libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev -y
wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.58.tar.xz
tar xvf bluez-5.58.tar.xz && cd bluez-5.58
./configure --prefix=/usr --mandir=/usr/share/man --sysconfdir=/etc --localstatedir=/var --enable-experimental
make -j4
sudo make install
sudo reboot
Check successful upgrade with bluetoothctl -v
Afterwards install https://github.com/Arkq/bluez-alsa as described in the README and please have the following dependencies installed.
Dependencies to install sudo apt-get install -y libsndfile1 libsndfile1-dev libbluetooth-dev
SBC:
git clone https://git.kernel.org/pub/scm/bluetooth/sbc.git
./bootstrap-configure
./configure
make
sudo make install
(I configured it with ../configure --enable-aac --enable-msbc
)
Make it available via systemd as described in the WIKI https://github.com/Arkq/bluez-alsa/wiki/Systemd-integration
Normally a Bluetooth device is only discoverable for a limited amount of time. Since this is a headless setup we want the device to always be discoverable.
- Set the DiscoverableTimeout in
/etc/bluetooth/main.conf
to 0
# How long to stay in discoverable mode before going back to non-discoverable
# The value is in seconds. Default is 180, i.e. 3 minutes.
# 0 = disable timer, i.e. stay discoverable forever
DiscoverableTimeout = 0
- Enable discovery on the Bluetooth controller
sudo bluetoothctl
power on
discoverable on
exit
- Set proper device class in
/etc/bluetooth/main.conf
.
# Default device class. Only the major and minor device class bits are
# considered. Defaults to '0x000000'.
#Class = 0x000100
Class = 0x200400
A Bluetooth agent is a piece of software that handles pairing and authorization of Bluetooth devices. The following agent allows the Raspberry Pi to automatically pair and accept A2DP, HFP, HSP and AVRCP connections from Bluetooth devices (HFP, HSP and AVRCP are required to get macOS, Windows connections working). All other Bluetooth services are rejected.
Copy the included file a2dp-agent to /usr/local/bin
and make the file executable with
sudo chmod +x /usr/local/bin/a2dp-agent
Before continuing, verify that the agent is functional. The Raspberry Pi should be discoverable, pairable and recognized as an audio device.
- Manually run the agent by executing
sudo /usr/local/bin/a2dp-agent
- Attempt to pair and connect with the Raspberry Pi using your phone or computer.
- The agent should output the accepted and rejected Bluetooth UUIDs
A2DP Agent Registered
AuthorizeService (/org/bluez/hci0/dev_94_01_C2_47_01_AA, 0000111E-0000-1000-8000-00805F9B34FF)
Rejecting non-A2DP Service
AuthorizeService (/org/bluez/hci0/dev_94_01_C2_47_01_AA, 0000110d-0000-1000-8000-00805f9b34fb)
Authorized A2DP Service
AuthorizeService (/org/bluez/hci0/dev_94_01_C2_47_01_AA, 0000111E-0000-1000-8000-00805F9B34FF)
Rejecting non-A2DP Service
If the Raspberry Pi is not recognized as a audio device, ensure that the bluealsa package was installed as part of the Initial Setup
To make the A2DP Bluetooth Agent run on boot copy the included file bt-agent-a2dp.service to /etc/systemd/system
.
Now run the following command to enable the A2DP Agent service
sudo systemctl enable bt-agent-a2dp.service
Bluetooth devices should now be able to discover, pair and connect to the Raspberry Pi without any user intervention.
Now that Bluetooth devices can pair and connect with the Raspberry Pi we can test the audio playback.
The tool bluealsa-aplay
is used to forward audio from the Bluetooth device to the ALSA output device (sound card).
Execute the following command to accept A2DP audio from any connected Bluetooth device.
bluealsa-aplay -vv 00:00:00:00:00:00
Play a song on the Bluetooth device and the Raspberry Pi should output audio on either the headphone jack or the HDMI port. See this guide for configuring the audio output device of the Raspberry Pi.
To make the volume control work over AVCTP you have to configure triggerhappy. Create the audio.conf
file and change the triggerhappy.service. Type sudo systemctl edit --full triggerhappy.service
and change user nobody
into pi
.
Caused by a bug in debian you need to disable triggerhappy.socket
by executing sudo systemctl disable triggerhappy.socket
.
Reboot and enjoy!
Thank you very much for this as its been very helpful so far. I had it working perfectly with my OnePlus 6, but i have a need to connect multiple, new devices from time to time. To test this i made the RPi and phone "forget" each other and then try to connect from fresh. When i try now it requests a pairing pin, which means it doesn't auto-connect on the RPi's side. Any ideas?
EDIT: ignore all that. I enabled the service again and it seems to be working fine now even after multible reboots and pairing/forgetting. My new problem is that audio will no longer stream - if i test with
bluealsa-aplay -vv 00:00:00:00:00:00
, i get an error message:bluealsa-aplay: E: Couldn't open PCM: Device or resource busy