Making the Raspberry Pi 3 a bluetooth audio receiver

Now you might think this is a straight forward operation. There must be many people who have this kind of setup and a simple script will run all the required actions for you.

Well this is almost true. It took me very many hours to get this working and its still not perfect. Mostly because there is a feature in how bluetooth and wifi work on the Raspberry Pi 3. For audio to sound perfect you need to either have an external bt-adapter or external wifi-adapter. If you have internal bluetooth and wifi enabled at the same time then at the time of this posting you will have a choppy audio experience. Also volume seems to be very low even at maximum but I will investigate this further (look in the comments for a solution to low volume). Now then lets get hacking.

Raspberry Pi 3 Initial state

For these steps to work I will put it here that the device I was using was a fresh install of Raspbian Lite. So your journey will be different depending on the state of your machine.

Configure the PI

Configure your password, set preferred boot options etc.

sudo apt-get update
sudo apt-get upgrade
sudo raspi-config

The one option that I would recommend you to set is

Advanced Options -> Audio -> Force 3.5mm

So the audio will definitely output to the analog output.

Install BT-Speaker daemon

A wonderful German software engineer who goes by the name lukasjapan in github has made a good bt-speaker daemon which we will be using. https://github.com/lukasjapan/bt-speaker

Quick Installation for Raspbian:

