Skip to content

Conversational Awareness volume ducking not implemented in Linux Qt client — workaround included #498

@cwtopel

Description

@cwtopel

Environment:

  • OS: Arch Linux, KDE Plasma
  • LibrePods: Qt-based Linux client (current stable)
  • AirPods: Pro 3rd Gen (Model A3064)
  • Bluetooth adapter: TP-Link UB500 (RTL8761BU)
  • Audio: PipeWire 1.6.2 (PulseAudio compat layer)

Problem:

Conversational Awareness is correctly detected and the AirPods themselves respond properly (switching to transparency mode on voice detected), but no volume ducking occurs on the Linux side. The full CA event cycle is visible in logs:

librepods:  Setting conversational awareness to:  enabled
librepods:  Conversational awareness state received:  true
librepods:  Received conversational awareness data
librepods:  Conversational awareness event: voice detected
librepods:  Noise control mode received:  AirpodsTrayApp::Enums::NoiseControlMode::Adaptive
librepods:  Noise control mode received:  AirpodsTrayApp::Enums::NoiseControlMode::Transparency
librepods:  Received conversational awareness data
librepods:  Conversational awareness event: voice ended

The AirPods switch to transparency mode correctly on voice detected, and back on voice ended. However, LibrePods takes no action on the PipeWire/PulseAudio side — system volume is unchanged.

Root cause:

Volume ducking on voice detected / voice ended events appears to not be implemented in the current Qt-based Linux client. Searching the binary confirms no PulseAudio/volume calls are made in response to CA events.

Additional notes:

There is also a persistent phone socket error on this adapter:

qt.bluetooth.bluez: Invalid address to remote address passed.
librepods:  Phone socket error:  QBluetoothSocket::SocketError::UnsupportedProtocolError,
           "Invalid Bluetooth address passed to connectToService()"
librepods:  Phone socket is not open, cannot relay packet

This is a known RTL8761BU limitation (also reported in #295) and does not appear to affect CA event detection — the events are received correctly regardless.

Workaround:

Until this is implemented natively, the following wrapper script restores volume ducking behavior by monitoring LibrePods log output and calling pactl directly. It includes a 5-second sticky hold so brief pauses in speech don't immediately restore volume, and suppresses the KDE Plasma volume OSD during operation:

#!/bin/bash
LOW_VOL=40%
HIGH_VOL=70%
HOLD_SECS=6
TIMER_PID=

# Disable KDE volume OSD
kwriteconfig6 --file plasmarc --group OSD --key Enabled false
qdbus org.kde.plasmashell /PlasmaShell refreshCurrentShell 2>/dev/null

cleanup() {
    # Re-enable KDE volume OSD on exit
    kwriteconfig6 --file plasmarc --group OSD --key Enabled true
    qdbus org.kde.plasmashell /PlasmaShell refreshCurrentShell 2>/dev/null
    kill $TIMER_PID 2>/dev/null
}
trap cleanup EXIT

librepods 2>&1 | while read line; do
    if echo "$line" | grep -q "voice detected"; then
        pactl set-sink-volume @DEFAULT_SINK@ $LOW_VOL
        kill $TIMER_PID 2>/dev/null
        (sleep $HOLD_SECS && pactl set-sink-volume @DEFAULT_SINK@ $HIGH_VOL) &
        TIMER_PID=$!
    fi
done

Non-KDE users can remove the kwriteconfig6 and qdbus lines. The LOW_VOL, HIGH_VOL, and HOLD_SECS variables can be adjusted to taste.

Expected behavior:

When voice detected fires, system volume should duck to a lower level. When voice ended fires (or after a timeout), volume should restore.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions