George Kiagiadakis
May 05, 2026
Reading time:
In March 2026, Collabora participated in the Embedded World trade show in Nuremberg, like every year, as an exhibitor. One of our many demos on the trade show floor was an Auracast™ transmitter, broadcasting audio from a Mediatek Genio 700 Evaluation Kit (EVK) with an MT7921 Bluetooth® controller, using Debian Linux, BlueZ, and PipeWire. In this post, I'll walk you through how this demo was set up, in the hope that it will be useful to early adopters and other developers who want to try this themselves. The user interfaces needed to make Auracast™ easy to use don't really exist yet and practical documentation is still scarce, so this is a good opportunity to share what we learned along the way. All the scripts and configuration files used in this demo are available in our public repository.

On the transmitter side, we used a Mediatek Genio 700 EVK with an MT7921 Bluetooth® module connected via M.2. For the audio source, we had a RODECaster Video — the same device driving the presentation videos on the monitor above — connected over USB. Linux sees it as a standard USB audio class device, so no special drivers were needed.
The signal chain at the booth looked like this: audio content played on the RODECaster Video was captured by the Genio 700 EVK over USB, routed through PipeWire into the broadcast path, and then transmitted by BlueZ as an Auracast™ stream over Bluetooth® LE Audio. On the receiving end, multiple devices picked up the same broadcast simultaneously.
For receivers, we used a mix of JBL Go 4 speakers, Creative Zen Hybrid Pro headphones, and several other Auracast™-capable gadgets. Having a variety of vendors' products on the table was deliberate: a broadcast demo is only convincing when it works across different hardware, not just with one carefully curated pair of devices.
The demo ran on one of the Debian images that Collabora builds for MediaTek Genio platforms. If you haven't seen this work yet, we published a status update on kernel enablement and image availability for Genio boards last year. These images gave us a reliable baseline at the booth: known-good userspace, predictable kernel integration, and the ability to iterate quickly on Bluetooth® and audio stack changes without worrying about the rest of the system.
On top of the distribution-provided Linux kernel 6.18.5, we built BlueZ 5.86, PipeWire 1.6.0, and WirePlumber 0.5.13 from source, replacing the older versions of those components that are provided by Debian. This combination gave us a stable foundation, with access to the latest Bluetooth® LE Audio and Auracast™ functionality that is built into the latest versions of BlueZ and PipeWire.
Setting up an Auracast™ source today involves several moving parts that all need to be in place before anything works: BlueZ itself, the broadcast advertisement, the WirePlumber audio policy, and the runtime services. Let me walk through each.
If you've read my previous post on implementing Bluetooth® LE Audio & Auracast™ on Linux, this will look familiar. The first step is enabling LE Audio in BlueZ's /etc/bluetooth/main.conf, including the ISO socket UUID in the kernel experimental options:
Experimental = true KernelExperimental = ...,
Beyond that, a BlueZ build with the full LE Audio profile set is required. We built BlueZ 5.86 with BAP, BASS, VCP, MCP, MICP, CCP, CSIP, and TMAP all enabled, along with experimental APIs. Also, as discussed in my previous post, if you want to try this with a different controller, it's worth verifying that it reports iso-broadcaster in bluetoothctl's management menu before going further, as not all Bluetooth® controllers support it.
Broadcast advertising is handled through a bluetoothctl script. Here is the one we used:
advertise.name "Collabora" # # Public Broadcast Profile (0x02 == SQ / 0x04 == HQ), 0x00 = no LTV metadata advertise.service 0x1856 0x04 0x00 # # Broadcast_name AD: "Collabora BlueZ Auracast" advertise.data 0x30 25 9 67 111 108 108 97 98 111 114 97 32 66 108 117 101 90 32 65 117 114 97 99 97 115 116 # # Broadcasting Device (0x0885) advertise.appearance 2181 # # Harman (87) - JBL Go 4 compatibility advertise.manufacturer 87 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0xdf 0xfd # advertise on
The key parts are the Public Broadcast Profile service UUID (0x1856), which is what tells receivers this is an Auracast™ source, and the Broadcast_name AD type (0x30), which is the human-readable stream name that appears when a receiver scans for available broadcasts. You'll notice the broadcast name is written as a sequence of decimal numbers rather than a string — this is a limitation of bluetoothctl, which only accepts raw numeric bytes for arbitrary advertising data. The numbers are simply the ASCII codes of each character: 67 111 108 ... decodes to "Collabora", and so on.
The advertise.appearance line sets the Bluetooth® appearance code to 0x0885, which identifies the device as a "Broadcasting Device" in the Bluetooth® assigned numbers. Including it is optional, but it can help receivers and scanning tools display a more descriptive device type.
The manufacturer data entry for Harman (company ID 87) is a known JBL quirk, documented in Bumble's compatibility notes: when the JBL Go 4 is in Auracast™ receiver mode, it will only connect to broadcasts that include this specific manufacturer data in the advertisement. Without it, the speaker simply ignores the broadcast entirely.
The audio side of the broadcast source is configured via a WirePlumber drop-in. Here is ours:
monitor.bluez.properties = {
bluez5.bcast_source.config = [
{
"adapter": "1C:CE:51:F5:0C:B2",
"encryption": false,
"sync_factor": 2,
"bis": [
{
"qos_preset": "48_2_2",
"audio_channel_allocation": 0,
"metadata": [
# Streaming Audio Contexts
{ "type": 2, "value": [ 64, 0 ] }
# Program Info: Collabora Demo
{ "type": 3, "value": [ 67 111 108 108 97 98 111 114 97 32 68 101 109 111 ] }
# Language: eng
{ "type": 4, "value": [ 101 110 103 ] }
]
},
]
}
]
}
A few things are worth explaining here. The adapter field pins the broadcast source to a specific Bluetooth® controller by MAC address, which is important when you have multiple controllers in the system (as we did, with the second one dedicated to Bumble — see the Monitoring section below).
The bis array defines the Broadcast Isochronous Streams — one entry per stream — and each entry carries three key fields that together define how that stream is transmitted and identified. The first, qos_preset, selects a predefined codec configuration from the Bluetooth® Basic Audio Profile (BAP) specification. The value 48_2_2 corresponds to a setting with 48 kHz sampling rate, high reliability, and high latency. The second field, audio_channel_allocation, is a bitfield describing which audio channels this stream carries: 0 means mono, 1 is front left, 2 is front right, 3 is front left + right (stereo), and so on, following the Bluetooth® channel allocation assigned values. The third field, metadata, carries additional stream descriptors and is explained below. Crucially, it is possible to define multiple BIS entries — each with its own preset, channel allocation, and metadata — making it possible to broadcast multiple simultaneous streams in different languages, for instance, which is one of the more compelling features of Auracast™.
The metadata fields are worth unpacking because the format is not exactly self-explanatory. The program info (type: 3) and language (type: 4) values are strings encoded as ASCII bytes — 67 111 108 108 97 98 111 114 97 32 68 101 109 111 is "Collabora Demo", and 101 110 103 is "eng" — for the same reason as the advertising data above: the configuration format only accepts numeric values. The audio context (type: 2) is a 2-byte little-endian integer: [ 64, 0 ] is 0x0040, which corresponds to the "Live Audio" streaming context as defined in the Bluetooth® specification.
This verbosity is a known pain point. The current WirePlumber configuration format for broadcast sources mirrors the BlueZ low-level options and Bluetooth® packet structures fairly directly, which makes it powerful but impenetrable for anyone without the spec open in front of them. Improving this — with a more human-readable, higher-level interface — is something we intend to address. But if you are determined to work with it as-is and you want to understand things better, I'd strongly recommend that you read the LE Audio Book first — I myself couldn't make sense of this configuration until I read it.
We also had a separate WirePlumber drop-in to disable the board's internal ALSA sound card, which prevented it from competing as the default audio route and kept the signal flow deterministic throughout the demos.
The runtime was organized as a set of systemd user services: an advertiser service that runs the bluetoothctl script above, a sink service that creates a PipeWire virtual sink using pw-loopback that routes to the BlueZ broadcast output node, and an audio link service that links the default ALSA input (the RODECaster Video, in our case) to that virtual sink, again using pw-loopback.
One important caveat: the startup order matters a lot. The advertiser service must be started before the BlueZ broadcast output node starts streaming. This has to do with the HCI (Host-Controller Interface) commands that are sent to the controller, which must be sent in a particular order according to the Bluetooth® specs. The node will start streaming when it is linked to another node, which happens when the virtual sink service is started. This is also the reason why I created this virtual sink: to be able to start/stop streaming independently from whether there was a source present or not during my testing. Obviously, the audio link service then has to be started last. But once everything is up, the system runs unattended.
My initial idea was to use systemd dependencies to make those services start in that particular order, but this proved unreliable because the various scripts take some time to execute and they don't have any way to give feedback to systemd when they are done loading, so it's impossible to make this work just using dependencies.
To solve that problem and also make booth operation smoother, I "vibe coded" a small GTK4 control panel with start/stop buttons for each service and live status indicators. It's a simple tool, but it made the demo substantially more robust: quick resets, easy recovery if anything were to break (which thankfully didn't happen), and no need to SSH in and type commands under pressure.
As an additional feature of the demo, we turned the Genio's internal display into an Auracast™ scanner using Bumble — an alternative Bluetooth® stack written in Python that runs entirely in userspace. Unlike BlueZ, Bumble is primarily a development and testing tool, but it comes with some very handy built-in utilities, including this Auracast™ scanner that can discover broadcasts and display their metadata.
We ran Bumble's scanner (bumble-auracast scan) on a dedicated second Bluetooth® controller, an ASUS BT540 USB adapter, keeping it entirely separate from the MT7921 that was doing the actual broadcasting. This meant Bumble was acting as a genuine independent receiver, seeing exactly what any other Auracast™-capable device in the room would see.
That turned out to be a very valuable part of the demo, and not just for debugging. Auracast™ broadcasts carry rich metadata: stream names, language tags, audio quality information, and support for multiple simultaneous streams. We kept the scanner output visible on a terminal window throughout the demo, and it became a natural focal point for conversations with booth visitors. People could see in real time what a receiver discovers when it scans for Auracast™ sources — the broadcast name, the available streams, the language of each — and that made it much easier to explain what makes Auracast™ interesting beyond the basic "wireless audio to many devices" pitch.
The demo worked well, but it also made clear where the gaps still are.
The CLI tooling and end-to-end workflow for setting up an Auracast™ source need significant improvement. As you can tell from the setup described above, building a robust configuration today still requires deep familiarity with multiple software layers and quite a few moving parts. There are active discussions in the community about how to streamline this, in terms of better bluetoothctl commands, better WirePlumber integration, and improved documentation.
Additionally, desktop integration is just starting to be discussed more seriously. For Auracast™ to reach beyond developer-focused setups, we'll need proper user-facing controls for discovering, selecting, and managing broadcast streams — the kind of experience users already expect from Wi-Fi or classic Bluetooth® pairing.
Finally, official qualification remains a significant milestone ahead. We're making progress, but getting the full BlueZ + PipeWire stack through official Bluetooth® SIG qualification is substantial work and realistically extends into 2027.
Shipping Bluetooth® LE Audio and Auracast™ on embedded Linux requires careful integration across Kernel, BlueZ, PipeWire, policy configuration, and hardware validation. Demos like this one are valuable precisely because they expose both what already works well and what still needs engineering effort to become truly product-grade.
If you're evaluating Bluetooth® LE Audio or Auracast™ for your own device, our team has hands-on experience with this entire stack and can help with platform bring-up, configuration, interoperability validation, and qualification planning. Get in touch to discuss your use case!
05/05/2026
Collabora brought Bluetooth Auracast broadcasting to MediaTek Genio 700 for Embedded World 2026. Here's the complete, fully Open Source…
22/04/2026
Using our XR expertise, Collabora created a standalone XR experience for our 1% for the Planet partner, SOMAR, to showcase the direct impact…
17/04/2026
BitNet-style ternary brings LLM inference to ExecuTorch via its Vulkan backend, enabling much smaller, bandwidth-efficient models with portable…
23/03/2026
PanVK’s new framebuffer abstraction for Mali GPUs removes OpenGL-specific constraints, unlocking more flexible tiled rendering features…
02/03/2026
Get the recap of Nicolas Frattaroli's FOSDEM talk detailing Rockchip’s mainline progress, including Vulkan 1.4 and NPU support as a vital…
02/12/2025
As an active member of the freedesktop community, Collabora was busy at XDC 2025. Our graphics team delivered five talks, helped out in…