41

I am looking for a way to configure the Raspberry Pi 3 as bluetooth speaker using Raspbian Jessie. What I mean by as bluetooth speaker is use it to receive audio stream via bluetooth using A2DP and play it via speakers connected to the Raspberry Pi via the audio jack, the HDMI port or USB audio adapter.

Different tutorials are available online but are quite outdated and most of them does not work anymore.

gtatr
  • 514
  • 1
  • 6
  • 14
  • It is unclear what you mean by "as bluetooth speaker" – Milliways May 24 '16 at 09:54
  • 2
    Edited. Hope is clear now – gtatr May 24 '16 at 10:00
  • 2
    Perfectly clear to me, I'm interested in reading any real answers. – Burt_Harris May 26 '16 at 19:12
  • The voted solution is a similar route I ended going with. However, I have a github repo which will set this up for you on a fresh install of raspbian Jessie Lite(unsure if it works without a little config for Jessie with pixel) simply follow the install instructions here: https://github.com/bareinhard/super-simple-raspberry-Pi-audio-receiver-install . The main problem I see with existing solutions is that they use pulseaudio5 by default. This will compile pa6 and get rid of a lot of playback issues that pa5 experiences. – Brett Reinhard Dec 10 '17 at 02:07

4 Answers4

31

I have been on this project after while (to help my friend doing their paper for graduating) and find the online project doing just fine (although the pi processing the audio is quite lagging the pi, and voltage drop make it freeze as the only way to make it reboot is to unplugged the power cable).

This is the step that I've been working on and it works on raspberry pi 3.

1. Download the required package

This project depend on pulseaudio so grab it and installing by typing:

sudo apt-get update && sudo apt-get install bluez pulseaudio-module-bluetooth python-gobject python-gobject-2 bluez-tools udev

i rather update the firmware of raspberry first before installing them because i have problem with rpi-bluetooth package so i do:

sudo rpi-update

and make it install and advance to next step.

2. Edit Configuration and applied it

First add pi username to the group pulseaudio with

sudo usermod -a -G lp pi

create new config under /etc/bluetooth/audio.conf using text editor and add the following line

[General]:
Enable=Source,Sink,Media,Socket

edit file /etc/bluetooth/main.confusing your preferred text editor (I'm using nano).

Set Bluetooth Class, Modify the following line to:

 Class = 0x00041C

0x000041C means that the rpi bluetooth support A2DP protocol.

change /etc/pulse/daemon.conf add / modify (don't forget to check the code thoroughly before adding them), and change

resample-method = trivial

you can using any method you like, i personally using speex-float-3 for reference you can see this link

start pulseaudio service with:

pulseaudio -D

we are going to use ragusa87 script to automate the bluetooth source to audio sink. First please add new configuration to udev init.d by editing file /etc/udev/rules.d/99-input.rules and add this to the file

SUBSYSTEM="input", GROUP="input", MODE="0660"
KERNEL=="input[0-9]*", RUN+="/usr/lib/udev/bluetooth"

add folder udev to /usr/lib by using mkdir

sudo mkdir /usr/lib/udev && cd /usr/lib/udev

and add this to the file bluetooth (credits ragusa87)

#!/bin/bash
# This script is called by udev when you link a bluetooth device with your computer
# It's called to add or remove the device from pulseaudio
#
#

# Output to this file
LOGFILE="/var/log/bluetooth_dev"

# Name of the local sink in this computer
# You can get it by calling : pactl list short sinks
# AUDIOSINK="alsa_output.platform-bcm2835_AUD0.0.analog-stereo"
AUDIOSINK="alsa_output.0.analog-stereo.monitor"
# User used to execute pulseaudio, an active session must be open to avoid errors
USER="pi"

# Audio Output for raspberry-pi
# 0=auto, 1=headphones, 2=hdmi. 
AUDIO_OUTPUT=1

# If on, this computer is not discovearable when an audio device is connected
# 0=off, 1=on
ENABLE_BT_DISCOVER=1

echo "For output see $LOGFILE"

## This function add the pulseaudio loopback interface from source to sink
## The source is set by the bluetooth mac address using XX_XX_XX_XX_XX_XX format.
## param: XX_XX_XX_XX_XX_XX
## return 0 on success
add_from_mac(){
  if [ -z "$1" ] # zero params
    then
        echo "Mac not found" >> $LOGFILE
    else
        mac=$1 # Mac is parameter-1

        # Setting source name
        bluez_dev=bluez_source.$mac
        echo "bluez source: $mac"  >> $LOGFILE

        # This script is called early, we just wait to be sure that pulseaudio discovered the device
        sleep 1
        # Very that the source is present
        CONFIRM=`sudo -u pi pactl list short | grep $bluez_dev`
        if [ ! -z "$CONFIRM" ]
        then
            echo "Adding the loopback interface:  $bluez_dev"  >> $LOGFILE
            echo "sudo -u $USER pactl load-module module-loopback source=$bluez_dev sink=$AUDIOSINK rate=44100 adjust_time=0"  >> $LOGFILE

            # This command route audio from bluetooth source to the local sink..
            # it's the main goal of this script
            sudo -u $USER pactl load-module module-loopback source=$bluez_dev sink=$AUDIOSINK rate=44100 adjust_time=0  >> $LOGFILE
            return $?
        else
            echo "Unable to find a bluetooth device compatible with pulsaudio using the following device: $bluez_dev" >> $LOGFILE
            return -1
        fi
    fi
}

## This function set volume to maximum and choose the right output
## return 0 on success
volume_max(){
    # Set the audio OUTPUT on raspberry pi
    # amixer cset numid=3 <n> 
    # where n is 0=auto, 1=headphones, 2=hdmi. 
    amixer cset numid=3 $AUDIO_OUTPUT  >> $LOGFILE

    # Set volume level to 100 percent
    amixer set Master 100%   >> $LOGFILE
    pacmd set-sink-volume 0 65537   >> $LOGFILE
    return $?
}

## This function will detect the bluetooth mac address from input device and configure it.
## Lots of devices are seen as input devices. But Mac OS X is not detected as input
## return 0 on success
detect_mac_from_input(){
    ERRORCODE=-1

    echo "Detecting mac from input devices" >> $LOGFILE
    for dev in $(find /sys/devices/virtual/input/ -name input*)
    do
        if [ -f "$dev/name" ]
        then
            mac=$(cat "$dev/name" | sed 's/:/_/g')
            add_from_mac $mac

            # Endfor if the command is successfull
            ERRORCODE=$?
            if [ $ERRORCODE -eq 0]; then
                return 0
            fi
        fi
    done
    # Error
    return $ERRORCODE
}
## This function will detect the bt mac address from dev-path and configure it.
## Devpath is set by udev on device link
## return 0 on success
detect_mac_from_devpath(){
    ERRORCODE=-1
    if [ ! -z "$DEVPATH" ]; then
        echo "Detecting mac from DEVPATH"  >> $LOGFILE
        for dev in $(find /sys$DEVPATH -name address)
        do
            mac=$(cat "$dev" | sed 's/:/_/g')
            add_from_mac $mac

            # Endfor if the command is successfull
            ERRORCODE=$?
            if [ $ERRORCODE -eq 0]; then
                return 0
            fi

        done
        return $ERRORCODE;
    else
        echo "DEVPATH not set, wrong bluetooth device? " >> $LOGFILE
        return -2
    fi
    return $ERRORCODE
}


## Detecting if an action is set
if [ -z "$ACTION" ]; then
    echo "The script must be called from udev." >> $LOGFILE
    exit -1;
fi
## Getting the action
ACTION=$(expr "$ACTION" : "\([a-zA-Z]\+\).*")

# Switch case
case "$ACTION" in
"add")

    # Turn off bluetooth discovery before connecting existing BT device to audio
    if [ $ENABLE_BT_DISCOVER -eq 1]; then
        echo "Stet computer as hidden" >> $LOGFILE
        hciconfig hci0 noscan
    fi

    # Turn volume to max
    volume_max

    # Detect BT Mac Address from input devices
    detect_mac_from_input
    OK=$?

    # Detect BT Mac address from device path on a bluetooth event
    if [ $OK != 0 ]; then
        if [ "$SUBSYSTEM" == "bluetooth" ]; then
            detect_mac_from_devpath
            OK=$?
        fi
    fi

    # Check if the add was successfull, otherwise display all available sources
    if [ $OK != 0 ]; then
        echo "Your bluetooth device is not detected !" >> $LOGFILE
        echo "Available sources are:" >> $LOGFILE
        sudo -u $USER pactl list short sources >> $LOGFILE
    else
        echo "Device successfully added " >> $LOGFILE
    fi
    ;;

"remove")
    # Turn on bluetooth discovery if device disconnects
    if [ $ENABLE_BT_DISCOVER -eq 1]; then
        echo "Set computer as visible" >> $LOGFILE
        sudo hciconfig hci0 piscan
    fi
    echo "Removed" >> $LOGFILE
    ;;

