Bluetooth audio on a headless Raspberry Pi using BlueAlsa

Intro

How to connect a Bluetooth speaker or a pair of Bluetooth headphones to a Rapberry Pi using the command line. No PulseAudio required!

Tested on a Raspberry Pi 400 running freshly installed [1] Raspberry Pi OS Lite aka Rasbian GNU/Linux 10 (Buster). Report any issues on GitHub.

BlueAlsa [2] is a Bluetooth audio backend for ALSA. It bridges the gap between BlueZ 5 (the Bluetooth stack) and ALSA (the audio stack) without the need for PulseAudio (a fat sound server).

Note

These instructions don’t apply to Rasbian 11 as it doesn’t ship a BlueAlsa package.

Rasbian 12 should include bluez-alsa-utils [3]; this page will be updated thereafter.

Command lines

A full terminal log is available here.

Note

The prompts have been removed for the best copy-pasting experience. You can highlight whole code blocks, no need to aim for corners!

Worried about “Pastejacking”? You can clone this website’s git repo and get hit by malicious build scripts instead or view this page’s raw reST source.

Adding the ‘pi’ user to the ‘bluetooth’ group

sudo usermod -G bluetooth -a pi && logout

Logout is needed for the change to take effect.

Installing and starting the BlueAlsa daemon

sudo apt update && sudo apt install bluealsa -y && \
sudo service bluealsa start

On Debian and derivatives the service will be enabled on startup by default.

Connecting a Bluetooth device

Warning

The code blocks in this section can not be copy-pasted.

Lines with commands to enter are emphasized.

The 00:00:00:00:00:00 and AA:BB:CC:DD:EE:FF below stand for the MAC addresses of your Bluetooth controller and audio device, respectively. You’ll find them out soon.

Using bluetoothctl interactively

Automating bluetoothctl is currently not covered in this article. I’ve listed some pointers here [6].

Start the bluetoothctl shell. On Raspbian Lite Bluetooth is enabled out of the box and the agent is registered automatically.

pi@raspberrypi:~ $ bluetoothctl
Agent registered
[bluetooth]#

The last line shows the bluetoothctl prompt; the following commands are executed in the bluetoothctl shell.

Tip

Tab completion works here, no need to type the full address!

To discover your Bluetooth device’s MAC, turn scan on. Make sure the device is in pairing mode!

[bluetooth]# scan on
Discovery started
[CHG] Controller 00:00:00:00:00:00 Discovering: yes

bluetoothctl will keep spitting out scan results so you might want to turn scan off after recognizing your device. Exiting bluetoothctl will turn off scanning automatically, but we’re not there yet!

Next up: pairing, trusting and connecting. Trusting enables connecting automatically, including after reboot. Yet you need to connect manually for the first time.

[bluetooth]# pair AA:BB:CC:DD:EE:FF
Attempting to pair with AA:BB:CC:DD:EE:FF
[CHG] Device AA:BB:CC:DD:EE:FF Connected: yes
[CHG] Device AA:BB:CC:DD:EE:FF ServicesResolved: yes
[CHG] Device AA:BB:CC:DD:EE:FF Paired: yes
Pairing successful
[CHG] Device AA:BB:CC:DD:EE:FF ServicesResolved: no
[CHG] Device AA:BB:CC:DD:EE:FF Connected: no

[bluetooth]# trust AA:BB:CC:DD:EE:FF
[CHG] Device AA:BB:CC:DD:EE:FF Trusted: yes
Changing AA:BB:CC:DD:EE:FF trust succeeded

[bluetooth]# connect AA:BB:CC:DD:EE:FF
Attempting to connect to AA:BB:CC:DD:EE:FF
[CHG] Device AA:BB:CC:DD:EE:FF Connected: yes
Connection successful

The prompt changes to reflect connection status. Exit the bluetoothctl shell with either ^D or typing quit.

[BT DEVICE NAME]# quit

Your Bluetooth device’s MAC address is needed in the next step, so let’s save it into a variable as follows:

pi@raspberrypi:~ $ MAC="AA:BB:CC:DD:EE:FF"

Playing audio

The following barebones system-wide config for bluealsa defaults to using A2DP (ie. not sounding like a cheap handsfree); see the Gentoo Wiki article on Bluetooth headphones [4], the BlueALSA README [2] and the ALSA Wiki [5] for more information about configuration, listed here in order of thoroughness and relevance.

A simple multi-device asound.conf can be found here.

The following lines are indented with four spaces; the tab key doesn’t work as expected in here documents [7], but it does in your text editor.

Note

$MAC is your Bluetooth device’s MAC address and is substituted automatically (as long as you did the previous section in the same shell). Feel free to copypaste!

sudo tee /etc/asound.conf <<EOF
defaults.bluealsa {
    interface "hci0"
    device "$MAC"
    profile "a2dp"
}
EOF

All done. Test with aplay:

Warning

Loud!

aplay -D bluealsa /usr/share/sounds/alsa/Front_Center.wav

The file should play without throwing any errors.

Example of streaming audio from YouTube using mpv

The youtube-dl [8] version installed in tandem with mpv is really old; the package from PyPI is used here instead.

sudo apt install -y python3-pip mpv && \
sudo apt purge -y youtube-dl && \
sudo pip3 install youtube-dl && \
mpv --no-video --audio-device=alsa/bluealsa ytdl://dQw4w9WgXcQ

mpv can be configured to use BlueAlsa by default. Below is a simple system-wide mpv.conf for audio-only Bluetooth usage; ~/.config/mpv/mpv.conf is where per-user configuration resides. For more information, search for “Configuration files” in the mpv manual [9]. alsa/$PCM_NAME (for example alsa/btheadset) is used to refer to a spesific device.

sudo tee /etc/mpv/mpv.conf <<EOF
no-video
volume=50
audio-device=alsa/bluealsa
EOF

Disabling SAP (optional)

sudo mkdir /etc/systemd/system/bluetooth.service.d && \
cd /etc/systemd/system/bluetooth.service.d && \
sudo tee 01-disable-sap-plugin.conf <<EOF
[Service]
ExecStart=
ExecStart=/usr/lib/bluetooth/bluetoothd --noplugin=sap
EOF
sudo systemctl daemon-reload && \
sudo systemctl restart bluetooth.service

The empty ExecStart= line is required for replacing the daemon’s start command and not just appending to it [10].

Reloading daemon configurations and restarting the bluetooth service requires no reboot. [11]

Further reading

I have found the following resources useful. Feel free to look elsewhere, but be wary of everything assuming you have or need PulseAudio. To prevent link rot, I’ve made sure both the Internet Archive Wayback Machine and archive.today have a copy available as well as forked the repos/gists on GitHub.

See also the open GitHub issue “Add a mention on setting the sound device as default” for some discussion regarding ALSA defaults and fallbacks, as well as how to set a higher baud rate to fix sound stuttering.