Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Headless A2DP Audio Streaming on Raspbian Stretch

About

This gist will show how to setup Raspbian Stretch as a headless Bluetooth A2DP audio sink. This will allow your phone, laptop or other Bluetooth device to play audio wirelessly through a Rasperry Pi.

Motivation

A quick search will turn up a plethora of tutorials on setting up A2DP on the Raspberry Pi. However, I felt this gist was necessary because this solution is:

  • Automatic & Headless - Once setup, the system is entirely automatic. No user iteration is required to pair, connect or start playback. Therefore the Raspberry Pi can be run headless.
  • Simple - This solution has few dependencies, readily available packages and minimal configuration.
  • Up to date - As of December 2017. Written for Raspbian Stretch & Bluez 5.43

Prerequisites

  • Raspbian Stretch - I used the Lite version as this is a headless setup. See the official guide if you need help.
  • Bluez-alsa - Available in the Raspbian package repo. This software allows us to stream A2DP audio over Bluetooth without PulseAudio.
  • Raspberry Pi with Bluetooth - The Raspberry Pi 3 has integrated Bluetooth, however there is a known bug when the WiFi is used simultaneously. Cheap USB Bluetooth dongles work equally well.

Disabling Integrated Bluetooth

If you are using a separate USB Bluetooth dongle, disable the integrated Bluetooth to prevent conflicts.

To disable the integrated Bluetooth add the following

# Disable onboard Bluetooth
dtoverlay=pi3-disable-bt

to /boot/config.txt and execute the following command

sudo systemctl disable hciuart.service

Initial Setup

First make sure the system is up to date using the following commands.

sudo apt-get update
sudo apt-get upgrade

Then reboot the Pi to ensure the latest kernel is loaded.

Now install the required packages.

sudo apt-get install bluealsa python-dbus

Make Bluetooth Discoverable

Normally a Bluetooth device is only discoverable for a limited amount of time. Since this is a headless setup we want the device to always be discoverable.

  1. Set the DiscoverableTimeout in /etc/bluetooth/main.conf to 0
# How long to stay in discoverable mode before going back to non-discoverable
# The value is in seconds. Default is 180, i.e. 3 minutes.
# 0 = disable timer, i.e. stay discoverable forever
DiscoverableTimeout = 0
  1. Enable discovery on the Bluetooth controller
sudo bluetoothctl
power on
discoverable on
exit

Install The A2DP Bluetooth Agent

A Bluetooth agent is a piece of software that handles pairing and authorization of Bluetooth devices. The following agent allows the Raspberry Pi to automatically pair and accept A2DP connections from Bluetooth devices. All other Bluetooth services are rejected.

Copy the included file a2dp-agent to /usr/local/bin and make the file executable with

sudo chmod +x /usr/local/bin/a2dp-agent

Testing The Agent

Before continuing, verify that the agent is functional. The Raspberry Pi should be discoverable, pairable and recognized as an audio device.

Note: At this point the device will not output any audio. This step is only to verify the Bluetooth is discoverable and bindable.

  1. Manually run the agent by executing
sudo /usr/local/bin/a2dp-agent
  1. Attempt to pair and connect with the Raspberry Pi using your phone or computer.
  2. The agent should output the accepted and rejected Bluetooth UUIDs
A2DP Agent Registered
AuthorizeService (/org/bluez/hci0/dev_94_01_C2_47_01_AA, 0000111E-0000-1000-8000-00805F9B34FB)
Rejecting non-A2DP Service
AuthorizeService (/org/bluez/hci0/dev_94_01_C2_47_01_AA, 0000110d-0000-1000-8000-00805f9b34fb)
Authorized A2DP Service
AuthorizeService (/org/bluez/hci0/dev_94_01_C2_47_01_AA, 0000111E-0000-1000-8000-00805F9B34FB)
Rejecting non-A2DP Service

If the Raspberry Pi is not recognized as a audio device, ensure that the bluealsa package was installed as part of the Initial Setup

Install The A2DP Bluetooth Agent As A Service

To make the A2DP Bluetooth Agent run on boot copy the included file bt-agent-a2dp.service to /etc/systemd/system. Now run the following command to enable the A2DP Agent service

sudo systemctl enable bt-agent-a2dp.service

Thanks to @matthijskooijman for fixing up some issues in the Bluetooth Agent service.

Bluetooth devices should now be able to discover, pair and connect to the Raspberry Pi without any user intervention.

Testing Audio Playback

Now that Bluetooth devices can pair and connect with the Raspberry Pi we can test the audio playback.

The tool bluealsa-aplay is used to forward audio from the Bluetooth device to the ALSA output device (sound card).

Execute the following command to accept A2DP audio from any connected Bluetooth device.

bluealsa-aplay -vv 00:00:00:00:00:00

Play a song on the Bluetooth device and the Raspberry Pi should output audio on either the headphone jack or the HDMI port. See this guide for configuring the audio output device of the Raspberry Pi.

Install The Audio Playback As A Service

To make the audio playback run on boot copy the included file a2dp-playback.service to /etc/systemd/system. Now run the following command to enable A2DP Playback service

sudo systemctl enable a2dp-playback.service

Reboot and enjoy!

Low Volume Output

If you are experiencing low volume output, run alsamixer and increase the volume of the Pi's soundcard.