#   
*)
    echo "Unsuported action $action" >> $LOGFILE
    ;;
esac
echo "--" >> $LOGFILE

PLEASE NOTE that your AUDIOSINK might different from mine, check it before using pactl list short sinks

make the script executable by inputting this code

chmod 777 bluetooth 

plug in headset to test whether the audio jack working and test with

 aplay /usr/share/sounds/alsa/Front_Center.wav

or you can set the default audio routing with

sudo amixer cset numid=3 n

where n could be: 0 = auto 1 = jack 2 = hdmi

3. Pair and Connect the audio

go to terminal and type bluetoothctl. First activate bluetooth with power on and then agent on, set the default agent that you've been editing before with default-agent, and then set discoverable mode and pair mode on with discoverable on; pairable on. You should see raspberrypi bluetooth on your phone or laptop and you can pair it on the phone by clicking it and touch pair. On the terminal you type y. Back to the terminal, you connect to the phone by type connect xx:xx:xx:xx:xx:xx where xx:xx:xx:xx:xx:xx is you phone bluetooth mac address. and don't forget to trust with trust xx:xx:xx:xx:xx:xx where xx:xx:xx:xx:xx:xx is your phone bluetooth mac address And voila you have bluetooth amplifier (or whatever the name is) by using raspberry.

4. Conclusion

after trying and experimenting, i found out the audio quality is low and i rather not using it as the raspberry will be freeze if you using it with the song being streaming to the raspberry. I advice to use UPNP speaker project by using gmediarenderer. The audio is superb and there's no delay and scatter sound and it can play lossless audio file (flac, wav, dll). This is the detailed how to setup it

reference: jobpassion's tutorial; ragusa's script; related work;

xdhe
  • 526
  • 4
  • 10
  • I am not able to execute `sudo service pulseaudio restart`, I am getting `Failed to restart pulseaudio.service: Unit pulseaudio.service failed to load: No such file or directory. ` – gtatr May 30 '16 at 21:21
  • Moreover, with `bluetoothctl` when I do `connect xx:xx:xx:xx:xx:xx` I get `Failed to connect: org.bluez.Error.Failed` using either my phone or laptop – gtatr May 30 '16 at 21:30
  • What os you've using? The only os that support raspberry pi 3 onboard bluetooth is raspbian Jessie and Ubuntu Mate >16.04. On the Ubuntu Mate bluetooth a2dp is already present, so you've might check it on Bluetooth Manager. – xdhe May 31 '16 at 04:56
  • If you've already tried any online tutorial and mess up, I think it's best to reinstall and purging configuration of the packages. I've messing with the Bluetooth packages by installing manually 'rpi-bluetooth' package and the Bluetooth is not working. So I've reflash raspbian image and it works just fine although the sound is not pleasant IMO. – xdhe May 31 '16 at 05:08
  • I am using a freshly installed raspbian Jessie, and I was following your instructions step by step, perhaps there is a missing step coming from a freshly installed OS. I might give Ubuntu Mate a try – gtatr May 31 '16 at 10:18
  • are you sure that package pulseaudio is already installed? maybe sudo apt-get install pulseaudio && sudo service bluetooth start might help. – xdhe May 31 '16 at 10:24
  • Yes, pulseaudio is already installed. I can start it by `pulseaudio --start` but when I load the module `module-bluetooth-discover` I'm getting `Failure: module initialization failed `. About the bluetooth: after starting it, `sudo service bluetooth status` reports `Unknown key Enable in main.conf` and `Sap driver initialization failed. sap-server: Operation not permitted (1)` – gtatr May 31 '16 at 10:34
  • hmm strange, did the phone/laptop discover raspberrypi bluetooth as Wireless Headset? Can i see your main.conf (upload it to pastebin) and i try to compare it with mine. – xdhe May 31 '16 at 10:41
  • Let us [continue this discussion in chat](http://chat.stackexchange.com/rooms/40540/discussion-between-g-tataranni-and-xdhe). – gtatr May 31 '16 at 11:17
  • please check the answer, i've already fixed it and it should work now. – xdhe May 31 '16 at 15:56
  • `/etc/udev/rules.d/99-input.rules` doesn't exist on my jesse install. Instead I have `/etc/udev/rules.d/99-com.rules` - Do I use this file instead? – square_eyes Jan 02 '17 at 07:52
  • I used it, and while my initial connect worked streaming audio it didn't connect after a re-boot. – square_eyes Jan 02 '17 at 09:11
  • @xdhe Does speex-float-3 work without stutter for you? My Pi3 can play stutterless audio upto speex-float-1. – Karthik Nishanth Jan 29 '17 at 13:53
  • @KarthikNishanth i used ffmpeg, working fine in my case :-) – xdhe Jan 30 '17 at 06:06
  • @xdhe I set it as ffmpeg and pulseaudio keeps crashing after some time (no auto respawn). Do you run it in system mode/user mode? What are your cmd line arguments? Thanks btw. – Karthik Nishanth Jan 30 '17 at 11:18
  • This works well also on the PI 1 (with bt dongle). Is it possible to do the same without pulseaudio? bt -> alsa? – niry May 21 '17 at 02:01
  • I have tried undoing these instructions I had done months ago and yet I still am unable to un-brick my raspberry pi that only boots to raspberry pi desktop... I would not recommend these instructions to anyone especially since you can get a dedicated bluetooth to speaker device for much less than the price of a Pi. – NoBugs Jul 19 '17 at 06:05
  • @NoBugs agreed, the op stated that he need this 'hack' to built something bigger. If you trying to achieved what the so-called bluetooth amplifier stick, this is not the best method. Instead use the bluetooth amplifier if you looking for quality. – xdhe Jul 22 '17 at 05:10
  • Quality seems much better on USB audio than on the jack. I tested both with headphones on the RPI's analog jack and with USB headphones: the quality on the analog jack was pretty bad, with a lot of stuttering... however on the USB headphones I didn't encounter any stutter. – Dan Mirescu Mar 20 '18 at 14:35
