Audio Output Management

Switch audio output between monitors, headphones, and speakers using PipeWire/WirePlumber.

Quick Start

# List available audio outputs (sinks)
wpctl status
# Set default output (replace <sink_id> with number from above)
wpctl set-default <sink_id>
Example: Switch to HDMI output
wpctl set-default 96

Core Commands

wpctl (WirePlumber)

Primary tool for PipeWire audio management.

# Show full audio status (sinks, sources, streams)
wpctl status
# Set default audio output
wpctl set-default <sink_id>
# Adjust volume
wpctl set-volume @DEFAULT_AUDIO_SINK@ 50%      # Set to 50%
wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+      # Increase 5%
wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-      # Decrease 5%
# Mute/unmute
wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
# Get current volume
wpctl get-volume @DEFAULT_AUDIO_SINK@

pactl (PulseAudio compatibility)

PipeWire provides PulseAudio compatibility layer.

# List sinks (short format)
pactl list sinks short
# Set default sink by name
pactl set-default-sink <sink_name>
# Volume control
pactl set-sink-volume @DEFAULT_SINK@ +5%    # Up
pactl set-sink-volume @DEFAULT_SINK@ -5%    # Down
pactl set-sink-volume @DEFAULT_SINK@ 50%    # Set
# Mute toggle
pactl set-sink-mute @DEFAULT_SINK@ toggle

Identify Audio Sinks

Using wpctl status

wpctl status
Example output
Audio
 ├─ Sinks:
 │      63. 800 Series ACE Headphones [vol: 1.00]
 │      64. 800 Series ACE HDMI / DisplayPort 3 Output [vol: 1.00]
 │  *   96. GB203 High Definition Audio Controller Digital Stereo (HDMI) [vol: 0.40]

The * marks the current default sink.

Using pactl

pactl list sinks short

Common Scenarios

Switch to HDMI/DisplayPort

wpctl status | grep -i hdmi
wpctl set-default <sink_id>

Switch to Headphones

wpctl status | grep -i headphone
wpctl set-default <sink_id>

Move Running Application

# List running audio streams
wpctl status
# Move stream to different output
pactl move-sink-input <stream_id> <sink_id>

Shell Functions

Add to ~/.zshrc or ~/.bashrc:

audio-hdmi
audio-hdmi() {
    local sink=$(wpctl status | grep -i "hdmi\|displayport" | head -1 | awk '{print $1}' | tr -d '.')
    if [[ -n "$sink" ]]; then
        wpctl set-default "$sink"
        echo "Switched to HDMI/DisplayPort: sink $sink"
    else
        echo "No HDMI/DisplayPort sink found"
    fi
}
audio-headphones
audio-headphones() {
    local sink=$(wpctl status | grep -i headphone | head -1 | awk '{print $1}' | tr -d '.')
    if [[ -n "$sink" ]]; then
        wpctl set-default "$sink"
        echo "Switched to Headphones: sink $sink"
    else
        echo "No Headphones sink found"
    fi
}
audio-select (requires fzf)
audio-select() {
    local sink=$(wpctl status | grep -E "^\s+[0-9]+\." | \
        sed 's/^[ *]*//' | \
        fzf --prompt="Select audio output: " | \
        awk '{print $1}' | tr -d '.')
    if [[ -n "$sink" ]]; then
        wpctl set-default "$sink"
        echo "Switched to sink $sink"
    fi
}
Volume aliases
alias vol='wpctl get-volume @DEFAULT_AUDIO_SINK@'
alias vol+='wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+'
alias vol-='wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-'
alias mute='wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle'

GUI Tools

pavucontrol

  • Arch

  • Fedora/RHEL

  • Debian/Ubuntu

sudo pacman -S pavucontrol
sudo dnf install pavucontrol
sudo apt install pavucontrol
pavucontrol

qpwgraph (PipeWire node graph)

  • Arch

  • Fedora/RHEL

sudo pacman -S qpwgraph
sudo dnf install qpwgraph
qpwgraph

Troubleshooting

No Sound After Switching

# Check if sink is suspended
pactl list sinks short
# Restart audio stack
systemctl --user restart pipewire pipewire-pulse wireplumber

HDMI Audio Not Appearing

# Reload WirePlumber
systemctl --user restart wireplumber
# Check kernel audio devices
cat /proc/asound/cards

Persist Default Sink

Create WirePlumber rule:

mkdir -p ~/.config/wireplumber/wireplumber.conf.d/
~/.config/wireplumber/wireplumber.conf.d/50-default-sink.conf
monitor.alsa.rules = [
  {
    matches = [
      {
        node.name = "alsa_output.pci-0000_02_00.1.hdmi-stereo"
      }
    ]
    actions = {
      update-props = {
        priority.session = 2000
      }
    }
  }
]
systemctl --user restart wireplumber

Quick Reference

Task Command

List audio sinks

wpctl status

Switch default output

wpctl set-default <sink_id>

Get volume

wpctl get-volume @DEFAULT_AUDIO_SINK@

Set volume

wpctl set-volume @DEFAULT_AUDIO_SINK@ 50%

Mute toggle

wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle

Restart audio

systemctl --user restart pipewire wireplumber