Custom Audio Control on Linux: Switch Between Headphones, Speakers, and Dual Audio with a Single Command
Source: Dev.to

TL;DR: I created a script called audioctl that, with a single command, lets me switch between headphones (via HDMI), analog speakers, or play audio through both at the same time. All using pactl, some Bash, and the power of Linux.
What is pactl?
pactl (short for PulseAudio Control) is a command‑line tool used to control audio servers such as PulseAudio and, with full compatibility, PipeWire — the modern successor to PulseAudio, now default in distros like Fedora, Ubuntu 22.04+, Arch, and NixOS.
With it you can:
- List audio devices (sinks and sources)
- Change volume
- Switch between outputs
- Move audio streams between devices
- Load or unload modules (such as
module-combine-sink)
It’s the “Swiss Army knife” of terminal audio — and the foundation for everything we’ll build in this tutorial.
The Problem
I use a simple but common setup:
- Headphones are connected to the monitor, which is connected to the PC via HDMI.
- Speakers are connected to the analog audio output of the computer.
My father‑in‑law needed to switch between speakers and headphones — something he could already do in the UI — but he also needed the ability to enable both at the same time (for accessibility reasons).
So I thought: Linux gives me full system control — why not create my own audio controller?
That’s exactly what I did. Below is a step‑by‑step guide to building the tool and adapting it to your own setup.
Prerequisites
- A modern Linux system (Ubuntu, Fedora, Arch, NixOS, etc.) with PulseAudio or PipeWire.
- Terminal and a text editor.
- At least two working audio outputs.
💡 To check whether you’re using PipeWire or PulseAudio:
pactl info | grep "Server Name"
If it shows “PipeWire” or “PulseAudio,” you’re good to go!
Step 1: Understand Your Audio Setup
List sinks (audio outputs)
pactl list sinks short
Example output
52 alsa_output.pci-0000_01_00.1.hdmi-stereo ... RUNNING
57 alsa_output.pci-0000_09_00.6.analog-stereo ... SUSPENDED
RUNNING= currently in useSUSPENDED= available but idle
List audio cards
pactl list cards
Look for the analog device and confirm the active profile (e.g., output:analog-stereo).
Step 2: Basic Volume Control
pactl can control the default sink’s volume using the special identifier @DEFAULT_SINK@.
# Increase volume by 5%
pactl set-sink-volume @DEFAULT_SINK@ +5%
# Decrease volume by 5%
pactl set-sink-volume @DEFAULT_SINK@ -5%
Step 3: Switch Audio Outputs
Set the default sink:
pactl set-default-sink SINK_NAME
Move active streams manually:
pactl list short sink-inputs
pactl move-sink-input STREAM_ID NEW_SINK
Step 4: Audio on Two Devices at the Same Time (Dual Mode)
Create a combined sink that forwards audio to both HDMI and analog outputs:
pactl load-module module-combine-sink \
sink_name=combined_output \
slaves=alsa_output.hdmi,alsa_output.analog \
sink_properties=device.description="Dual_HDMI+Analog"
Step 5: The Final Script — audioctl
#!/usr/bin/env bash
# audioctl – simple audio output switcher
# (Full script omitted for brevity; see the “Full Code” section for the complete version)
# Example skeleton:
# - Detect available sinks
# - Accept commands: toggle, speakers, headphones, dual
# - Use pactl to set default sink or load combined sink
Installation
chmod +x ~/projects/audioctl
mkdir -p ~/bin
ln -sf ~/projects/audioctl ~/bin/audioctl
Make sure ~/bin is in your PATH:
export PATH="$HOME/bin:$PATH"
Reload your shell configuration:
source ~/.bashrc
Extra Tips
Test with continuous audio:
speaker-test -t wav -c 2
Keyboard shortcuts (GNOME/KDE/i3)
Super + F11→audioctl toggleSuper + F12→audioctl dual
Debug & Useful References
Quick debug commands:
pactl list sinks short
pactl get-default-sink
pactl list short sink-inputs
pactl list cards
Official References
- PulseAudio CLI docs
- PipeWire docs
module-combine-sinkdocs
Conclusion
With less than 60 lines of Bash, I solved a real problem — and gained flexibility no graphical app offers.
✨ Control is in your hands — and in the terminal.
Full Code
https://gist.github.com/igorgbr/8031267dee77acf6d7d298ec72a37f94