21

Here is an alternate solution that doesn't rely on PulseAudio: https://github.com/lukasjapan/bt-speaker

Install on raspbian as root with:

curl -s https://raw.githubusercontent.com/lukasjapan/bt-speaker/master/install.sh | bash

It will start a bluetooth speaker daemon that automatically accepts a single client for A2DP/AVRCP and pipes the audio stream directly to ALSA.

Lukas
  • 356
  • 2
  • 4
  • Security reminder: I wrote the script by myself so I can assure you it is safe but please verify the contents by yourself – Lukas Mar 15 '17 at 00:56
  • nice! I will try to test this in the next days – gtatr Mar 16 '17 at 19:45
  • 2
    i was trying your solution, and it worked but the audio stuck every other second. why is this happening? – wolfram77 Nov 15 '17 at 18:05
  • Most likely the Wifi issue: https://github.com/lukasjapan/bt-speaker/issues/4 – Lukas Nov 25 '17 at 06:05
  • 1
    By far the best solution. Easy and straight forward. The only "issue" is a slight delay (around 500ms) which makes watching moving not pleasant. – Bin4ry Dec 07 '19 at 21:50
  • Once installed, could BT be used for other purposes? Is it enough to run `service bt_speaker stop`? – Dmitry Grigoryev Apr 14 '20 at 07:01
3

I have written succinct instructions for the Raspberry Pi 3 on my blog. Most instructions online are for older versions of Debian/Xbian. Here are the instructions that I have tested and are working on Raspberry Pi 3 with Xbian.

  1. Start by install / updating all the packages

    sudo apt-get update
    sudo apt-get upgrade
    sudo apt-get install pulseaudio-module-bluetooth bluez-tools
    
  2. Add users to groups. This is very important. If using any other distro, replace ‘xbian’ with your username.

    sudo gpasswd -a xbian pulse
    sudo gpasswd -a xbian lp
    sudo gpasswd -a pulse lp
    sudo gpasswd -a xbian audio
    sudo gpasswd -a pulse audio
    
  3. Set up PulseAudio & Bluetooth Device Class

    sudo sh -c "echo 'extra-arguments = --exit-idle-time=-1 --log-target=syslog' >> /etc/pulse/client.conf"
    sudo hciconfig hci0 up
    sudo hciconfig hci0 class 0x200420
    sudo reboot
    

