with the "latest" versions of pulseaudio 12.2 and bluez/bluetoothd 5.50 in Nov 2020 in Raspbian repos
guide updated on Nov 23, 2020
There are tons of guides online that show you how to use your Raspberry Pi as a Bluetooth audio receiver. Unfortunately, at time of writing, none of them seem to work, and contain unnecessary (unexplained) steps or settings that don't really add anything useful.
If you haven't followed any guides yet, skip to the TRUTHS part. If you have, the LIES part may clarify some things for you.
Before doing some deep diving myself, I tried using these guides to get the result I wanted.
I found them to be so confusing. They may have been written for older versions of pulseaudio and/or bluez, but anyway, they contain a lot of information that is incorrect with current versions.
You need a script that creates a pulseaudio sink for all of your bluetooth connections and removes them afterwards
I don't use any script and it works just fine. The modules for pulseaudio that talk to bluez deal with this stuff. I don't need my Pi to be discoverable, I just want to pair my phone and be done with it.
You need to set a Class in /etc/bluetooth/main.conf
The Class is set automatically when pulseaudio connects to bluetoothd over dbus, no need to set it
You need to enable some services in /etc/bluetooth/audio.conf
This file is completely ignored by bluetoothd as you can check with strace
You need to change the resample-method in /etc/pulse/daemon.conf to trivial
I don't see why. It works fine without changing the resampling method
lp is the pulseaudio group
The lp group is for printer services. So that's nonsense. In older versions of bluez' dbus policy file bluetooth.conf
, the lp group would have permission to talk to bluez out of the box, so I guess that's why they wanted you to add the pi user to it (bluetoothctl access without sudo)
You need a specific bluetooth alsa package
Not true. I didn't install anything and all worked fine
Here are some things that are true. From top to bottom you can also read this as a step-by-step guide. Assuming you already have bluez and pulseaudio installed and working.
- You need to install the pulseaudio bluetooth module
You need the pulseaudio-module-bluetooth
package that comes with module-bluetooth-policy
and module-bluetooth-discover
. Find it in your distro's package manager.
- Pulseaudio needs permission to talk to bluez over dbus
These permissions are handled in /etc/dbus-1/system.d/bluetooth.conf
. It ships with bluez by default. Without a policy file pulseaudio will not be allowed to talk to bluez over dbus. My bluez package came shipped with a bluetooth.conf file that is not equal to the one currently in the bluez git repository, and did not work. I took the most recent file from the bluez git repository - which is also the file that will be shipped with new versions of dbus. It worked without any modifications. Be sure to do a reboot after changing this file cuz just restarting dbus can cause some programs to crash.
- You need to create a systemd service file for pulseaudio
Pulseaudio is not meant to be run as a service (but we're gonna do it anyway) so create a file over at /etc/systemd/system/pulseaudio.service
and add this:
[Unit]
Description=PulseAudio Daemon
After=bluetooth.service
[Install]
WantedBy=multi-user.target
[Service]
Type=simple
ExecStart=/usr/bin/pulseaudio --system --realtime --disallow-exit --no-cpu-limit --disable-shm
I found this template somewhere online and works well. I did add After=bluetooth.service
to make sure pulseaudio and bluez start in order to prevent potential conflicts.
- You need to configure pulseaudio
In /etc/pulse/system.pa
, add the following to the bottom.
load-module module-bluetooth-policy
load-module module-bluetooth-discover headset=native
PulseAudio supports HFP which allows mobile telephony devices to be represented as a modem. We don't want this functionality to be enabled as it can cause some issues and we simply don't need it. Hence we disable it using the headset=native
option on the module-bluetooth-discover
module.
Assuming your bluetooth service is already enabled and started, we now enable and start our pulseaudio service.
# systemctl enable pulseaudio
# systemctl start pulseaudio
Now we run bluetoothctl and check whether everything looks good.
# bluetoothctl
show
> ...
> UUID: Audio Sink (0000110b-0000-1000-8000-00805f9b34fb)
> ...
Now pair and trust the devices you want to stream from using bluetoothctl. Upon connection the audio streaming will work straight away.
If you are - like me - using the native-protocol-tcp pulseaudio module to allow for streaming from linux pcs in conjunction with the zeroconf-publish module, and you're getting segfaults when starting pulseaudio: change your .pa to first load the native-protocol-tcp module, then load the bluetooth modules, and finally load the zeroconf-publish module. First loading the network related modules and then the bluetooth modules may result in a pulseaudio segfault on armv6 processors like the rpi b.
Another problem you may encounter is this error:
Assertion 'pa_shared_set(c, name, pconn) >= 0' failed at pulsecore/dbus-shared.c:48, function dbus_connection_new(). Aborting.
Again, solve this by loading the zeroconf-publish module at the bottom of your .pa.
There is a bluez plugin that seems to mess this up from time to time. The solution: open up /lib/systemd/system/bluetooth.service
and add --noplugin=avrcp
to the ExecStart command. Then run systemctl daemon-reload
followed by systemctl restart bluetooth
. That should fix it. Source: https://unix.stackexchange.com/a/515348
I wrote a script that does a lot of the things discussed here automatically, assuming a mint raspbian install:
https://gist.github.com/Tobiaqs/62cbb28cf64836ba7681da35b1fe50ef