8

I have a raspberry pi zero W and I would like to stream sound over bluetooth to a bluetooth-enabled speaker / headphone.

So how to achieve this with alsa?

Besi
  • 874
  • 4
  • 11
  • 24

2 Answers2

8

I did manage to play sound and record using my Marshall MID headphones using a Raspberry Pi Zero W, which has a builtin WiFi + Bluetooth adapter, but no audio jack.

Please note that there are different approaches using different tools such as bluez alsa and pulseaudio, hcitool, bluetoothctl.

Install bluez-alsa

Bluez Alsa let's you play sound on a bluetooth speaker like so:

aplay -D bluealsa:DEV=AA:BB:CC:DD:EE:FF,PROFILE=a2dp,HCI=hci0 ~/piano.wav

You'll have to install the bluealsa client from source.

cd && git clone https://github.com/Arkq/bluez-alsa.git
cd bluez-alsa
# git checkout tags/v1.3.1 -b v1.3.1
sudo apt install bluez bluez-tools -y
sudo apt install libglib2.0-dev -y
sudo apt install libasound2-dev -y
sudo apt install build-essential autoconf -y
sudo apt install libbluetooth-dev -y
sudo apt install libtool -y
sudo apt install libsbc-dev -y
# sudo apt install libbsd-dev libfdk-aac-dev libncurses5-dev libreadline-dev -y

mkdir -p m4
autoreconf --install
mkdir build && cd build
# ../configure --enable-aac --enable-debug
#../configure --enable-debug
../configure CFLAGS="-g -O0" LDFLAGS="-g" --enable-debug
make && sudo make install

Now you can run sudo bluealsa -S in a seperate terminal. You can startup bluealsa by it to /etc/rc.local before the exit line:

sudo nano /etc/rc.local

Now add

# Start bluealsa as root <https://github.com/Arkq/bluez-alsa>
export LIBASOUND_THREAD_SAFE=0
/usr/bin/bluealsa -S &

Reboot and make sure that it's running: ps -ef | grep bluealsa

User groups

Add the pi user to the audio and the bluetooth group

sudo adduser pi bluetooth
sudo adduser pi audio

bluetoothd with a2dp plugin

There is a a2dp plugin for our bluetooth agent. So we'll change the services' ExecStart parameter like so:

sudo nano /etc/systemd/system/bluetooth.target.wants/bluetooth.service

And while we're here we'll disable sap since this may cause some errors:

ExecStart=/usr/lib/bluetooth/bluetoothd --noplugin=sap --plugin=a2dp

Now reload and restart the agent:

sudo systemctl daemon-reload
systemctl restart bluetooth

bluetoothctl

I run bluetoothctl and issue the following commands:

sudo bluetoothctl
list
# Controller XXXXXX mydevice [default]
power on
agent on
default-agent
scan on
# [NEW] Device AA:BB:CC:DD:EE:FF XYZ
# Now I Press the pairing button on the device (disabling bluetooth on any nearby devices)
connect AA:BB:CC:DD:EE:FF
trust AA:BB:CC:DD:EE:FF
exit

The trust command will enable to auto-pair the device again later on.

If auto-connecting does not work after reboot you may add the following line to /etc/rc.local:

echo -e "power up\nconnect AA:BB:CC:DD:EE:FF\n quit"|bluetoothctl

Alsa config

Now let's create a config for our bluetooth device and add it either to /etc/asound.conf (global) or ~/.asoundrc (per-user basis).

    pcm.mid {
        type plug
        slave {
            pcm {
                type bluealsa
                device AA:BB:CC:DD:EE:FF
                profile "a2dp"
            }
        }
        hint {
            show on
            description "Marshall MID"
        }
     }

Playback and recording

Now that the devices is connected you should be able to playback like so:

aplay -D mid ~/piano.wav

Alternatively you can specify the address and profile like so:

aplay -D bluealsa:DEV=2C:4D:79:0D:17:F9,PROFILE=a2dp,HCI=hci0 ~/piano.wav

For recording you'll need a different profile:

arecord -D bluealsa:DEV=2C:4D:79:0D:17:F9,PROFILE=sco ~/test.wav

This may result in poor sound quality.

Troubleshooting

There are a few things that can go wrong so here some troubleshooting pointers.

Bluetoothctl

  • list lists the interfaces. Use select XX:XX:XX... to select another interface
  • devices list the devices. Use scan on, scan off to find new devices.
  • info XX:XX:XX... show information about the given device
  • remove XX:XX:XX... to remove a pairing and connection use remove. This can be helpful for starting over, when there are problems with the pairing process.

Unpair from other devices

Often the bluetooth devices may be connected to other computers, smartphones tablets. These devices can block a new pairing so make sure to switch those devices off or remove the pairing.

Bad file descriptor

I encountered an error when starting bluealsa which was :

bluealsa: Couldn't initialize controller thread: Bad file descriptor

In this case I had to delete the hci* file in the /run directory:

sudo rm /run/bluealsa/hci*

I would also get this message when running bluealsa without sudo.

Bluetooth service

You can get some logs by running

journalctl | grep blue

The status of the bluetooth service will also show some possible errors (Such as the SAP server error from above):

GFP> service bluetooth status
● bluetooth.service - Bluetooth service
   Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2018-10-24 08:59:08 UTC; 4s ago
     Docs: man:bluetoothd(8)
 Main PID: 566 (bluetoothd)
   Status: "Running"
   CGroup: /system.slice/bluetooth.service
           └─566 /usr/lib/bluetooth/bluetoothd