sudo -i
bash <(curl -s https://raw.githubusercontent.com/lukasjapan/bt-speaker/master/install.sh)

Update Bluez

The script we just ran installed bluez from raspbian repo which is not the most up to date version available. To get the newest bluez version we must download the source from bluez website and compile it for raspbian.

Check the most up to date version from their download page.
Bluez download page

cd ~
wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.47.tar.xz
tar -xf bluez-5.47.tar.xz

Install dependencies

sudo apt-get update
sudo apt-get install -y libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev

Configure, make and install Bluez

cd bluez-5.47/
./configure --prefix=/usr --sysconfdir=/etc  --localstatedir=/var --enable-library --disable-systemd
make
sudo make install
sudo install -v -dm755 /etc/bluetooth
sudo install -v -m644 src/main.conf /etc/bluetooth/main.conf

Rename your bluetooth to something descriptive

sudo nano /etc/bluetooth/main.conf

Testing the waters

The bt_speaker.service doesn’t work yet. There are some permissions that need to be set before it can send commands to the bluetooth but we can try that our system is working so far by manually running the bt_speaker.py

First lets stop bluetooth and the possibly running bt_speaker.

sudo systemctl stop bluetooth
sudo systemctl stop bt_speaker

Now lets start bluetooth again and make it discoverable.

sudo systemctl start bluetooth
sudo bluetoothctl
power on
discoverable on
exit

Now you can try to connect to the Raspberry Pi with your phone and see if it is discoverable and able to connect. Audio will not work yet at this point. If you were successful in discovering and connecting to the Raspberry Pi via bluetooth then we can start the bt_speaker.py manually to test audio.

cd /opt/bt-speaker
python bt_speaker.py

You will need to first unpair the pi from your phone and the connect again for the bt_speaker daemon to register the connection and offer the audio services.

If all went well you should now be able to play music from your phone through the Pi to the speakers.

But as you might notice the audio is quite choppy and in the terminal you can see “underrun!!! (at…” text at regular intervals.

To get the audio to be smooth we need to disable the internal wifi adapter

sudo ifconfig wlan0 down

After this restart the bt_speaker.py and notice a smooth audio experience.

If anyone knows a solution to this problem other that buying an external wifi-adapter it would be much appreciated.

Permissions

Next we need to give some permission for the btspeaker user that the bt_speaker install script created and is using to start the bt_speaker.service.

Lets open the bluetooth.conf file and add some lines.

sudo nano /etc/dbus-1/system.d/bluetooth.conf

Add these lines to the file after root policies inside <busconfig>

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

Now if you start the bt_speaker service it should start without a hitch.

sudo systemctl start bt_speaker
sudo systemctl status bt_speaker

Helping services

Then all there is left to do is to set this up so that it starts nicely after the Raspberry boots up.

Some of these steps might be unnecessary but it’s all the things I had to do to get this working.

First lets modify the /etc/bluetooth/main.conf

sudo nano /etc/bluetooth/main.conf

Modify/Add the end of the file to

AutoEnable = true

Now for some reason that alone didn’t autostart the bluetooth for me. For some reason the bluetooth does not power on. So for that we will create our own service.

 

sudo mkdir /opt/bt_power
sudo nano /opt/bt_power/bt_power.sh

Inside this file will look like this

#!/bin/bash
echo -e "power on\nexit\n" | bluetoothctl
echo -e "power on\nexit\n" | bluetoothctl
systemd-notify --ready --status="Bluetooth power on"

Then create the bt_power.service file

sudo nano /etc/systemd/system/bt_power.service

And this is the contents

[Unit]
Description="Turn bluetooth power on"
After=bluetooth.service

[Service]
Type=notify
WorkingDirectory=/opt/bt_power
ExecStart=/opt/bt_power/bt_power.sh

[Install]
WantedBy=multi-user.target

Next we will modify the bt_speaker.service to wait for bt_power.service to finish and also to check that bluetooth service is running.

sudo nano /etc/systemd/system/bt_speaker.service

Modify to match this

[Unit]
Description="Simple bluetooth speaker for the Raspberry Pi"
After=bt_power.service
Requires=bluetooth.service
Wants=bluetooth.service

[Service]
TimeoutStartSec=30
WorkingDirectory=/opt/bt-speaker
ExecStartPre=/bin/sleep 10
ExecStart=/opt/bt-speaker/bt_speaker.py
StartLimitBurst=100
Restart=always
User=btspeaker

[Install]
WantedBy=multi-user.target

Then lets enable our service

sudo systemctl enable bt_power.service

And finally reload systemctl daemon

sudo systemctl daemon-reload

Now all there is left to do is to reboot the Pi and enjoy the fruits of our labours.

sudo reboot

If all went well after your Raspberry Pi reboots you should be able to connect via bluetooth and start blasting some beats.

Don’t forget to disable the internal wifi adapter. How to permanently disable wifi from autostarting at boot is left as an exercise for the reader 🙂

32 Replies to “Making the Raspberry Pi 3 a bluetooth audio receiver”

  1. Low volume problem was corrected by ensuring that the Raspberry Pi was indeed outputting at 100%. To achieve this just type in terminal amixer sset PCM 100%

    Now the Raspberry Pi will be able to output at full volume when volume is also at 100% in the bluetooth device playing the media.

  2. i have just completed the complete process described here and all is working fine.
    The problem I have is that I want to be able to pipe audio over bluetooth from more than one device, but the second device is not able to see the raspberry pi when it scans for bluetooth devices, even after the first device has had its bluetooth radio turned off. I hope I am being clear about what I am looking for here! Any help would be appreciated.

    1. Hi,

      The bluetooth by default is not discoverable. You need to repeat these steps:

      sudo systemctl start bluetooth
      sudo bluetoothctl
      power on
      discoverable on
      exit

      And then pair the new device.

      In consumer products there is a dedicated button for this procedure. For the Pi you would have to build your own button or configure the Pi to be always discoverable.

  3. This’d be my last attempt to get the pi working as a Bluetooth receiver. Will update my results.

    Meanwhile….Should the section ‘Configure, make and install Bluez’ read cd bluez-5.47 instead? There wont be a directory bluez-5.23 at that point?

    1. I’m using USB speakers with the pi and it woked for the first time. Thanks a ton MARKUS JÄRVISALO!

      However, after re boot, BT Connects but doesn’t output sound. I’m needing to run these commands, re-connect and it works. Any ideas to fix?

      sudo systemctl stop bluetooth
      sudo systemctl stop bt_speaker

      sudo systemctl start bluetooth
      sudo bluetoothctl
      power on
      discoverable on
      exit

      cd /opt/bt-speaker
      python bt_speaker.py

  4. Finnally I found this working solution! Thank you very much.

    Only one thing (not sure if it is really necessary, I’m begginner):
    To let bt_power service corretly runnig, it is necessary to make executable the script?

    sudo chmod +x /opt/bt_power/bt_power.sh

    Thank you again!

  5. Been struggling with this for a couple of days now, getting so close!

    Thanks Stefano for your tip, that allowed the services to run for me 🙂

    Now I’m in the same position as Bharath, needing to run that command in order for it to work. I’m guessing it might be a timing issue, no idea how to fix it though. Will keep trying but if anyone has any tips that would be much appreciated!

  6. Just an update to say I’ve had no luck with this. Ended up making a script to run Bharath’s commands, which I can run from the desktop. Looking for a way to remotely trigger it now, but a more elegant solution (the way this is meant to work) would be much appreciated!

    1. I’ll redo all the steps tomorrow to see if I can replicate the problem and see if I can come up with some solution.

      James, are you using Raspbian Stretch Lite or Stretch with Desktop?

      1. Hi Markus, thanks for replying 🙂

        I’m using Stretch with Desktop, let me know if any other information would be helpful!

        1. I’ve been quite busy for the past month and I haven’t had the time nor the energy to dive into this. I can confirm that I had this same issue if I had Stretch with Desktop on my Pi. For my purposes the Lite version works just fine so I have no motivation to try and troubleshoot the Desktop problems.

  7. Hi,

    very good tutorial, thanks 🙂

    A short question: any idea, how I could record the received “sound” to my harddisk on a standard Raspi 3b with an onboard soundcard? Since e.g “arecord” does not seem to support the new “Stretch / Alsa” comination…

    Thanks, Randy

  8. Is there a way to set a passcode and device ID for the pairing? In case you have two Pi’s in different nearby rooms, and don’t want them to be accessible through automatic pairing. So one could be “room1” with pass 1234 and the other “room2” and pass 4321.

  9. I just dont seem to get this to work. Only getting [FAILED] Failed to start bt_power.service.

    When I check status I get.

    Active:failed (result: exit-code)
    Prosses: 435 ExecStart=/opt/bt_power/bt_power.sh (code=exited, status=203/EXEC)

    Where to go from here?
    I’m a complete nuub. So I have a complex new install of newest noobs lite. And followed this to the letter

  10. Thanks for superb instruction, work well on Pi 3B+ out of the box after install BT-Speaker daemon anyway my setup doesn’t compile new BlueZ version , I’m also install raspsotify too. now awaiting POE Hat from foundation to solved my cable wiring now I’m plug my KEF X300A to pi and make it bluetoothable so my PC / Mobile device can access to KEF at anytime.

  11. Thanks for the great instructions.
    I also added this to autoconnect to my phone when no other phone is connected:
    sudo nano /opt/bt_power/bt_autoconfig.sh

    entered this into the script:
    #!/bin/bash
    bluetoothctl << EOF
    connect [enter your MAC add]
    EOF

    and added this line to bt_speaker.py inside the else in the update_discoverable fuction :
    subprocess.call('/opt/bt_power/bt_autoconfig.sh', shell=True)

  12. I have a Problem: I can’t connect to the Pi. On the phone, it adds the Pi to the List of known and paired devices but when I try to connect to it, it does nothing. What am I doing wrong?

    1. You need to have Raspbian Stretch Lite running on the Raspberry Pi 3 Model B.

      If you don’t have lots of experience with linux systems then I suggest you make a clean install of Raspbian Stretch Lite and follow the instructions very carefully.

      I think this error is because you have the full Desktop version of Raspbian installed or you just didn’t follow the instructions carefully enough.

      1. try to run the python command with the word sudo at the beginning
        The error you are having is related to permissions (there is an access denied error in the screen)

  13. This works flawlessly on Raspberry Pi 3 with Raspbian Jessie Lite.

    I didn’t have to disable the wifi adapter, I couldn’t notice any problem in the sound (though I just tested for a few minutes and I do get the message “underrun” in the command line).

    I also didn’t have to add the service to force bluetooth to power on. Setting `AutoEnable = true` in `/etc/bluetooth/main.conf` did the trick.

    Great tutorial, straight to the point with good explanations. Thanks !

  14. i messing around over weeks with Bluez, blue alsa, pulse audio etc. mostly the raspberry will not accepted as A2DP sink. Then it is accepted (by additional pulse audio bluetooth-module installation), no sound. This tutorial is the tutorial what works for me. But why, im confused? What ist the difference you made?(i tried it with Zero W, latest Raspbian stretch and bluez 5.49 and 5.5).

    1. I cannot know what you have done or did not do.

      For this tutorial I read a lot of different but similar Bluetooth audio receiver instructions and then I took all the best parts of each one and then experimented with the settings etc. for quite some time before I got everything perfect. This tutorial did not just fall from the sky for me but I had to do a lot of research and practical work to make this work and I was so proud of myself for getting this to work that I thought I will share it with the world because I saw a lot of people trying to do the same thing but failing with incomplete instructions. And so I made my own instructions which were more complete than the others and had all the steps in them.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.