#!/usr/bin/python
from __future__ import absolute_import, print_function, unicode_literals
import sys
import dbus
import dbus.service
import dbus.mainloop.glib
try:
from gi.repository import GObject
except ImportError:
import gobject as GObject
AGENT_INTERFACE = "org.bluez.Agent1"
AGENT_PATH = "/test/agent"
class Rejected(dbus.DBusException):
_dbus_error_name = "org.bluez.Error.Rejected"
class Agent(dbus.service.Object):
exit_on_release = True
def set_exit_on_release(self, exit_on_release):
self.exit_on_release = exit_on_release
@dbus.service.method(AGENT_INTERFACE,
in_signature="", out_signature="")
def Release(self):
print("Release")
if self.exit_on_release:
mainloop.quit()
@dbus.service.method(AGENT_INTERFACE,
in_signature="os", out_signature="")
def AuthorizeService(self, device, uuid):
print("AuthorizeService (%s, %s)" % (device, uuid))
if uuid == "0000110d-0000-1000-8000-00805f9b34fb":
print("Authorized A2DP Service")
return
print("Rejecting non-A2DP Service")
raise Rejected("Connection rejected")
@dbus.service.method(AGENT_INTERFACE,
in_signature="o", out_signature="s")
def RequestPinCode(self, device):
print("RequestPinCode (%s)" % (device))
return "0000"
@dbus.service.method(AGENT_INTERFACE,
in_signature="o", out_signature="u")
def RequestPasskey(self, device):
print("RequestPasskey (%s)" % (device))
return dbus.UInt32("password")
@dbus.service.method(AGENT_INTERFACE,
in_signature="ouq", out_signature="")
def DisplayPasskey(self, device, passkey, entered):
print("DisplayPasskey (%s, %06u entered %u)" %
(device, passkey, entered))
@dbus.service.method(AGENT_INTERFACE,
in_signature="os", out_signature="")
def DisplayPinCode(self, device, pincode):
print("DisplayPinCode (%s, %s)" % (device, pincode))
@dbus.service.method(AGENT_INTERFACE,
in_signature="ou", out_signature="")
def RequestConfirmation(self, device, passkey):
print("RequestConfirmation (%s, %06d)" % (device, passkey))
return
@dbus.service.method(AGENT_INTERFACE,
in_signature="o", out_signature="")
def RequestAuthorization(self, device):
print("RequestAuthorization (%s)" % (device))
raise Rejected("Pairing rejected")
@dbus.service.method(AGENT_INTERFACE,
in_signature="", out_signature="")
def Cancel(self):
print("Cancel")
if __name__ == '__main__':
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
agent = Agent(bus, AGENT_PATH)
obj = bus.get_object("org.bluez", "/org/bluez");
manager = dbus.Interface(obj, "org.bluez.AgentManager1")
manager.RegisterAgent(AGENT_PATH, "NoInputNoOutput")
print("A2DP Agent Registered")
manager.RequestDefaultAgent(AGENT_PATH)
mainloop = GObject.MainLoop()
mainloop.run()
[Unit]
Description=A2DP Playback
After=bluealsa.service syslog.service
Requires=bluealsa.service
[Service]
ExecStartPre=/bin/sleep 3
ExecStart=/usr/bin/bluealsa-aplay --profile-a2dp 00:00:00:00:00:00
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=A2DP-Playback
User=pi
[Install]
WantedBy=multi-user.target
[Unit]
Description=A2DP Bluetooth Agent
After=bluetooth.service
Wants=bluetooth.service
[Service]
ExecStartPre=/bin/sh -c "echo discoverable on | bluetoothctl"
ExecStart=/usr/bin/python -u /usr/local/bin/a2dp-agent
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=A2DP-Agent
[Install]
WantedBy=bluetooth.service
@Phil171

This comment has been minimized.

Copy link

commented Mar 19, 2018

Hi Mill 1000,
I don't know where to start ...
Brand new on RPI.
I have a RPi 3, Debian Stretch updated and upgraded, I followed all your tutorial but I can not get a sound on my headphones by reading an MP3 or a video with OMXPlayer or TBOPlayer.
he headset is connected, recognized, associated, but no sound, and if I ask to be in A2DP, error with A2DP sink.
I've tried to disconnect wlan0 and using wifi dongle on wlan1 without success.
I occurs a problem when "Testing The Agent", sudo /usr/local/bin/a2dp-agent returns :
"A2DP Agent Registered"
And that's all... for a long long time.
Of course, I've installed all the stuff by :
sudo apt-get install blueman pulseaudio pavucontrol pulseaudio-module-bluetooth
Reboot, same problem but now, Bluetooth Devices don't want to open.
If you can help a newbie in RPi...
Sorry for my poor english,
Best Regards from France,
Philippe

@allebb

This comment has been minimized.

Copy link

commented Mar 20, 2018

Hey mill1000,

Thanks for the guide on how to get this working and although I've successfully been able to make this work with my iPhone and my daughters iPhone I cannot seem to get my MacBook Pro or my Ubuntu desktop to output sound any sound - Am I missing something?

Looking at the error logs (syslog) on the RaspberryPi it seems that when my Mac connects it is rejected with a messaging saying "Handsfree device not compatible". The MacBook then disconnects from Bluetooth after a few seconds and the output sound device ("raspberrypi") never appears in my Sound settings? - Do you have any advice?

Update: I can confirm that it's working on Windows 10 based desktop... it would be really great if I could get it working on my Ubuntu Linux 17.10 desktop and my MacBook Pro (running latest version of OSX) - Any idea's would be much appreciated! - I can also confirm that I'm using the same external Asus BT400 Bluetooth adaptor on both my Windows desktop and my Linux Desktop.

Many thanks in advance,
Bobby

@davthomaspilot

This comment has been minimized.

Copy link

commented Apr 3, 2018

Thanks for the guide!

It's working for me on an RPI-zero W with the latest stretch-lite. However, when I ran

sudo /usr/local/bin/a2dp-agent

I just got
A2DP Agent Registered

I didn't get any AuthorizeService records. Still, I was able to connect from my Ipad and stream audio to the pi.

