We're hiring!
*

Using a Raspberry Pi as a Bluetooth speaker with PipeWire

Frederic Danis avatar

Frederic Danis
September 02, 2022

Share this post:

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 select Console Autologin using the raspi-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! ;)

Comments (62)

  1. 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

    1. 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

    2. 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

      1. 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

        1. 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

      2. 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

    3. 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

  2. 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

  3. 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

  4. 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

    1. 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

      1. 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

      2. 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

  5. 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

    1. 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

      1. 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

        1. 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

          1. 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

            1. 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

    2. 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

  6. 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

    1. 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

      1. 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

      2. 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

        1. 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

    2. 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

  7. iplakora:
    Sep 19, 2022 at 11:26 AM

    Buy bluetooth speakers in Ghana Buy Bluetooth Speakers in Ghana. There are many options when it comes to choosing Bluetooth speakers. Stud100 from Kora is the best speaker and travel friendly. You can carry it anywhere with you

    Reply to this comment

    Reply to this comment

  8. 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

    1. 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

      1. 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

  9. 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

    1. 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

      1. 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

  10. 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

    1. 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

  11. 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

    1. 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

      1. 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

        1. George Kiagiadakis:
          Nov 02, 2022 at 06:15 PM

          Yes, that all sounds correct!

          Reply to this comment

          Reply to this comment

  12. 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

    1. 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

  13. 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

  14. 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

  15. 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

    1. 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

  16. 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

    1. 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

  17. 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

  18. 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

  19. 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

  20. 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

    1. 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

  21. 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

    1. 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

      1. 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

  22. 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

    1. 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

      1. 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

        1. 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

    2. 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

      1. 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


Add a Comment






Allowed tags: <b><i><br>Add a new comment:


Search the newsroom

Latest Blog Posts

Automatic regression handling and reporting for the Linux Kernel

14/03/2024

In continuation with our series about Kernel Integration we'll go into more detail about how regression detection, processing, and tracking…

Almost a fully open-source boot chain for Rockchip's RK3588!

21/02/2024

Now included in our Debian images & available via our GitLab, you can build a complete, working BL31 (Boot Loader stage 3.1), and replace…

What's the latest with WirePlumber?

19/02/2024

Back in 2022, after a series of issues were found in its design, I made the call to rework some of WirePlumber's fundamentals in order to…

DRM-CI: A GitLab-CI pipeline for Linux kernel testing

08/02/2024

Continuing our Kernel Integration series, we're excited to introduce DRM-CI, a groundbreaking solution that enables developers to test their…

Persian Rug, Part 4 - The limitations of proxies

23/01/2024

This is the fourth and final part in a series on persian-rug, a Rust crate for interconnected objects. We've touched on the two big limitations:…

How to share code between Vulkan and Gallium

16/01/2024

One of the key high-level challenges of building Mesa drivers these days is figuring out how to best share code between a Vulkan driver…

Open Since 2005 logo

We use cookies on this website to ensure that you get the best experience. By continuing to use this website you are consenting to the use of these cookies. To find out more please follow this link.

Collabora Ltd © 2005-2024. All rights reserved. Privacy Notice. Sitemap.