Oct 24 08:59:08 godfatherphone systemd[1]: Stopped Bluetooth service.
Oct 24 08:59:08 godfatherphone systemd[1]: Starting Bluetooth service...
Oct 24 08:59:08 godfatherphone bluetoothd[566]: Bluetooth daemon 5.43
Oct 24 08:59:08 godfatherphone systemd[1]: Started Bluetooth service.
Oct 24 08:59:08 godfatherphone bluetoothd[566]: Starting SDP server
Oct 24 08:59:09 godfatherphone bluetoothd[566]: Bluetooth management interface 1.14 initialized
Oct 24 08:59:09 godfatherphone bluetoothd[566]: Failed to obtain handles for "Service Changed" characteristic
Oct 24 08:59:09 godfatherphone bluetoothd[566]: Sap driver initialization failed.
Oct 24 08:59:09 godfatherphone bluetoothd[566]: sap-server: Operation not permitted (1)
Oct 24 08:59:09 godfatherphone bluetoothd[566]: Endpoint registered: sender=:1.6 path=/A2DP/SBC/Source/1

The following lines are in red:

  • Failed to obtain handles for "Service Changed" characteristic
  • Sap driver initialization failed.
  • sap-server: Operation not permitted (1)

Information and debugging

Additional packages

sudo apt install blueman xauth -y
sudo apt install -y obex-data-server 

Logfiles

Logs to check during debugging

dmesg | egrep -i 'blue|firm'
tail -f /var/log/syslog
journalctl -u bluetooth

No such device

At some point I got the following error message:

ALSA lib ../../../src/asound/bluealsa-pcm.c:666:(_snd_pcm_bluealsa_open) Couldn't get BlueALSA transport: No such device
aplay: main:788: audio open error: No such device

This message won't come if the device is connected and paired.

Displaying the connected devices:

 $ busctl tree org.bluez
└─/org
  └─/org/bluez
    └─/org/bluez/hci0
      ├─/org/bluez/hci0/dev_XX_XX_79_0D_17_F9
      └─/org/bluez/hci0/dev_XX_XX_26_AF_79_03

Status of bluetooth

The System D status command will give you the status and errors of the bluetooth agent.

sudo systemctl status bluetooth


● bluetooth.service - Bluetooth service
   Loaded: loaded (/lib/systemd/system/bluetooth.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2018-10-24 18:21:16 UTC; 14min ago
     Docs: man:bluetoothd(8)
 Main PID: 615 (bluetoothd)
   Status: "Running"
   CGroup: /system.slice/bluetooth.service
           └─615 /usr/lib/bluetooth/bluetoothd --noplugin=sap

Oct 24 18:21:16 mypi systemd[1]: Starting Bluetooth service...
Oct 24 18:21:16 mypi bluetoothd[615]: Bluetooth daemon 5.43
Oct 24 18:21:16 mypi systemd[1]: Started Bluetooth service.
Oct 24 18:21:16 mypi bluetoothd[615]: Starting SDP server
Oct 24 18:21:16 mypi bluetoothd[615]: Excluding (cli) sap
Oct 24 18:21:16 mypi bluetoothd[615]: Bluetooth management interface 1.14 initialized
Oct 24 18:21:16 mypi bluetoothd[615]: Failed to obtain handles for "Service Changed" characteristic
Oct 24 18:23:29 mypi bluetoothd[615]: Endpoint registered: sender=:1.12 path=/A2DP/SBC/Source/1
Oct 24 18:23:29 mypi bluetoothd[615]: Endpoint unregistered: sender=:1.12 path=/A2DP/SBC/Source/1
Oct 24 18:23:43 mypi bluetoothd[615]: Endpoint registered: sender=:1.13 path=/A2DP/SBC/Source/1

Policy User

According to wiki.archlinux.org:

Edit the file /etc/dbus-1/system.d/bluetooth.conf and add these lines to the bottom, just before the closing </busconfig>.

<policy user="bluealsa">
  <allow send_destination="org.bluez"/>
</policy>

Optional: Get the address of the the bluetooth device

On my mac I hit while pressing the bluetooth icon in the status bar.

enter image description here

Besi
  • 874
  • 4
  • 11
  • 24
  • mp3 does not work, only wav ... – mahatmanich Nov 10 '18 at 23:19
  • Thanks for the detailed explanation. I was able to stream a mp3 file to connected BT speaker. However, what I am trying to achieve is to route all the sound playback over to BT device. So, the default audio sink should be set to connected BT speaker. Can you give me a pointer in that direction? – Purush Pawar Feb 14 '19 at 13:13
  • omg, THANK YOU! I've tried soooooo many tutorials, guides, tips etc and this was the only solution that actually works for my headless Pi Zero W. I have working bluetooth audio now! Yay! – HankScorpio Jan 29 '24 at 21:23
  • @HankScorpio I'm very glad you're able to listen to some wireless music now =) – Besi Jan 31 '24 at 08:59
0

Note: When setting up /etc/asound.conf or .asoundrc if you set it as "default" then you don't need to specify the device when calling aplay. ie:

aplay ~/piano.wav

instead of

aplay -D mid ~/piano.wav

To do this the asoundrc should appear like so

pcm.!default {
        type plug
        slave.pcm {
                type bluealsa
                device "MAC address"
                profile "a2dp"
        }
}
ctl.!default {
type bluealsa
}
Dirk
  • 3,541
  • 3
  • 18
  • 25
Brian
  • 1
  • Sorry for the formatting of the asoundrc file. I cannot seem to find a way to post this with all the nice formatting included but you can add the format as you like when adding the text to your asoundrc file. Note: This default works for the mplayer example used above as well. – Brian Jun 18 '20 at 21:38
  • Re formatting: indent with 4 spaces or use 'code' button in the editor – Dirk Jun 19 '20 at 08:25