https://www.collabora.com/news-and-blog/blog/2022/09/02/using-a-raspberry-pi-as-a-bluetooth-speaker-with-pipewire-wireplumber/ Collabora Logo - Click/tap to navigate to the Collabora website homepage * About + Who we are + Our expertise + Our work + Open Source + Our ecosystem * Services + Guide + Train + Build + Integrate + Optimize + Maintain * Industries + Automotive + Digital TV + Silicon + OEM + VR/AR * News & Blog * Careers * Contact Menu button * About * Services * Industries * News & Blog * Careers * Contact * +44 (0)1223 362967 * +1 514 667 2499 * contact@collabora.com We're hiring! [heroSizer_] * * Home * News & Blog * Blog Using a Raspberry Pi as a Bluetooth speaker with PipeWire Frederic Danis avatar Frederic Danis September 02, 2022 Share this post: [socialShar] [socialShar] [socialShar] [socialShar] [socialShar] 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(r) speakers to play music from your phone? A Raspberry Pi can be easily used as an audio bridge between a Bluetooth(r) 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(r) 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(r) 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. 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(r) 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! ;) Related Posts PipeWire: Bluetooth support status update PipeWire: Bluetooth support status update PipeWire: A year in review & a look ahead PipeWire: A year in review & a look ahead Integrating libcamera into PipeWire Integrating libcamera into PipeWire Related Posts PipeWire: Bluetooth support status update PipeWire: Bluetooth support status update PipeWire: A year in review & a look ahead PipeWire: A year in review & a look ahead Integrating libcamera into PipeWire Integrating libcamera into PipeWire Comments (1) 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 Add a Comment Name: [ ] Email: [ ] Website: [ ] [ ] Notify of New Replies: [ ] Please tick this box to confirm you have read and accept the terms of our privacy notice regarding collection/storage and usage of your personal data: * Allowed tags:
Add a new comment: [ ] [ ] [ ] [ ] [ ] Post Search the newsroom Search [Search news & blog..] [Search] Latest Blog Posts Using a Raspberry Pi as a Bluetooth speaker with PipeWire 02/09/2022 Using PipeWire, WirePlumber and a Raspberry Pi, you can create an audio bridge between a Bluetooth(r) device and an analog speaker system,... Introducing the r600/NIR back-end 07/07/2022 Adventures in NIR-land: the past, the present, and what's lies ahead for the native NIR back-end for Mesa's R600 driver. Adding secondary command buffers to PanVk 15/06/2022 Getting PanVk, an open source driver for Arm Mali Midgard and Bifrost GPUs, closer to conformancy by implementing one of the core Vulkan... Bridging the synchronization gap on Linux 09/06/2022 After fighting with the divide between implicit and explicit synchronization with Vulkan on Linux for over seven years, we may finally have... Monado's hand tracking: hand-waving our way towards a first attempt 31/05/2022 Optical hand tracking for XR has a bit of a reputation - getting training data, training neural nets, and deploying them in real-time, low-latency... Visual-inertial tracking for Monado 05/04/2022 Monado now has initial support for 6DoF ("inside-out") tracking for devices with cameras and an IMU! Three free and open source SLAM/VIO... About Collabora Whether writing a line of code or shaping a longer-term strategic software development plan, we'll help you navigate the ever-evolving world of Open Source. hangugyi guggihangugeo beojeonyi Collabora.com bogi Bandeira de PortuguesAcesse Collabora.com em Portugues Learn more * Who we are * Services * Our expertise * Industries * Our work * Careers * Open Source Collabora on Twitter Collabora on YouTube Collabora on Mastodon Collabora on LinkedIn Collabora on Facebook Collabora RSS Feed +44 1223 362967 +1 514 667 2499 contact@collabora.com 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 (c) 2005-2022. All rights reserved. Privacy Notice. Sitemap. To ensure the Collabora website works as designed, please enable JavaScript. Thanks