Pipewire: Change per-application output sink

I wanted the comfort of switching the audio output for running application through a custom keyboard shortcut. For that I looked into the abyss of Pipewire, PulseAudio and wireplumber applications. By looking through the output of different tools, like pactl, pw-cli, … and finally wpctl. The easiest way to achieve this could be by parsing the output of wpctl provided by wireplumber.

For my solution you need:

  • wireplumber (wpctl)
  • rofi
  • pactl

Shell script: pw-change-sink


set -euo pipefail

rofi_cmd() {
    rofi "$@"

outputs="$(pactl list sinks \
    | awk '/Sink/ {sink=$2} /Description:/ {desc=substr($0, length($1)+3, length($0)-length($1)) ; print sink ";" desc}' \
    | sed -n -E 's/^#([0-9]+);(.*)/\1\t\2/p' \
    | tr -d '"')"
streams="$(pactl list sink-inputs \
    | awk '/Sink Input/ {sink=$3} /application.name =/ {print sink ";" $3}' \
    | tr -d '#' \
    | tr -d '"' \
    | tr ';' '\t')"

selected_stream="$(echo "$streams" | rofi_cmd -dmenu -i -p "Active Audio Streams" | awk '{print $1}')"
selected_output="$(echo "$outputs" | rofi_cmd -dmenu -i -p "Available Output Devices" | awk '{print $1}')"

pactl move-sink-input "$selected_stream" "$selected_output"

notify-send -u low --icon=speaker "Audio" "Output for applicationchanged."

The rofi_cmd is a placeholder for future features, like overwriting the configuration.

When executed only active audio streams are shown. If you are not running an application outputting audio at the moment, you will not see any “Active Audio Stream”.