pw-duck lowers music, games, videos, and other playback while people are speaking in a selected voice-call stream.
It is built for PipeWire desktops and controlled from a tray icon.
- Automatic ducking for non-call audio
- Voice-call stream selection from running playback streams
- Tray toggle for ducking on/off
- Sensitivity, ducking volume, and hold-time tuning
paru -S pw-duckThen start pw-duck from your launcher or run:
pw-duckFrom this repository:
nix run .#Other app outputs:
nix run .#tray
nix run .#tune
nix run .#tune-guicargo build --release
cargo build --release --features guiThe build needs Rust plus PipeWire/pkg-config development libraries. The gui feature also needs GTK4.
- PipeWire with a compatible session manager, for example WirePlumber
- PulseAudio compatibility (
pactlmust work) pw-link- A StatusNotifierItem/SNI tray host
- GTK4 for the graphical tuner
KDE Plasma supports SNI natively. GNOME needs an AppIndicator/KStatusNotifierItem extension.
- Join a voice call so the call playback stream exists.
- Start
pw-duck. - In the tray menu, choose
Source: choose. - Select the stream that contains the call audio.
- Enable
Ducking. - Adjust
Tuner: openif needed.
pw-duck # start tray
pw-duck tray # start tray explicitly
pw-duck sources # list selectable playback streams
pw-duck select-source 5 # select stream by sink-input index
pw-duck status # show current audio state
pw-duck tune # terminal tuner
pw-duck tune-gui # graphical tuner, if built with gui
pw-duck config-path # print config pathIf sources shows a stream as #546, pass only the number:
pw-duck select-source 546- Sensitivity: how easily call speech is detected;
0%disables detection. - Ducking volume: volume for non-call audio while speech is active.
- Hold: delay before normal volume is restored after speech stops.
Settings are saved to:
~/.config/pw-duck/config.toml
While ducking is enabled, pw-duck creates a temporary virtual PipeWire sink and routes non-call playback through it. The selected call stream stays on the normal output path and is used only for detection.
On shutdown, streams are moved back. If that cannot be done safely, the virtual sink is left alive instead of breaking active application audio.
- On GNOME, enable an AppIndicator/KStatusNotifierItem extension.
- Restart
pw-duckif your tray host cached an old icon.
- Join a call first; many apps create playback streams only while audio is active.
- Run
pw-duck sourcesand pick the stream that contains the call audio.
- Check the selected source.
- Increase sensitivity.
- Make sure sensitivity is not
0%. - Run
pw-duck status.
Use the dev shell:
direnv exec . cargo fmt --check
direnv exec . cargo check
direnv exec . cargo test
direnv exec . cargo check --features guiRegenerate icons after editing assets/icons/source/*.png:
scripts/generate-icons.shBuild the Nix package:
nix build .#MIT