Frederic Danis
September 02, 2022
Reading time:
Do you have an old pair of PC speakers, or an old Hi-Fi, that you would like to convert into a pair of Bluetooth® speakers to play music from your phone? A Raspberry Pi can be easily used as an audio bridge between a Bluetooth® device and an analog speaker system, to make this possible. In this quick guide, I will show you how to set up the software on a Pi, using PipeWire, to achieve this.
In my demonstration setup, I am using a Raspberry Pi 3, which embeds a Bluetooth® chipset, and I am connecting an analog speaker to the 3.5mm jack. For the software, I am using RaspberryPi OS Lite with a recent PipeWire version installed from the Debian testing (Bookworm) repositories, as the version included in RaspberryPi OS (which is based on Debian Bullseye) is too old to support this use case.
PipeWire is able to output sound to the internal audio chipset without any special configuration. It provides Bluetooth® A2DP support with optional codecs (SBC-XQ, LDAC, aptX, aptX HD, aptX-LL, FastStream) out of the box. At the same time, WirePlumber automatically creates the connection between the A2DP source and the audio chipset when a remote device, like a phone or a laptop, connects. This makes the configuration very easy, as PipeWire will work out of the box. We will only need to set up BlueZ to make the system headless.
Let's see how this is done.
First, install RaspberryPi OS Lite (64-bit) to your SD card (assuming /dev/sdb
is the SD card device on your PC/laptop):
$ xzcat 2022-04-04-raspios-bullseye-arm64-lite.img.xz | sudo dd of=/dev/sdb bs=1M status=progress
Connect the Raspberry Pi to a display & keyboard, boot it from this SD card, and complete the OS configuration.
After the OS configuration is complete, install PipeWire and WirePlumber from the testing (Bookworm) repository:
$ echo 'APT::Default-Release "stable";' | sudo tee /etc/apt/apt.conf.d/99defaultrelease $ echo "deb http://ftp.de.debian.org/debian/ testing main contrib non-free" | sudo tee /etc/apt/sources.list.d/testing.list $ sudo apt update $ sudo apt -t testing install pipewire wireplumber libspa-0.2-bluetooth
The RaspberryPi OS Lite version automatically logs in the user created during the setup and this will automatically start PipeWire and WirePlumber. This is all that's needed for setting up PipeWire.
Update - January 2023
Depending on the version of
RaspberryPi OS Lite
the OS does not automatically log in the user created during setup. You will have to selectConsole Autologin
using theraspi-config
utility.Recent versions of PipeWire and WirePlumber packages have been back-ported to bullseye, allowing for the use of the bullseye-backports repository instead of the testing repository:
$ echo "deb http://deb.debian.org/debian bullseye-backports main contrib non-free" | sudo tee /etc/apt/sources.list.d/bullseye-backports.list $ sudo apt update $ sudo apt -t bullseye-backports install pipewire wireplumber libspa-0.2-bluetooth
Next, we will need to set up a BlueZ pairing agent to accept pairings and A2DP connections. The reason we are doing this is because the target system is not going to have a user interface and we don't want to connect to it using ssh and type commands every time we want to pair a new device to it.
As this will require the DBus Python support, let's install this first:
$ sudo apt install python3-dbus
Then, copy the speaker-agent.py
python script and its related systemd unit file from GitHub pw_wp_bluetooth_rpi_speaker to your user home directory on the Raspberrry Pi.
The speaker-agent.py
python script, also shown below, will set the Raspberry Pi Bluetooth® adapter as always discoverable and will allow pairing and A2DP connections:
#!/usr/bin/python3 # SPDX-License-Identifier: LGPL-2.1-or-later import dbus import dbus.service import dbus.mainloop.glib from gi.repository import GLib BUS_NAME = 'org.bluez' AGENT_INTERFACE = 'org.bluez.Agent1' AGENT_PATH = "/speaker/agent" A2DP = '0000110d-0000-1000-8000-00805f9b34fb' AVRCP = '0000110e-0000-1000-8000-00805f9b34fb' bus = None 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): # Always authorize A2DP and AVRCP connection if uuid in [A2DP, AVRCP]: print("AuthorizeService (%s, %s)" % (device, uuid)) return else: print("Service rejected (%s, %s)" % (device, uuid)) raise Rejected("Connection rejected by user") @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) mainloop = GLib.MainLoop() # By default Bluetooth adapter is not discoverable and there's # a 3 min timeout # Set it as always discoverable adapter = dbus.Interface(bus.get_object(BUS_NAME, "/org/bluez/hci0"), "org.freedesktop.DBus.Properties") adapter.Set("org.bluez.Adapter1", "DiscoverableTimeout", dbus.UInt32(0)) adapter.Set("org.bluez.Adapter1", "Discoverable", True) print("RPi speaker discoverable") # As the RPi speaker will not have any interface, create a pairing # agent with NoInputNoOutput capability obj = bus.get_object(BUS_NAME, "/org/bluez") manager = dbus.Interface(obj, "org.bluez.AgentManager1") manager.RegisterAgent(AGENT_PATH, "NoInputNoOutput") print("Agent registered") manager.RequestDefaultAgent(AGENT_PATH) mainloop.run()
The systemd unit starts the speaker agent on boot as RaspberryPi OS Lite automatically logs in the user:
[Unit] Description=Bluetooth speaker agent [Service] ExecStart=python speaker-agent.py [Install] WantedBy=default.target
This systemd unit will need to be placed in ~/.config/systemd/user/
and enabled manually using:
$ systemctl --user enable speaker-agent.service
Finally, configure the BlueZ daemon to allow re-pairing without user interaction:
$ sudo sed -i 's/#JustWorksRepairing.*/JustWorksRepairing = always/' /etc/bluetooth/main.conf
Now, connect the audio output of your Raspberry Pi to a speaker or your Hi-Fi system, reboot, pair, and connect your phone.
Enjoy the sound! ;)
19/12/2024
In the world of deep learning optimization, two powerful tools stand out: torch.compile, PyTorch’s just-in-time (JIT) compiler, and NVIDIA’s…
08/10/2024
Having multiple developers work on pre-merge testing distributes the process and ensures that every contribution is rigorously tested before…
15/08/2024
After rigorous debugging, a new unit testing framework was added to the backend compiler for NVK. This is a walkthrough of the steps taken…
01/08/2024
We're reflecting on the steps taken as we continually seek to improve Linux kernel integration. This will include more detail about the…
27/06/2024
With each board running a mainline-first Linux software stack and tested in a CI loop with the LAVA test framework, the Farm showcased Collabora's…
26/06/2024
WirePlumber 0.5 arrived recently with many new and essential features including the Smart Filter Policy, enabling audio filters to automatically…
Comments (63)
tino:
Sep 02, 2022 at 06:16 PM
With how cheap Bluetooth speakers are, don't waste a raspberry on this, Especially considering that there is a great lack of Raspberry in the market
Reply to this comment
Reply to this comment
Arien:
Sep 02, 2022 at 11:31 PM
It's a tech demo, chill out :)
Also, nothing else will do literally all relevant codecs and even opus over bluetooth for highest possible quality.
Also, you don't need to run this on a pi an nothing will stop you from doing lots of other stuff with it in parallel. It's a computer, after all.
I really like pipewire and I'm amazed at the pace of development.
Reply to this comment
Reply to this comment
J:
Sep 03, 2022 at 01:51 AM
I'd like to know what Bluetooth compatible speaker you would recommend? I'd like to have audio quality on par with or surpassing a proper bookshelf speaker or "studio monitor." Don't get me wrong, most conventional "Bluetooth speakers" nowadays have decent audio quality and are very appealing, but they still cannot compete with even a decent low-end monitor such as the JBL LSR305. I personally run a simple $10 Bluetooth dongle with some older bookshelf speakers in my garage and at our community pool and people are blown away because they're used to these cheap Bluetooth speakers. Expanding my setup to something like what this post is suggesting makes a lot of sense to me, even if it's using Raspberry Pis.
Reply to this comment
Reply to this comment
Frédéric Danis:
Sep 06, 2022 at 05:12 PM
I'm not sure to understand your question.
The idea of this blog post is to use a non Bluetooth speaker and to transform it into a Bluetooth speaker with a Raspberry Pi.
If you want better sound quality you may add an audio card to the RaspberryPi, USB or HAT.
Reply to this comment
Reply to this comment
Paul Norris:
Sep 13, 2022 at 03:23 PM
How do you configure the software to use the DAC HAT, rather than the 3.5mm jack for output?
Reply to this comment
Reply to this comment
tino:
Sep 07, 2022 at 01:46 PM
if you are looking for "studio audio quality", the Bluetooth way is not the right one, a good DAC and semi-pro headphones with cables are better
Reply to this comment
Reply to this comment
Tony:
Sep 03, 2022 at 04:14 AM
I have a nice B&O speaker that has an unreliable Wi-Fi connection that will now get a new lease on life using this idea.
I also have a spare RP3 available.
Reply to this comment
Reply to this comment
V:
Sep 02, 2022 at 10:27 PM
Thanks for this, I'll try it out for sure. I attempted something like this a few years back and it was just too unreliable, as I was routing everything manually, basically.
Reply to this comment
Reply to this comment
Aidan Macgregor:
Sep 04, 2022 at 09:07 PM
Not to try this on armbian on amlogic or rockchip boxes!
Reply to this comment
Reply to this comment
void:
Sep 05, 2022 at 10:31 PM
Thanks for the guide! Just a question, what would the necessary changes be in order to avoid allow pairing from any device? I don't mind going into bluetoothctl and pair/trust a device when I want it to be able to stream music to my rpi.
Reply to this comment
Reply to this comment
Frédéric Danis:
Sep 06, 2022 at 05:17 PM
This is done by the "speaker-agent.py" python script, see the second part of the blog post.
Reply to this comment
Reply to this comment
Fedor:
Dec 27, 2022 at 09:43 AM
Please can you show an example in the script how to add only the required mac addresses. I'm not strong in Python.
Reply to this comment
Reply to this comment
Fedor:
Dec 27, 2022 at 09:44 AM
Please can you show an example in the script how to add only the required mac addresses. I'm not strong in Python.
Reply to this comment
Reply to this comment
Stuart Naylor:
Sep 10, 2022 at 02:41 AM
Does anyone know if pipewire supports the new Bluetooth LE broadcast audio protocols.
PS
A Pi Zero2 makes a great audio platform with a cheap DAC module and as someone mentioned earlier converting a decent pair of 2nd user bookshelf speakers can make Sonos challenging audio quality.
Reply to this comment
Reply to this comment
Olivier Crete:
Sep 10, 2022 at 07:47 AM
Work is ongoing to support the new Bluetooth LE broadcast audio protocols.
Reply to this comment
Reply to this comment
Stuart Naylor:
Sep 10, 2022 at 08:38 PM
Would you have a link to a repo or group as quite interested in LE Auracast and if it can time sync clients to the level of say Snapcast which does a great in that respect over wifi.
I am trying to work out whether to have a single bluetooth input and relay via snapcast over wifi for multichannel time sync or just use Auracast but like 'work in progress' apart from the SIG info I can find nothing about any Linux adoption of Auracast.
Also with the Raspberry Pi the WiFi/BT combo chips are near useless in dual mode where if you google you will find a huge history of a huge rake of problems where the solution is don't mix and match just use one or the other.
For most operations WiFi & BT can multiplex but a constant stream on both on a Pi is not a tasty pie to consume.
I disable BT use the wifi and add a single BT dongle and works great but it took some hair pulling and actually reading what others say to realise.
So I really like snapcast also that is a great tcp/ip multichannel with choice of codec casting software and I am really struggling to choose a roadmap between it and Auracast.
PS is anyone interested in creating an interest forum / repo(s) as would be really interested in other thoughts and collaboration?
Reply to this comment
Reply to this comment
Frédéric Danis:
Sep 16, 2022 at 04:46 PM
Bluetooth LE Audio is work in progress in both BlueZ and PipeWire, but it's hard to find compatible Bluetooth adapters.
Currently the Connected stream support has been merged upstream for both BlueZ and PipeWire.
Auracast is not yet supported by BlueZ.
Reply to this comment
Reply to this comment
Franco Castillo:
Oct 08, 2022 at 04:55 AM
What are the benefits of Bluetooth LE Audio? How is it different from the Bluetooth that is used in a portable speaker and a smartphone for example?
Reply to this comment
Reply to this comment
Stuart Naylor:
Oct 11, 2022 at 03:32 PM
There is a whole rake of improvements with Bluetooth LE prob one of the biggest upgrades to BT in a while maybe ever.
Better codecs, more bandwidth, more channels, but what interests me is auracast which is a sort of revenue broadcast, so from unlimited clients think headphone disco to maybe a simple 7:1 speaker setup that all share a stream.
https://www.theverge.com/2022/7/12/23204956/bluetooth-le-audio-completed-low-power-high-quality-wireless-headphones
Reply to this comment
Reply to this comment
Stuart Naylor:
Sep 16, 2022 at 02:20 PM
I posted on the BlueZ github and kindly got a replay and much will be implemented in the Linux kernel 6.0 release so maybe next release or subsequent I am guessing for bluetooth broadcast audio
Reply to this comment
Reply to this comment
Sorin:
Sep 16, 2022 at 08:04 AM
What about a native protocol, to connect over ethernet or wifi like pulseaudio, so that one does not pollute the environment with additional bluetooth noise?
I also would like a pin authentication for bluetooth connections instead of no authentication: I live in an apartment bloc and somone nearby can connect to my audio system and play a loud sound in the middle of the night, to have some fun.
bluez-tools is offering some authentication agents, one of them allows no authentication with the bt-agent program.
Reply to this comment
Reply to this comment
Stuart Naylor:
Sep 16, 2022 at 09:14 AM
Likely the reason they have done bluetooth is because there is a plethora of RTP but very few common ones on media devices.
Apple airplay 1 has opensource such as https://github.com/mikebrady/shairport-sync
Chromecast I think is proprietary and Google are not releasing that but there is https://www.airserver.com/
Spotify cast requires a premium subscription with there recent api changes.
So bluetooth may have its downsides but if you want wide compatibility and ease then its likely why that option was chosen.
The code shows how to auto accept connections but equally pin codes can be used and its all documented via bluez
Also the Pi has a problem as those Broadcom combo wifi/bt combo units are not great and its best to use solely one or the other but not both at the same time.
If you google you will find a huge history of woe with concurrent use where often its better to blacklist or dtoverlay diable the bt and just add a cheap dongle to stop the many errors that can occur.
Snapcast is a great NTP sync multi room wifi cast opensource but its finding sources that you may even use bluetooth to the server then transmit over wifi to clients https://github.com/badaix/snapcast
Reply to this comment
Reply to this comment
Sorin:
Sep 20, 2022 at 07:52 PM
Pulseaudio has its own open source protocol for transmitting audio over eth or wifi and I'm using it to send audio from various linux sources to an audio server running on odroid, connected to a USB balanced audio and Yamaha HS8. It also accepts 2 concurrent bluetooth A2DP connections via 2 USB bluetooth dongles. The USB audio also has input which is connected to a TOS link converter and by an optical cable to a TV.
Reply to this comment
Reply to this comment
Sorin:
Sep 20, 2022 at 08:01 PM
You can connect the Pi via eth, as it's a server. It will receive audio via the wifi router either from an eth or a wifi source. As for bt, you can use an USB dongle. I usually disable the 2.4 GHz radio on the router and only keep higher frequencies to not interfere with bt.
Reply to this comment
Reply to this comment
Stuart Naylor:
Sep 20, 2022 at 08:56 PM
Its not the freq its the combo chip sharing the SDIO / gSP from broadcom that on the Pi has never truly coexited.
If you want both and 100% be sure disable one and get a dongle or join the plethora of Pi posts of woe.
Reply to this comment
Reply to this comment
Aidan Macgregor:
Sep 16, 2022 at 03:22 PM
i currently use amlogic TV box, i still have to try this set up on armbian on some of my boxes, but currently have a set up with android TV (My Custom ROM) i have installed"smart tube next" (Manually as my rom clean and empty) this allows me to cast youtube (by pin connect) & i also have modded spotify APKs as both a Phone version & an android TV version that both work with spotify connect With Each Other Ad Free (Still Works Tested Today, if you are premium it will work Downloading Both Spotifys From The Play Store), I also used macrodroid to ensure both apps start at boot so connection can happen in background without user interaction :)
Reply to this comment
Reply to this comment
JJ Jackson:
Oct 26, 2022 at 09:59 PM
What does a Hi-Fi card look like? What would I be looking for in a regular speaker? I'm new to this so I don't know what you're talking about. I would still like to learn, but I need help. Thank you
Reply to this comment
Reply to this comment
George Kiagiadakis:
Oct 31, 2022 at 05:04 PM
There are hats (i.e. add-on cards) for the Raspberry-pi that extend the Pi to be a Hi-Fi amplifier. For instance, https://www.amazon.com/Inno-Maker-Raspberry-Amplifier-Expansion-Capacitor/dp/B07CZZ95B9 (that was the first result on the search). These cards can then be connected to Hi-Fi speakers with regular copper wires. On the Raspberry Pi, you can then select this card as the audio output (using wpctl status / wpctl set-default), and have all audio play through the Hi-Fi speakers.
Reply to this comment
Reply to this comment
Sunny the Solar Guy:
Jan 07, 2023 at 05:28 PM
IQAudio (now owned by raspberry pi) make a amp call DigiAmp that is excellent . its HAT and works very well. I have it running Volumio. I also have the DAC-Pro that had RCA connectors to connect to an HI-Fi. works like magic. very affordable too. black PCB means it still IQAudio made and new ones are green PCB meaning manufactured by RaspPi
Reply to this comment
Reply to this comment
Clayton Barton:
Oct 30, 2022 at 08:53 PM
I'm not getting any audio.
wireplumber won't install.
pipewire.pulse package doesn't exist.
apt-add-repository doesn't work any more.
what a nightmare I just wasted a whole day dicking with this
Reply to this comment
Reply to this comment
Clayton Barton:
Nov 01, 2022 at 12:10 AM
I eventually was able to get some audio thru for only 30 seconds at a time then it dropped the audio and the audio device profile with it.
Tried trusting the device and writing out the profile to the config, nothing works and then pulse killed my lxpanel for good!
Could not get lxpanel back no matter what I tried
Reply to this comment
Reply to this comment
George Kiagiadakis:
Nov 01, 2022 at 03:23 PM
I am sorry to hear about these issues you are facing. May I suggest that you try again on a new installation of the operating system, following the instructions carefully? Perhaps something was overlooked or maybe there was some external factor that affected your OS installation.
In any case, if you continue running into issues, please let us know what exactly fails, at which step, with what kind of error message, etc, so that we are able to give you some more meaningful advice.
Reply to this comment
Reply to this comment
Clayton Barton:
Nov 01, 2022 at 05:07 PM
Unable to locate package wireplumber
libspa-0.2-bluetooth has unmet dependences libldacbt-abr2, libldacbt-enc2, libopenaptx0
Reply to this comment
Reply to this comment
George Kiagiadakis:
Nov 02, 2022 at 07:21 AM
That is strange. I wonder if this happens because apt is getting confused somehow. Perhaps some recent changes in the testing repository are incompatible with the bullseye image.
May I suggest that you use bullseye-backports instead of testing, with this repository line:
deb https://deb.debian.org/debian/ bullseye-backports main contrib non-free
Recent versions of pipewire and wireplumber are now backported and available there. This was not the case when this blog post was written, so this is why the instructions above recommend setting up the "testing" repository.
Reply to this comment
Reply to this comment
Nicolás Rico:
Nov 02, 2022 at 03:41 PM
I'd love to try this out, but after adding the testing repos and apt updating, now there are hits under 'testing' of several packages that were already installed from stable.
This worries me.
Granted, i'm not a unix guru, i only dabble. But i think i got the 00defaultrelease and testing.list files in the right places (after all, i simply ran the provided CLI commands as they were).
Any way to get PipeWire from test without affecting other packages?
Reply to this comment
Reply to this comment
George Kiagiadakis:
Nov 02, 2022 at 04:44 PM
Hi, take a look at my comment above about using bullseye-backports instead. The relevant packages should be available in that repository now, so you no longer need to pull things from testing.
Reply to this comment
Reply to this comment
Nicolás Rico:
Nov 02, 2022 at 05:09 PM
thank you for the quick reply!
I've been looking into it (that, and pinning); if I understood correctly I'd have to leave the 99defaulterelease under apt.conf.d, but instead of creating the testing.list under sources.list.d run:
$ echo "deb https://deb.debian.org/debian/ bullseye-backports main contrib non-free" | sudo tee /etc/apt/sources.list.d/bullseye-backports.list
to create the backports list.
Which I guess it means i need to install with "apt -t bullseye-backports" instead, right?
Reply to this comment
Reply to this comment
George Kiagiadakis:
Nov 02, 2022 at 06:15 PM
Yes, that all sounds correct!
Reply to this comment
Reply to this comment
Clayton Barton:
Nov 02, 2022 at 04:50 PM
I'll give that a try.
Just to make sure I don't have to use OS Lite to get this to work do I?
I've tried a bunch of changing the user config file and the global config but nothing is sticking for the source default.
also for some reason the 3.5mm jack is listed as a source and don't see it in the config to change.
it's like it connects and has audio throughput then after about a minute of the same song the audio drops out while the song is still playing and everything is still connected.
Reply to this comment
Reply to this comment
George Kiagiadakis:
Nov 02, 2022 at 06:30 PM
> Just to make sure I don't have to use OS Lite to get this to work do I?
In theory any Raspberry Pi OS image should work, but we tried it with the Lite one because this is supposed to be a headless machine. Also, the version that contains a desktop might have dependency issues on the packages that depend on PulseAudio, so maybe this is why you had problems before. PulseAudio must be completely uninstalled prior to setting this up. Also, the xfce panel volume plugin might have some strange interaction with PipeWire (there is a known issue).
> I've tried a bunch of changing the user config file and the global config but nothing is sticking for the source default.
Try the wpctl command line tool. "wpctl status" should list all the inputs and outputs. "wpctl set-default " should be able to set a default input or output, where the id is the number that appears on the status output.
> it's like it connects and has audio throughput then after about a minute of the same song the audio drops out while the song is still playing and everything is still connected.
Hmm, this could indicate that something is crashing. Perhaps you can take a look at the logs with journalctl and see if you can spot an issue there. It could also be that you still have PulseAudio installed and it interferes with what you are trying to do.
Reply to this comment
Reply to this comment
clayton:
Nov 02, 2022 at 07:07 PM
Journalctl doesn't log anything when it drops the audio only when it eventually disconnects.
Thanks for the tips I'll try them out.
Reply to this comment
Reply to this comment
clayton:
Nov 02, 2022 at 07:07 PM
Journalctl doesn't log anything when it drops the audio only when it eventually disconnects.
Thanks for the tips I'll try them out.
Reply to this comment
Reply to this comment
Clayton Barton:
Nov 04, 2022 at 12:25 AM
changing the sources did get sudo apt -t backports install cmd to do something but ended with an error:
The value 'backports' is invalid for APT:Default-Release as a release is not available in sources
wpctl command not found
Reply to this comment
Reply to this comment
Nicolás Rico:
Nov 05, 2022 at 04:17 AM
There's a comment of mine where I asked what were the changes necessary for the backports repo and doing it just like I outlined in there it worked perfectly.
I just tried that today and got to set it up.
I'm using the full version of the 64bit raspbian with pulseaudio i think. As a sidenote i still have to tinker with it as it starts to lag with use, but it's too late rn to troubleshoot and i need some sleep
Reply to this comment
Reply to this comment
P V Anthony:
Nov 16, 2022 at 11:09 AM
Just installed using 2022-09-22 image and followed the instructions. All works as per the blog.
While playing the song through bluetooth from my mobile phone, my friend came and paired to the same unit and started playing his song. Now both songs can be heard.
Is there a way to prevent the new paired device from playing a song? Until the first paired device stop playing the song. Then the second paired device can play the song.
I hope I am clear in my explanation.
I am hoping to use the gpio pins to connect a toggle switch to kick the first person out and allow the second person to play his song.
Reply to this comment
Reply to this comment
Frédéric Danis:
Nov 16, 2022 at 04:09 PM
Yes, nothing prevents multiple A2DP connections and PipeWire will mix the audio.
One way to prevent this should be to reject the connection to the A2DP service (AuthorizeService method in speaker-agent.py) if another device is already connected, and keep track of the connected device.
Reply to this comment
Reply to this comment
Tommie Jones:
Nov 20, 2022 at 09:15 PM
Use Cava to add a visualizer to your raspberry pi based Bluetooth speaker.
https://medium.com/@atlantageek/visualizing-your-music-on-raspberry-pi-f7c44c4ded70
Reply to this comment
Reply to this comment
Julian:
Dec 23, 2022 at 07:14 PM
Thanks for the guide.
I'm trying to use a RP1 as receiver, but the audio is choppy and stuttering for all codecs i tried (i think i tired all), and some codecs don't make the RP1 produce any sound.
Did somebody manage to get this fully working on a RP1?
Reply to this comment
Reply to this comment
Wayne Walker:
Jan 11, 2023 at 01:22 AM
I have a Raspberry Pi 4 Model B Rev 1.4. I install os lite 2022-09-22 and followed the directions above.
any device can pair with the RPi, but within a few seconds the connection either fails or is terminated.
Logs show this at the end when the connection fails:
```
Jan 11 01:20:14 raspberrypi bluetoothd[555]: src/profile.c:ext_confirm() Hands-Free unit authorizing connection from 58:CB:52:9D:57:94
Jan 11 01:20:14 raspberrypi bluetoothd[555]: src/agent.c:agent_ref() 0x55c05aabb0: ref=2
Jan 11 01:20:14 raspberrypi bluetoothd[555]: src/agent.c:agent_call_authorize_service() authorize service request was sent for /org/bluez/hci0/dev_58_CB_52_9D_57_94
Jan 11 01:20:14 raspberrypi bluetoothd[555]: src/agent.c:agent_ref() 0x55c05aabb0: ref=3
Jan 11 01:20:14 raspberrypi bluetoothd[555]: src/agent.c:simple_agent_reply() agent error reply: org.bluez.Error.Rejected, Connection rejected by user
Jan 11 01:20:14 raspberrypi bluetoothd[555]: src/profile.c:ext_auth() Hands-Free unit rejected 58:CB:52:9D:57:94: Connection rejected by user
```
Reply to this comment
Reply to this comment
Roger:
Feb 22, 2023 at 05:01 PM
Hey Frederic,
Many thanks for the great tutorial...Managed to get this working on a normal Rasberry Pi 4. Just wondering what changes I'd have to make to get it working on an OrangePi 3 LTS?
Thanks
Rog
Reply to this comment
Reply to this comment
Branko Znuderl:
Apr 08, 2023 at 07:51 PM
Hi,
I try to do step:
This systemd unit will need to be placed in ~/.config/systemd/user/ and enabled manually using:
$ systemctl --user enable speaker-agent.service
When I run above I get error;
Failed to enable unit: Unit file speaker-agent.service does not exist.
I have downloaded from github py file and unit file... please help.
Reply to this comment
Reply to this comment
Frédéric Danis:
Apr 11, 2023 at 02:43 PM
Hi,
This is strange. I just do an installation and it works fine for me.
Can you check the installation of the python script and its systemd unit file?
It should be something similar to:
fdanis@raspberrypi:~ $ ls -l ~/speaker-agent.py ~/.config/systemd/user/speaker-agent.service
-rw-r--r-- 1 fdanis fdanis 154 Apr 11 14:21 /home/fdanis/.config/systemd/user/speaker-agent.service
-rw-r--r-- 1 fdanis fdanis 4968 Apr 11 14:20 /home/fdanis/speaker-agent.py
Reply to this comment
Reply to this comment
JB:
Apr 08, 2023 at 10:31 PM
Thanks for this tutorial Frederic, I was able to follow most of it on my Raspberry PI 3 with a fresh Raspbian OS Lite 32-it. I'm installing it all via SSH, not logged in using the account I created when I flashed the image to the MicroSD card with the Raspberry Imager tool.
I created the 2 files and ran this command:
systemctl --user enable speaker-agent.service
But then I get this error:
Failed to connect to bus: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined (consider using --machine=@.host --user to connect to bus of other user)
I checked the raspi-config for autologin, it says:
B2 Console Autologin Text console, automatically logged in as 'albert' user
Any idea what I can do to fix the error?
Thanks!
Reply to this comment
Reply to this comment
Frédéric Danis:
Apr 11, 2023 at 04:07 PM
Hi,
This is strange. I just do an installation using Raspberry Pi Imager, Raspberry Pi OS Lite (32-bit) and enabling SSH.
It works fine for me, I just had to add public keys for bullseye-backports repository by running:
sudo gpg --keyserver keyserver.ubuntu.com --recv-keys 648ACFD622F3D138
sudo gpg --export 648ACFD622F3D138 | sudo apt-key add -
sudo gpg --keyserver keyserver.ubuntu.com --recv-keys 0E98404D386FA1D9
sudo gpg --export 0E98404D386FA1D9 | sudo apt-key add -
I'm not sure to understand what you mean by "not logged in using the account I created when I flashed the image …".
Afaiu, systemd is not running correctly on your image, here's what I got when running 'systemctl --user status':
fdanis@raspberrypi:~ $ systemctl --user status
● raspberrypi
State: running
Jobs: 0 queued
Failed: 0 units
Since: Tue 2023-04-11 16:29:10 CEST; 22s ago
CGroup: /user.slice/user-1000.slice/user@1000.service
├─session.slice
│ ├─pipewire.service
│ │ └─594 /usr/bin/pipewire
│ ├─wireplumber.service
│ │ └─596 /usr/bin/wireplumber
│ └─pipewire-pulse.service
│ └─597 /usr/bin/pipewire-pulse
├─init.scope
│ ├─579 /lib/systemd/systemd --user
│ └─580 (sd-pam)
└─app.slice
├─dbus.service
│ └─600 /usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
└─speaker-agent.service
└─595 python speaker-agent.py
Reply to this comment
Reply to this comment
JB:
Apr 11, 2023 at 07:20 PM
Thanks Frederic, I did not add the keys for bullseye repo so that's what I can test. Since we have an almost identical setup, that should work. In the Imager I could specify a username and password that I can then use to logon. Perhaps it failed because I first tried another tutorial which didn't work. I'll try again using a clean image. Thanks!
Reply to this comment
Reply to this comment
Luca S:
Apr 19, 2023 at 12:38 PM
Thank you for this nice tutorial!
I managed to get it working. I logged in via ssh in my regular user and set it all up. Had to tweak some settings because the audio was stuttering.
Unfortunately, it stops working as soon as I disconnect. Is that also the behaviour on your side or did I do something wrong? As soon as I log in with ssh it works again (I guess because the user service is started).
I would want it to automatically start the service on boot (similar to ssh).
"systemctl --user status" yields the same results as you previously mentioned here in the comments. Do we need pipewire to run as a system service?
Reply to this comment
Reply to this comment
Frédéric Danis:
Apr 27, 2023 at 10:18 AM
Hi, I just tested the disconnection then re-connection with my RPi connected to a screen and a keyboard, to prevent interaction with an ssh session, and it works fine for me.
Did you try to connect a screen and a keyboard to check that the auto-login session is working fine, then check the speaker-agent service status (systemctl --user status speaker-agent.service) before and after you disconnect?
Reply to this comment
Reply to this comment
Luca S:
Apr 27, 2023 at 04:34 PM
Hi, thank you for the reply! My RPi is running headless. The service gets started as soon as I log in via ssh, but I assume that it stops together with the pipewire service after I disconnect.
With no ssh connection running, my phone still can find the RPi as a bluetooth device. But when I try to connect to it, the attempt fails.
Reply to this comment
Reply to this comment
Frédéric Danis:
Apr 27, 2023 at 09:27 PM
Hi, the behavior you describe sounds to me like the automatic login on boot is not working.
This is required to start pipewire, wireplumber and the speaker-agent.service.
The RPi can run headless, but I think the only way to check if automatic login is working is to temporarily connect the RPi to screen and a keyboard.
Reply to this comment
Reply to this comment
Ayke van Laethem:
Jul 12, 2023 at 01:24 PM
I got a headless setup working. I changed the following things to make this work:
1. You need to disable logind integration: https://wiki.archlinux.org/title/WirePlumber#Keep_Bluetooth_running_after_logout_/_Headless_Bluetooth (create the directory if it doesn't exist yet).
2. You need to make the speaker-agent service a system daemon. Alternatively, I think you can keep the user session alive by running `loginctl enable-linger yourusername`.
You still need to log in once using SSH after the Pi has booted, but it will continue to work afterwards.
Reply to this comment
Reply to this comment
Luca S:
Jul 12, 2023 at 02:53 PM
My setup also works headless now. I didn't do the steps you mentioned. Inititally, I did not read the January 2023 update of this article. The autologin is crucial:
"Depending on the version of RaspberryPi OS Lite the OS does not automatically log in the user created during setup. You will have to select Console Autologin using the raspi-config utility."
That's all I had to do.
Reply to this comment
Reply to this comment
Judasc:
Sep 10, 2024 at 08:42 PM
Honda Goldwings GL1800 had a intercom analog system with analog connection for headphones (5-DIN connector with L-R-G-Mic-G pinout), is there a way to bridge this audio outputs and mic to a usb sound card on the PI and a bluetooth headset connected to the PI?. This will be a solution to use wireless headset with bike intercom system and audio (radio/cd/aux) connection each connector to a exclusive PI.... there is an expensive option with the SENA freewire system.
Reply to this comment
Reply to this comment
George Kiagiadakis:
Sep 20, 2024 at 07:04 AM
Yes, if you can make a cable to link the analog audio to the Pi, the rest should be easy. You don't necessarily need a USB sound card, it could also work with an audio shield. On the software side, the only thing you need to do is to create loopbacks to bridge the audio between the analog input/output and the Bluetooth headset. See https://docs.pipewire.org/page_module_loopback.html
Reply to this comment
Reply to this comment
Add a Comment