The Bluetooth service/device class 0x200420 mean the device is set up for Car Audio. See this link to explore more Bluetooth Class options.

  1. To pair with a device, we will need to use the “bluetoothctl” tool.

    sudo bluetoothctl
    
  2. Set the agent to KeyboardOnly and make it default. This needs to be done once only. Inside bluetoothctl, run the following commands:

    agent KeyboardOnly
    default-agent
    
  3. Turn on bluetooth on your phone/tablet and make sure it is discoverable. Run the following commands inside bluetoothctl:

    scan on
    pair xx:xx:xx:...
    trust xx:xx:xx:...
    exit
    

    xx:xx:xx:.. is the MAC address of your handset/device. After running ‘scan on’, wait a minute for your device to show up along with it’s MAC address. After running ‘pair xx:xx:xx:..’ check your device and accept the incoming connection. Do the same on terminal by typing yes.

  4. Now connect to the Raspberry Pi from your handset and it should connect as an audio device. All audio played through the device should now be output using Raspberry Pi’s HDMI or Analog out depending on your Pi’s configuration.

  5. If the connection fails, try again, sometimes it takes 2 attempts.

  • Thanks for taking the time to answer. Link-only answers are [discouraged](http://raspberrypi.stackexchange.com/help/how-to-answer) as there's no telling what's at the other end - if the linked article changes or disappears, so does this answer. Can you summarise the important points? – goobering Jun 22 '16 at 09:59
  • @goobering: Post updated. I am not too familiar with the formatting on Stack sites but I have done it to best of my ability. Thank you for taking the time to review my answer. Have a great day – Abdul Mueid Jun 22 '16 at 11:33
  • 1
    What did you do to fix the choppy audio? – NoBugs Feb 06 '17 at 04:05
  • It's super choppy. Do we have to overclock the pi ? – b-ak Feb 11 '17 at 16:01
  • While I appreciate the howto, it is so choppy... how on earth can they sell working Bluetooth receiver for $5 where a $35 quadcore Raspberry pi isn't quite powerful enough to do it??? – NoBugs Feb 18 '17 at 05:14
  • I have successfully paired my raspberry with my Samsung S4. However I cannot select it for playback. Another Bluetooth receiver works. Can you give more information what should be accomplished after each step in order to understand which step fails? – Frank Breitling Mar 25 '17 at 16:07
  • 1
    Abdul's instructions work perfectly, however the audio output through BT speaker is very choppy. This isn't acceptable audio quality in any case. PI native audio through Pulseaudio is very crappy. Time for a far better solution than Bluetooth. – Don Allen May 26 '17 at 17:11
1

Before you launch off down that route, have you considered the notoriously poor quality of the RPi 3.5mm audio jack output?

Sound output of the Raspberry Pi

This may be why you can't find an up-to-date tutorial.

To be fair, the other reason might be that a decent pair of speakers is no less expensive than a decent Bluetooth speaker. I wouldn't go down this route, unless your intention is to also invest in a USB soundcard (not expensive, but your total price is starting to increase now). Or, maybe you plan on using the HDMI output? It's really very good.

How about this one? All the components should be readily available.

http://www.instructables.com/id/Turn-your-Raspberry-Pi-into-a-Portable-Bluetooth-A/

This was my first RPi project. I haven't looked very thoroughly, but I believe the MPD component can be used to stream Bluetooth to the RPi. I'll leave you to do that research.

http://www.bobrathbone.com/raspberrypi_radio.htm

KDM
  • 598
  • 5
  • 17
  • I agree with you on the fact that there are better ready solutions out there, and not so expensive, but I want this to be part of a larger project – gtatr May 22 '16 at 10:58
  • I only speculate on the reasons for the elderly instructions. See other notes, though, on potential solutions. Look at the MPD daemon. I may be mistaken, but I think it can stream Bt. Could use a little more detail. If you're going to use the 3.5mm audio jack, it will probably work fine at 75%, but you'll need to rely on an external amplifier for volume control. – KDM May 22 '16 at 13:04
  • btw I tried that tutorial, plus almost any other tutorial online but with no success – gtatr May 22 '16 at 17:21