I had used bluetoothctl to turn on discovery, pair, and trust the Ipad Mac address before finding this guide. I was able to connect, but never hear any audio until I followed these steps. Still, maybe I need to start over?

It's working fine, but I'd like to automatically connect rather than having to do it from the Ipad. Is that possible?

@davthomaspilot

This comment has been minimized.

Copy link

commented Apr 3, 2018

Ok, so I figured out I can use a script with bluetoothctl and the connect command to auto-connect to a specific macaddr.

Does it make sense to modify the agent to call this script?

Or, is there a way to call the script whenever the bluetooth device with the specified macaddr is in range?

Sorry for my ignorance...

@davthomaspilot

This comment has been minimized.

Copy link

commented Apr 3, 2018

Ok, I found a thread that showed how to do it by running a script that continually checks

ls /dev/input/event0

When that exists, a connection is made using bluetoothctl and "connect" command. Seems to work fine.

But I'm thinking that a better way would be to modify the agent?

@herrwusel

This comment has been minimized.

Copy link

commented Apr 4, 2018

I can't install python-dbus. My raspberry is telling me that there isn't package called python-dbus. Am I missing something?

@davthomaspilot

This comment has been minimized.

Copy link

commented Apr 4, 2018

Everything worked yesterday.

I wanted to make sure I could repeat from scratch. So, today, I started fresh with the same stretch-lite image. I did the apt-get update and upgrade. But then neither bluealso nor the python-dbus packages could be installed:

> sudo apt-get install bluealsa
> Reading package lists... Done
> Building dependency tree
> Reading state information... Done
> Some packages could not be installed. This may mean that you have
> requested an impossible situation or if you are using the unstable
> distribution that some required packages have not yet been created
> or been moved out of Incoming.
> The following information may help to resolve the situation:
> 
> The following packages have unmet dependencies:
>  bluealsa : Depends: libsbc1 but it is not installable
> E: Unable to correct problems, you have held broken packages.
> 
sudo apt-get install python-dbus
Reading package lists... Done
Building dependency tree
Reading state information... Done
Package python-dbus is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source

E: Package 'python-dbus' has no installation candidate

@davthomaspilot

This comment has been minimized.

Copy link

commented Apr 4, 2018

I wonder if there's a way to do an "un upgrade"?

@davthomaspilot

This comment has been minimized.

Copy link

commented Apr 4, 2018

Tried again, now the packages installed. Maybe the servers were down for a bit.

@herrwusel

This comment has been minimized.

Copy link

commented Apr 5, 2018

@davthomaspilot: I got it working now. If you need any assistance I might help you.

@d-koppenhagen

This comment has been minimized.

Copy link

commented Apr 30, 2018

Hey guys, any news here? I run into the same issue (script stucks at "A2DP Agent Registered") when following this guide.

@gattohub

This comment has been minimized.

Copy link

commented May 14, 2018

Hola. hello. Thanks for this. Done and enjoying with Dietpi distro. For those who are interested, I had to change the user in the last step: from "pi" to "root"
Saludos.

@cdlenfert

This comment has been minimized.

Copy link

commented May 14, 2018

@d-koppenhagen I got stuck at the same point. I realized the bluetooth discoverable command didn't take, so I ran it again.
sudo bluetoothctl discoverable on
After that the pi shows up as a device that can be connected to, but then I'm unable to get audio output through my USB Sound card (I'm on a Pi Zero).

@oss001

This comment has been minimized.

Copy link

commented May 22, 2018

Just wanted to say thank you for this! There are so many guides that are outdated or are overly complicated and just don't work. Followed your steps and this worked perfectly!

@Cpt-Hook

This comment has been minimized.

Copy link

commented May 24, 2018

Hi, thank you for your amaying and working tutorial. I managed to get it to work, although after some time, when I try to connect and play some music, it does not work. I can connect, but no sound is playing.

All I have to do to get it to work is to restart the a2dp-playback.service:
sudo systemctl restart a2dp-playback.service
After that, it is working correctly again.

If i try command:
sudo systemctl status a2dp-playback.service
I get the following output:
● a2dp-playback.service - A2DP Playback Loaded: loaded (/etc/systemd/system/a2dp-playback.service; enabled; vendor preset: enabled) Active: failed (Result: exit-code) since Thu 2018-05-24 14:42:51 CEST; 6h ago Process: 22262 ExecStart=/usr/bin/bluealsa-aplay --profile-a2dp 00:00:00:00:00:00 (code=exited, status=1/FAILURE) Process: 22256 ExecStartPre=/bin/sleep 3 (code=exited, status=0/SUCCESS) Main PID: 22262 (code=exited, status=1/FAILURE)
May 24 14:01:05 raspberrypi systemd[1]: Starting A2DP Playback... May 24 14:01:08 raspberrypi systemd[1]: Started A2DP Playback. May 24 14:42:51 raspberrypi systemd[1]: a2dp-playback.service: Main process exited, code=exited, status=1/FAILURE May 24 14:42:51 raspberrypi systemd[1]: a2dp-playback.service: Unit entered failed state. May 24 14:42:51 raspberrypi systemd[1]: a2dp-playback.service: Failed with result 'exit-code'.

Do you know why it does that? I use the new Raspberry Pi 3b+. I am no linux expert and just learning the ropes.

@jonathanschneider

This comment has been minimized.

Copy link

commented May 28, 2018

I am trying to use the Raspberry Pi as a Bluetooth receiver for my Echo Dot. I paired and trusted the Echo using bluetoothctl so I did not install the a2dp-agent but installed the a2dp-playback service.
When I establish the connection from the Echo, it sends its audio to the Raspberry Pi as desired. However, when I establish the connection from the Raspberry Pi, the Echo continues to use its internal speaker as output.
The Raspberry Pi turns on my amplifier so I also want it to connect to the Echo automatically without me having to establish the connection from the Echo.
Is it possible that the Raspberry Pi advertises a different class or service when it establishes the connection? Or does the a2dp-playback service not trigger when the Raspberry Pi establishes the connection? I'd be thankful for any ideas.

@p7810456v2

This comment has been minimized.

Copy link

commented Jun 7, 2018

Is there a way to get the song name from this software in order to display it somewhere? I'm trying to make a Bluetooth audio streaming device that can display the song name and other information on an LCD screen.

@annagat

This comment has been minimized.

Copy link

commented Jun 8, 2018

Hi All,

I was able to get this working but the problem is after disconnecting and then connecting back there is no sound output anymore. I think the "bluealsa-aplay" is crushing during disconnect, not sure what's the problem. I tried running manually and below is the output when I disconnect.

pi@raspberrypi:~ $ bluealsa-aplay -vv 00:00:00:00:00:00 Selected configuration: HCI device: hci0 PCM device: default PCM buffer time: 500000 us PCM period time: 100000 us Bluetooth device(s): ANY Profile: A2DP Used configuration for 94:7B:E7:12:D8:5D: PCM buffer time: 500000 us (88200 bytes) PCM period time: 100045 us (17648 bytes) Sampling rate: 44100 Hz Channels: 2 bluealsa-aplay: Couldn't read event: Bad message

@p7810456v2

This comment has been minimized.

Copy link

commented Jun 9, 2018

This tutorial was very good, but after I rebooted, the audio would not work. Running "bluealsa-aplay -vv 00:00:00:00:00:00" gave the error "Couldn't open PCM: Device or resource busy."

Edit: Fixed by putting "sudo" before the command to run it as root. Try that before losing half of your (already very less in my case) brain cells over this.

@gattohub

This comment has been minimized.

Copy link

commented Jun 25, 2018

Hi. I do not understand why this guide was useful to connect my android phone but when I try to connect with my pc linux I can not get sound through the speakers. Everything happens in the same way. That is, correct pair, correct connection, sound ok from smart phone but nothing at all from pc linux with DEbian.

@ahahn94

This comment has been minimized.

Copy link

commented Jun 28, 2018

@annagat I had the same problem.

I modified my /etc/systemd/system/a2dp-playback.service in the following way to fix it:

I added

Restart=always
RestartSec=3

and changed User=pi to User=root, both in the [service] part of the file.

The problem is caused by missing permissions, so running the service as root fixes that.
The restart-part just restarts the service within 3 seconds if it crashes (just for enhanced availability).

@amilino

This comment has been minimized.

Copy link

commented Jul 2, 2018

Is this working with Kodi? I would like to use Kodi to recieve my audio stream from Android mobile device.

@amilino

This comment has been minimized.

Copy link

commented Jul 3, 2018

Ok, just figure out that Kodi can play audio at the same time. :) This is cool.

One question, is it useful to turn off Scanning, like this?
echo -e "scan off" | bluetoothctl

@aking7

This comment has been minimized.

Copy link

commented Jul 8, 2018

Bluetooth streaming is working from my phone to the RaspberryPi output, but there is still a GUI that pops up to accept the pairing request, which I need to accept. Does anyone have it working on a headless setup, where you can automatically pair new devices?

@amilino

This comment has been minimized.

Copy link

commented Jul 10, 2018

I don't have issues with pairing request, I have it only if I have before removed device by clicking on bluetooth icon from the taskbar in Raspbian. But when you accept it, it will not popup again for that particular device.

In general this solution works great, you can even have more Android devices connected at the same time. You can also play audio from all connected devices at the same time.

The biggest disadvantage is that it doesn't work if you try to connect it with Ubuntu system. I tested with Kubuntu on my laptop. It is working great from Android and even Windows but from other Linux machine like Ubuntu all looks fine but no sound. Too bad, I will have to look for some other solution unfortunately until this is fixed, hopefully it will be fixed.

@Ssnarf

This comment has been minimized.

Copy link

commented Jul 23, 2018

A quick note to say thank you. Worked well on raspi B+ with an old Belkin F8T003v2.
I had some issues getting bluealsa-aplay to start the audio hardware but this turned out to be a conflict with pulseaudio which was subsequently removed.

@ResistanceIsUseless

This comment has been minimized.

Copy link

commented Jul 30, 2018

Thank you so much for posting this!! This worked perfectly with the pi0w and the phat dac after running their setup script.

@lucatk

This comment has been minimized.

Copy link

commented Aug 2, 2018

Is there some way to make these services run earlier, as in as early as possible? I only need the system for the A2DP streaming and want to use it in my car. It's pretty useless if I have to wait 1 and a half minutes for my phone to connect and music to start playing. :(

@hahagu

This comment has been minimized.

Copy link

commented Aug 2, 2018

This is very useful and works fine.
However, there is a slight problem.
The device does not become discoverable when rebooted.

echo -e 'discoverable on \nquit' | sudo bluetoothctl

should be started on boot.

Also, it is somehow connectable after another device already connects?
This is unexpected..

Edit: I see @mill1000 made a post here,
and it does block the second device from playing audio.
But still, I think blocking the second device from connecting is a far better approach,
since if you want to switch to the second device you have to disconnect the first, disconnect the second, and reconnect the second device... 😞

Edit 2: I have made an automated script for this.
See https://github.com/hahagu/rpi-headless-a2dp

Edit 3: Here's the commit responsible for the simultaneous devices 'problem'.
Arkq/bluez-alsa@71b9f06
Arkq/bluez-alsa@d76191e

@cmougin

This comment has been minimized.

