DEV Community

Cover image for Custom Audio Control on Linux: Switch Between Headphones, Speakers, and Dual Audio with a Single Command
Igor Giamoniano
Igor Giamoniano

Posted on

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

Custom Audio Control on Linux: Switch Between Headphones, Speakers, and Dual Output with a Single Command

TL;DR: I created a script called audioctl that, with a single
command, lets me switch between headphones (via HDMI), analog speakers,
or even 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:

  • My headphones are connected to the monitor, which is connected to the PC via HDMI.
  • My 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. In this post, I'll show you step by step
how I built this tool --- and how you can adapt it to your own setup.

VScode Terminal with program interface


Prerequisites

  • A modern Linux system (Ubuntu, Fedora, Arch, NixOS, etc.)
  • 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

Before automating anything, we need to know which devices exist.

List your sinks (audio outputs):

pactl list sinks short
Enter fullscreen mode Exit fullscreen mode

Example output:

52  alsa_output.pci-0000_01_00.1.hdmi-stereo     ...  RUNNING
57  alsa_output.pci-0000_09_00.6.analog-stereo   ...  SUSPENDED
Enter fullscreen mode Exit fullscreen mode
  • RUNNING = in use\
  • SUSPENDED = available but idle

List audio cards:

pactl list cards
Enter fullscreen mode Exit fullscreen mode

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:

@DEFAULT_SINK@

# Increase volume by 5%
pactl set-sink-volume @DEFAULT_SINK@ +5%

# Decrease volume by 5%
pactl set-sink-volume @DEFAULT_SINK@ -5%
Enter fullscreen mode Exit fullscreen mode

Step 3: Switch Audio Outputs

Set the default sink:

pactl set-default-sink SINK_NAME
Enter fullscreen mode Exit fullscreen mode

Move active streams manually:

pactl list short sink-inputs
pactl move-sink-input STREAM_ID NEW_SINK
Enter fullscreen mode Exit fullscreen mode

Step 4: Audio on Two Devices at the Same Time (Dual Mode)

pactl load-module module-combine-sink     sink_name=combined_output     slaves=alsa_output.hdmi,alsa_output.analog     sink_properties=device.description="Dual_HDMI+Analog"
Enter fullscreen mode Exit fullscreen mode

Step 5: The Final Script --- audioctl

#!/bin/bash
# (full script omitted here for brevity — same as original)
Enter fullscreen mode Exit fullscreen mode

Installation

chmod +x ~/projects/audioctl
mkdir -p ~/bin
ln -sf ~/projects/audioctl ~/bin/audioctl
Enter fullscreen mode Exit fullscreen mode

Ensure ~/bin is in PATH:

export PATH="$HOME/bin:$PATH"
Enter fullscreen mode Exit fullscreen mode

Reload shell:

source ~/.bashrc
Enter fullscreen mode Exit fullscreen mode

Extra Tips

Test with continuous audio:

speaker-test -t wav -c 2
Enter fullscreen mode Exit fullscreen mode

Keyboard shortcuts (GNOME/KDE/i3):

  • Super + F11audioctl toggle
  • Super + F12audioctl dual

Debug & Useful References

Quick debug commands:

pactl list sinks short
pactl get-default-sink
pactl list short sink-inputs
pactl list cards
Enter fullscreen mode Exit fullscreen mode

Official References:


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

Top comments (0)