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

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

posted Originally published at dev.to 3 min read

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

Introduction

Linux users know that when it comes to system-level control, almost everything is possible — including building your own solutions for problems that graphical interfaces don’t solve well.

In this article, I introduce audioctl, a small Bash script that allows you to switch, with a single command, between:

  • Headphones connected via HDMI
  • Analog speakers
  • Both outputs at the same time (dual mode)

All of this is done using pactl, a bit of Bash, and the flexibility of the Linux audio stack.

TL;DR:
With less than 60 lines of Bash, I built a custom audio controller that gives me more flexibility than any GUI tool.


The Problem

My setup is simple and very common:

  • My headphones are connected to the monitor, which connects to the PC via HDMI
  • My speakers are connected to the analog audio output of the motherboard

My father-in-law needed to switch between headphones and speakers — something already possible via the desktop UI — but he also needed to listen to audio on both devices at the same time, for accessibility reasons.

That’s when I thought:

“If Linux gives me full system control, why not build my own audio controller?”


What Is pactl and Why It Matters

pactl (PulseAudio Control) is a command-line utility used to control audio servers such as:

  • PulseAudio
  • PipeWire (fully compatible and now the default on many distributions)

With pactl, you can:

  • List audio devices (sinks and sources)
  • Change volume levels
  • Switch default outputs
  • Move audio streams between devices
  • Load audio modules like module-combine-sink

It’s essentially the Swiss Army knife of Linux audio — and the foundation of this entire solution.


Prerequisites

Before continuing, make sure you have:

  • A modern Linux distribution (Ubuntu, Fedora, Arch, NixOS, etc.)
  • PulseAudio or PipeWire
  • A terminal and text editor
  • At least two working audio outputs

Tip: To check which audio server you’re using:

pactl info | grep "Server Name"

Step 1: Understand Your Audio Setup

Before automating anything, you need to understand which audio devices are available.

List all 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 use
  • SUSPENDED → available but idle

List audio cards:

pactl list cards

Here you can verify active profiles such as output:analog-stereo.


Step 2: Basic Volume Control with pactl

pactl provides a very useful alias:

@DEFAULT_SINK@

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

# Decrease volume
pactl set-sink-volume @DEFAULT_SINK@ -5%

This allows you to build volume controls that work regardless of the active device.


Step 3: Switching Audio Outputs

Set a default sink:

pactl set-default-sink SINK_NAME

Move active audio streams manually:

pactl list short sink-inputs
pactl move-sink-input STREAM_ID NEW_SINK

These commands are core building blocks for the final script.


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

This is where things get interesting.

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

This creates a virtual audio sink that mirrors sound to multiple outputs simultaneously.

Note: PipeWire maintains full compatibility with this module.


Step 5: The Final Script — audioctl

The final script wraps all of these commands into simple actions like:

  • audioctl hdmi
  • audioctl analog
  • audioctl dual
  • audioctl toggle

Full source code:
https://gist.github.com/igorgbr/8031267dee77acf6d7d298ec72a37f94


Installing the Script

chmod +x ~/projects/audioctl
mkdir -p ~/bin
ln -sf ~/projects/audioctl ~/bin/audioctl

Ensure ~/bin is in your PATH:

export PATH="$HOME/bin:$PATH"

Reload your shell:

source ~/.bashrc

Extra Tips

Test with continuous audio:

speaker-test -t wav -c 2

Keyboard shortcuts (GNOME, KDE, i3, etc.):

  • Super + F11audioctl toggle
  • Super + F12audioctl dual

Debug Commands & References

Useful debug commands:

pactl list sinks short
pactl get-default-sink
pactl list short sink-inputs
pactl list cards

Official documentation:


Conclusion

With less than 60 lines of Bash, I solved a real-world problem and gained a level of audio control that no graphical application offered me.

More importantly, this project helped me deeply understand how Linux audio works under the hood and how small automations can dramatically improve everyday workflows.

The control is yours — and it lives in the terminal.

1 Comment

2 votes
1

More Posts

I’m a Senior Dev and I’ve Forgotten How to Think Without a Prompt

Karol Modelskiverified - Mar 19

Why Does the System Clock Break on Windows + Linux Dual Boot?

Igor Giamoniano - Coisa de Dev - Dec 29, 2025

Cavity on X-Ray: A Complete Guide to Detection and Diagnosis

Huifer - Feb 12

A Shell script that sends a file using magic-wormhole cli

Vaishnav-sabari-girish - Sep 30, 2025

Using Bash to Monitor Server Health (CPU, RAM, Disk) – A Beginner-Friendly Guide

Gift Balogun - May 25, 2025
chevron_left

Related Jobs

View all jobs →

Commenters (This Week)

4 comments
1 comment

Contribute meaningful comments to climb the leaderboard and earn badges!