Copy link

commented Aug 3, 2018

@r1nzler
Hi r1nzler (matthew?). with pi0w: how did you work around the "known bug when the WiFi is used simultaneously. " (see top of this page) ?
did you turn the wifi off ?

@hashtagchris

This comment has been minimized.

Copy link

commented Aug 12, 2018

@davthomaspilot said above:

However, when I ran
sudo /usr/local/bin/a2dp-agent
I just got
A2DP Agent Registered
I didn't get any AuthorizeService records.

I had the same issue, because I had already paired and trusted my phone before trying out a2dp-agent. If you want to test a2dp-agent, try running bluetoothctl and use paired-devices, untrust and remove to unpair your device. Then run sudo /usr/local/bin/a2dp-agent and test pairing again.

@cmougin

This comment has been minimized.

Copy link

commented Aug 12, 2018

There is a known bug when the WiFi is used simultaneously => I added one line to switch off the WiFi when a BT device get connected:
os.system("sudo ifconfig wlan0 down")
also: import os.
This 100% solved the issue, on my raspi 0.

@Coda-Coda

This comment has been minimized.

Copy link

commented Aug 13, 2018

Awesome tutorial, thanks heaps 👍
I found it necessary to add systemctl start a2dp-playback.service to /etc/rc.local in order for the audio to play.

@marcosvfc

This comment has been minimized.

Copy link

commented Aug 15, 2018

It works! There is a know issue using the integrated bluetooth adapter and integrated wifi at same time, is there any way to auto disable the wifi adapter when a bluetooth device is connected? And reenable when disconnected... Maybe adding some line in the python script?
EDIT: I read the @cmougin comment now, sorry. Importing os and add os.system("sudo ifconfig wlan0 down"). But in what point should reanable the wifi adapter? I mean, in the python script.

@peekeesh

This comment has been minimized.

Copy link

commented Aug 16, 2018

Is there an issue with audio/video getting out of sync with this one? My pi 3 model b+ is setup as a headless bt audio receiver and used the instructions here:

https://github.com/nicokaiser/rpi-audio-receiver

It works fine for listening to music. But if I watch youtube videos, the audio somewhat gets delayed by .500 ms to 1 sec.

@amilino

This comment has been minimized.

Copy link

commented Aug 16, 2018

With Bluez 5.50. stuttering is no longer a problem. I am using wifi with bluetooth at the same time! Why do you keep discussing about that???
Please read my comments here for the referrence:
raspberrypi/linux#1402

The only side effect of this tutorial is that audio is not playing if you connect Linux device with RPI Bluetooth! Can that problem be fixed?

@Droxtor

This comment has been minimized.

Copy link

commented Aug 18, 2018

I have tried to do this kind of thing last 2 days and finally got it working with your simple but detailed tutorial. Thank you!

@saurimtr

This comment has been minimized.

Copy link

commented Aug 19, 2018

@mill1000 Sorry for the lamb question, but how do i "Copy the included file a2dp-agent to /usr/local/bin"? I've been using raspbian lite for only a couple of days and i'm lost, seriously!

@frenchy16

This comment has been minimized.

Copy link

commented Aug 19, 2018

@mill100 Thank you as it works! I've one issue. All is ok if I use the soundcard of my Pi3 but when I trie to use my usb soundcard there is no sound. How can I do as the qualitity of the Pi soundcard is very poor and I want to use my usb soundcard? Thanks

@amilino

This comment has been minimized.

Copy link

commented Aug 20, 2018

Hi @frenchy16, maybe your problem is same like mine. I have no sound when I connect linux based device with RPi. Unfortunately, mill1000 is not answering on questions at all and this tutorial is not so perfect.

Let us see if someone else can help us and give some answers. Otherwise I would recommend that you search for some alternative tutorial.

@Pindar

This comment has been minimized.

Copy link

commented Sep 1, 2018

@frenchy16 to get your usb sound card working you need to configure alsa-player. One tutorial you might find helpful is available at https://learn.adafruit.com/usb-audio-cards-with-a-raspberry-pi/instructions - I have mine working with hifiberry.
Feel free to have a look at my fork of this already great gist (thank you @mill1000) where I added some more information.

@Pindar

This comment has been minimized.

Copy link

commented Sep 1, 2018

Hi @saurimtr ! Let me help you with your question.

Copy the included file a2dp-agent to /usr/local/bin

  1. download the file
    curl -O -L https://gist.githubusercontent.com/mill1000/74c7473ee3b4a5b13f6325e9994ff84c/raw/fc6ba036b3addba061a70615080238de400ae51f/a2dp-agent
  2. copy file with following command
    cp a2dp-agent /usr/local/bin
@adrian-elian

This comment has been minimized.

Copy link

commented Sep 5, 2018

Hi All,
Following up the tutorial on my Raspberry pi zero w works great, except the part where i restart the pi.
I am not able to find my raspberry pi using my iphone x or iphone 6 until i type the following command line: pactl list sources short
As weird it may seam, as soon as i type the command, the pi's Bluetooth becomes visible and i can connect and pair to it. This happens at every restart.

Does anybody know why does this happen and how can i fix it ?
Regards
Adrian.

@Ov3r0n

This comment has been minimized.

Copy link

commented Sep 12, 2018

Hi!
I just followed the guide and I cannot get my phone/laptop to connect to the pi

They pair but no luck connecting. The pi does not show as an audio device
Any suggestions?

BTW, I´m using the raspbian desktop version, not sure if this affects the results

Thanks!

@nuthub

This comment has been minimized.

Copy link

commented Sep 22, 2018

Hello, I followed your guide, but do not get the pi recognized as audio device. I can discover and pair an android phone with pi. But the phone does not recognize the pi as audio device and therefore does not connect. What I get with a2dp-agent is
$ sudo a2dp-agent
A2DP Agent Registered
RequestPinCode (/org/bluez/hci0/dev_38_2D_D1_B6_88_51)
but nothing more.

From another computer I do a sdptool browse <MAC_OF_PI_BT> and cannot see any A2DP. As mentioned, I installed bluealsa and checked it is installed. Is there a way to test correct installation? sudo service bluealsa status says it is running.

@Antannah

This comment has been minimized.

Copy link

commented Sep 23, 2018

Hi there, I struggled with the situation, that I could pair my android phone, but there was no media-audio service available on the phone, neither there was the confirmation-request for authorisation of the a2dp service (as described in step 1-6 https://scribles.net/streaming-bluetooth-audio-from-phone-to-raspberry-pi-using-alsa/).
I managed to fix this by adding the a2dp-sink as protocol in /lib/systemd/system/bluealsa.service by changing the ExecStart line to ExecStart=/usr/bin/bluealsa -p a2dp-sink. Besides, the user stated there is `User=root in my case.

@marius-m

This comment has been minimized.

Copy link

commented Sep 29, 2018

I've stumbled also with a couple of problems and got through. Maybe someone finds this useful.

  • Not connecting issue - so after pairing with the bluetooth with bluetoothctl it would seem that the device would disconnect immediately. Tried out various things and not sure if this is related but connecting through lan cable instead ok wifi solved this issue. I've read somewhere other people were having these kind of problems also.
  • No sound even if device is shown as connected - with this had a couple of problems, but the main take away is this, be sure to run bluealsa-aplay -vv 00:00:00:00:00:00 to route the sound properly. Also, when running there seem to be no sound, seems like the sound was muted, and alsamixed would help to get the sound up again.

Amazing post, big thanks for the author. My raspberry is useful again ❤️

@kiai72

This comment has been minimized.

Copy link

commented Oct 17, 2018

it works. but changing volume of bluetooth audio has no effect - can we fix this somehow ?

@alejandro-n-rivera

This comment has been minimized.

Copy link

commented Oct 21, 2018

To anyone else having weird issues (e.g. "GDBus.Error.org.bluez.Error.Failed: Protocol not available") on current versions of Raspbian, I followed the instructions in the sections "Initial Setup" and "Make Bluetooth Discoverable" above exactly, but then created my own automatically running script--which worked for my purposes. Other posts I found suggested installing the pulseaudio bluetooth module package, but the whole point is to get around having to use pulseaudio. Figured I'd post the small shell script I created here (read the comment lines):

#!/bin/bash
# This shell script must be run with sudo/root privileges
# Place this shell script in /home/pi
# Add "sudo /home/pi/startA2DP.sh" (without quotes) to the end of /home/pi/.profile to run automatically after login
# Alternatively add to the end of /etc/xdg/lxsession/LXDE-pi/autostart for system-wide automatic run
# Don't forget to <sudo chmod +x /home/pi/startA2DP.sh> to mark as executable
# Before first run, do: <sudo apt-get update>, then <sudo apt-get upgrade>, and then: <sudo apt-get install bluealsa python-dbus>
# Make RPi discoverable over bluetooth (click on BT icon in taskbar)
# Initiate one-time pairing from the RPi in order to invoke a passkey
# Don't try to connect to the RPi from the BT Audio source first. Connect to the source from RPi BT menu in taskbar.
# Play around with pcm-buffer-time and pcm-period-time to adjust audio/video sync/delay (read bluealsa documentation online)
# Reboot after making changes to buffer/period time values
# NOTE: If connection is made, but there is no sound, right-click the volume icon in the taskbar and make sure it's set to "Analog" then reboot
# NOTE: This script does not stop after pressing Ctrl+C (due to forking '&' at the end), it continues running in the background

echo "Starting A2DP..."

# Remove old files in case of bad prev. exit
rm /var/run/bluealsa/*

# Start A2DP receiver stream, wait 1 sec, then route to headphone jack
bluealsa -p a2dp-sink & sleep 1s; bluealsa-aplay --pcm-buffer-time=170000 --pcm-period-time=10000 -vv 00:00:00:00:00:00 &

echo "A2DP Started."

Echo calls are there so you're able to test that the shell file executes before adding it to /home/pi/.profile

EDIT:
Added --pcm-buffer-time=150000 --pcm-period-time=10000 to the bluealsa-aplay call in the above script. These options seemingly gave me the best performance in terms of audio/video delay through trial-and-error, though I'm not exactly sure exactly how these options work. If someone knows more about these options or finds better values for them, please comment!

EDIT 2:
Slightly adjusted pcm-buffer-time (trying to get it in-sync with a UE Megaboom speaker for use with Samsung's dual-audio over BT feature) and added more clarifying comments to code

@hwassermann

This comment has been minimized.

Copy link

commented Nov 12, 2018

The technique is great but I encountered 2 issues.

Firstly, the device wasn't recognized as an audio device.

Solution:
Edit /lib/systemd/system/bluealsa.service

ExecStart=/usr/bin/bluealsa -p a2dp-sink

Next, the services would load neatly when doing a tidy system reboot, but not during a cold boot (necessary, since I'll be using the unit in my car and power supply will be interrupted).

journalctl revealed

A2DP-Playback[417]: /usr/bin/bluealsa-aplay: BlueALSA connection failed: No such file or directory

It seems the dependent bluetooth services, bluealsa and bluetoothd were taking longer to boot cold.

Solution
Edit /etc/systemd/system/a2dp-playback.service (installed as per instuctions above)

[Unit]
Description=A2DP Playback
...
[Service]
ExecStartPre=/bin/sleep 10
@obacho

This comment has been minimized.

Copy link

commented Nov 13, 2018

also had the problem of the Pi not being recognized as a audio sink.
hwassermann's Solution worked:
Edit /lib/systemd/system/bluealsa.service

ExecStart=/usr/bin/bluealsa -p a2dp-sink

@BamboOSZ

This comment has been minimized.

Copy link

commented Nov 29, 2018

Very good tutorial. Worked first time around!

Now to make it perfect for my use case (car bt receiver) I need to resolve two more issues:

  1. Make the phone connect automatically whenever pi boots up (atm. I have to connect manually every time)
  2. Increase maximum volume (its too quiet on my speakers)

As soon as I have solution I’ll post it here.
Any help would be most appreciated.

@mpkogli

This comment has been minimized.

Copy link

commented Dec 14, 2018

Working here on a Rasp 3B+ (with WiFi) after taking @hwassermann's suggestion above, but as @BamboOSZ mentioned the volume is very low, even with the speakers cranked. The volume does change when I adjust on my phone, but the max is not nearly what my setup should provide. Thanks to anybody who can point us in the right direction!

@luki139

This comment has been minimized.

Copy link

commented Dec 24, 2018

It's a little iffy on pi zero with usb soundcard. It struggles to show up when i use my android device (takes about 15s before the phone discovers it even though it's always discoverable) and my win 10 laptop never sees it. Does anyone know what's the problem? After connecting with the phone it works just fine

@amilino

This comment has been minimized.

Copy link

commented Dec 29, 2018

Any alternative tutorial, that can cover connection from Linux?

@pentacore

This comment has been minimized.

Copy link

commented Jan 9, 2019

Thought id fling in to provide another way to solve the cold boot issues @hwassermann had.

[Unit]
Description=A2DP Playback
StartLimitInterval=200
StartLimitBurst=5
...
[Service]
Restart=always
RestartSec=10

This way, it retries the starting of playback service 5 times with 10 sec delay, before giving up. this makes sure are dependencies are started beforehand

@brodie-g

This comment has been minimized.

Copy link

commented Feb 10, 2019

Thanks for the guide, it's working great.
I had the same issue with low volume, had to turn up my receiver way too high and started getting ambient noise coming through.
Using alsamixer you can turn up the Master output volume, I think be default it was only set to around 40%. Not sure if there's any side effects of this, but the sound quality at 90% master volume has been good for me.
https://my.esecuredata.com/index.php?/knowledgebase/article/6/adjust-the-volume-of-a-raspberry-pi-using-the-command-line

@zudljk

This comment has been minimized.

Copy link

commented Feb 20, 2019

I implemented this with my Raspi 1B and an Asus Xonar U7 USB sound card; it's working great!
However, when I try to connect my Windows 10 PC to it via bluetooth, it recognizes the Raspi as a stereo-only audio sink. How can I make the Raspi advertise itself as being 5.1 capable? Do I have to set that via the Bluetooth device class?

@pimseb

This comment has been minimized.

Copy link

commented Mar 20, 2019

Thank you for this guide. It works but I have a problem with sound level.
On my android phone I have only like 3 or 4 sound levels if I push up/down buttons. The volume doesn't use the whole scale of the bluetooth phone. It results of the sond being very loud even at low scale. Any way to fix it ?

@nivieru

This comment has been minimized.

Copy link

commented Mar 20, 2019

@amilino @gattohub @allebb and everyone else who got it working when connecting from android but get no sound when connecting from a linux system...
There's a bug in pulseaudio that sends the wrong RTP payload type. The bug is fixed in git (https://gitlab.freedesktop.org/pulseaudio/pulseaudio/merge_requests/48), and so compiling pulseaudio from a recent git fixed the problem for me.
As an alternative approach, I saw mentions of a version of bluez-alsa that disables checks for the payload type as a bypass to the problem, but didn't try it as the compiling PA worked for me.

@mill1000

This comment has been minimized.

Copy link
Owner Author

commented Apr 11, 2019

Wow. Just learned that Github doesn't send notifications on Gists. Did not think this would get so much attention.

For those of you having volume issues, check the volume settings of your output device using alsamixer as @brodie-g had mentioned.

@Mitte333

This comment has been minimized.

Copy link

commented May 1, 2019

I am able to connect my Laptop and stream audio to the pi. Now I want to connect another device for a project to stream it's audio signal and make FFT analysis. The problem is that the device connects and disconnects every few seconds. So I can't get a stable connection and also the device itself never shows a connection. The device can autoconnect to a simple BT-speaker and I get the sound. It is just impossible to connect the device with the pi. The device is paired and trusted and it works neither with onboard BT nor with BT dongle. Anyone has advice?

@jezza770

This comment has been minimized.

Copy link

commented May 11, 2019

Hi,
This worked like magic!!
Is there any way to clone the audio stream in that python script so I can do some post processing in a separate process?
I want to build a light controller based on instantaneous noise levels.
Thanks

@amilino

This comment has been minimized.

Copy link

commented Jun 10, 2019

Is it possible to connect a bluetooth speaker and play audio at the same time while streaming audio to RPi?
In other words, is it possible to use this tutorial to use bluetooth audio streaming to Raspberry and also send audio to a bluetooth device from RPi at the same time?

@mill1000

This comment has been minimized.

Copy link
Owner Author

commented Jun 10, 2019

@jezza770
The python script doesn't handle the audio data, it just authorizes the A2DP connection.
Bluez-alsa creates a virtual PCM audio device which handles the audio data. If you wanted to do some post processing you should look into accessing that ALSA device.

@amilino
Bluez-alsa does support sending audio so the software should be capable of receiving audio and forwarding it. However, I don't know if a single Bluetooth device can support multiple simultaneous connections. You may have to have a dedicated device for each connection. e.g. A USB Bluetooth dongle to receive audio from, and the internal Bluetooth to send audio to.

@amilino

This comment has been minimized.

Copy link

commented Jun 10, 2019

Tnx for a fast reply. One more question. Audio is not playing if you connect Linux device with RPI Bluetooth. Can that problem be fixed?

@mill1000

This comment has been minimized.

Copy link
Owner Author

commented Jun 10, 2019

@amilino Not sure I understand the problem. Are you trying to play music to the RPi using a Linux computer as the source? Does the Linux also have bluez-alsa? If so, you should be able to play to the RPi following the instruction here: https://github.com/Arkq/bluez-alsa#configuration--usage

@amilino

This comment has been minimized.

Copy link

commented Jun 10, 2019

Yes, music from my linux laptop. I am able to connect devices but no sound comming out from RPI.

@mill1000

This comment has been minimized.

Copy link
Owner Author

commented Jun 11, 2019

@amilino Assuming the RPi works with another source e.g. a phone, then the issue is likely the Linux laptop not sending A2DP data. I can't recreate your setup so unfortunately I won't be of much help.

@amilino

This comment has been minimized.

Copy link

commented Jun 11, 2019

@mill1000 I am on latest version of Kubuntu on my laptop. Pairing and connection to RPi is working fine and stable. But no sound coming out from RPi. I tired to play with settings under Audio volume settings but no luck. Actually when I select my raspberry as a Output device I hear no sound at all on my laptop but neither on RPi.

@amilino

This comment has been minimized.

Copy link

commented Jun 11, 2019

Hm, it looks like bluez-alsa is missing on my Kubuntu. Do you know how to install it on Kubuntu?

@mill1000

This comment has been minimized.

Copy link
Owner Author

commented Jun 11, 2019

In theory, Pulse Audio should be able to send audio via Bluetooth. I would think Kubuntu has Pulse Audio. Otherwise, you'll have to build from scratch following the bluez-alsa instructions: https://github.com/Arkq/bluez-alsa

@nivieru

This comment has been minimized.

Copy link

commented Jun 14, 2019

@amilino, this is a bug in pulseaudio. The bug is already fixed in git (https://gitlab.freedesktop.org/pulseaudio/pulseaudio/merge_requests/48), but not in the current release. To fix it for yourself, you need to complie pulseaudio from source using recent git. See my comment higher in the thread.

@amilino

This comment has been minimized.

Copy link

commented Jun 14, 2019

Hi, thank you for answer, but not sure if I need to compile bluez-alsa or pulseaudio and how to compile it. So far I tried bluez-alsa but it cannot compile on Ubuntu because of missing "macros" package and not sure how to install that package.

@GaMarius

This comment has been minimized.

Copy link

commented Jun 26, 2019

when I try to connect my phone to the pi after sudo /usr/local/bin/a2dp-agent, there's no reaction by the pi. Can somebody help me?

@matthijskooijman

This comment has been minimized.

Copy link

commented Jul 9, 2019

I've found that on a rpi3, using the built-in bluetooth adapter, the startup of the agent is not timed correctly. It looks like on startup, there are no bluetooth adapters available, so bluetooth.service is not started. Apparently systemd then decides there is no point in delaying the agent since bluetooth.service won't be started anyway. The agent starts, fails since bluez is not running yet, and a short while later the serial device that connects to the bluetooth adapter becomes available and bluetooth.service is started after all.

To fix this, I've changed the 'WantedBy= line to bluetooth.service rather than multi-user.target. This makes sure that the agent is not started until bluetooth.service is needed (and the existing After line makes sure that the agent is started after bluez).

I've also noticed that even when the discovery timeout is set to 0, the pi is not discoverable after a reboot and needs a manual bluetoothctl command to make it discoverable again. I've also fixed this in the agent service file, using a ExecStartPre directive.

With those changes, bt-agent-a2dp.service becomes:

[Unit]
Description=A2DP Bluetooth Agent
After=bluetooth.service
Wants=bluetooth.service

[Service]
ExecStartPre=/bin/sh -c "echo discoverable on | bluetoothctl"
ExecStart=/usr/bin/python -u /usr/local/bin/a2dp-agent
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=A2DP-Agent

[Install]
WantedBy=bluetooth.service

@mill1000, perhaps you want to include this in your gist above?

@amilino

This comment has been minimized.

Copy link

commented Jul 9, 2019

Heavy stuttering on RPi 4 with Buster. :(

@mill1000

This comment has been minimized.

Copy link
Owner Author

commented Jul 9, 2019

@matthijskooijman Nice work. I will update the Gist with your changes.

@amilino Sorry, I can't help. The RPi 4 is a completely different beast, and I don't have one to tinker with.

@alejandrosorolla

This comment has been minimized.

Copy link

commented Jul 26, 2019

I have installed everything, the bluetooth is visible but when I want to connect there is an error.

Connection failed- GDBus.Error:org.bluez.Error.Failed:Protocol not availabre. Try to connect manually

So I connect manually and...

Connection failed- No usable services on this device

What can I do?

@amilino

This comment has been minimized.

Copy link

commented Jul 26, 2019

It doesn't work on RPi4 with Buster, so maybe search for some alternative solution.

@colerd24

This comment has been minimized.

Copy link

commented Aug 9, 2019

I just tested that this one works on Buster:
https://github.com/nicokaiser/rpi-audio-receiver

@amilino

This comment has been minimized.

Copy link

commented Aug 9, 2019

I just tested that this one works on Buster:
https://github.com/nicokaiser/rpi-audio-receiver

True, it is working more stable but still stuttering a lot, every few seconds. Not usable at all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.