Virtual Sink Creation and Loopback on Linux

Page content

AudioSplit

How to Create, Manage, and Remove Virtual Sinks in Linux (PulseAudio/PipeWire)

When working on live streams, podcasts, or complex audio setups, having the ability to separate and control audio streams is essential. In Windows I have used Elgato WaveLink3 software to perform this tasks. One way to do this on Linux is by creating virtual sinks (null sinks) and assigning different applications to them. This post will show you how to automatically create virtual sinks, remap specific applications, and remove those sinks when you’re done—using simple Bash scripts.

Note: This was tested on Linux Mint 22 Cinnamon


1. Creating Virtual Sinks and Configuring Loopbacks

Purpose

The first script automates the creation of virtual (null) sinks named Audio1, Audio2, and Audio3. It also automatically sets up loopbacks to your real hardware sink (for example, alsa_output.pci-0000_0d_00.4.analog-stereo).
This setup allows you to:

  • Separate different application audio (e.g., game audio, voice chat, music) without affecting your primary system audio.
  • Replicate functionality similar to Elgato WaveLink3 software by splitting and isolating audio streams for recording or streaming.
  • Exclude certain channels from recordings (e.g., exclude music from VODs).

Why Use It

  1. Live Streaming: Direct your game, voice chat, and system audio to different channels, making it easier to adjust levels or exclude certain sources from your stream.
  2. Audio Mixing: Combine or isolate multiple audio inputs (games, music, voice) in OBS or other digital audio workstation software.
  3. Debugging: Diagnose audio issues by isolating specific applications to a single sink.

Identifying Your Default Output Device

Before creating the virtual sinks, it’s often helpful to confirm which hardware sink is currently being used by default. You can do this by running:

pactl list short sources
pactl info | grep "Default Source"
pactl info | grep "Default Sink"

For example, the default sink might be alsa_output.pci-0000_0d_00.4.analog-stereo. Use that value in your configuration for the loopbacks.

Script 1: create_sinks.sh

#!/usr/bin/env bash

# Function to check if a sink already exists
sink_exists() {
  local sink_name=$1
  pactl list short sinks | grep -q "$sink_name"
}

# Function to create a null sink and its loopback
create_sink_and_loopback() {
  local sink_name=$1
  local description=$2
  local sink=$3

  # Check and create the sink
  if sink_exists "$sink_name"; then
    echo "Sink $sink_name already exists. Assuming loopback is already configured."
  else
    echo "Creating sink: $sink_name with description: $description"
    pactl load-module module-null-sink sink_name=$sink_name sink_properties=device.description="$description"
    echo "Creating loopback for source: $sink_name.monitor to sink: $sink"
    pactl load-module module-loopback source="$sink_name.monitor" sink="$sink"
  fi
}

# List current sinks
echo "Checking existing sinks:"
pactl list short sinks

# Create new sinks and loopbacks
create_sink_and_loopback "Audio1" "Audio1" "alsa_output.pci-0000_0d_00.4.analog-stereo"
create_sink_and_loopback "Audio2" "Audio2" "alsa_output.pci-0000_0d_00.4.analog-stereo"
create_sink_and_loopback "Audio3" "Audio3" "alsa_output.pci-0000_0d_00.4.analog-stereo"

# List all sinks after configuration
echo "Sinks after configuration:"
pactl list short sinks

echo "Audio sources configured successfully."

How to Use It

  1. Make the script executable:
    chmod +x create_sinks.sh
    
  2. Run it:
    ./create_sinks.sh
    
  3. After it finishes, you should see the new sinks (Audio1, Audio2, Audio3) in your audio manager or by running pactl list short sinks again.

2. Remapping Specific Applications to Virtual Channels

Purpose

Once you’ve created these virtual sinks, you’ll likely want to route specific applications to them. The second script finds active sink inputs based on application names and reassigns them to the sink of your choice.

Why Use It

  1. Fine-Grained Control: Send game audio to Audio1, VoIP apps to Audio2, and background music to Audio3 for easier independent control.
  2. Selective Recording: Only capture your game audio and mic, while leaving out other system sounds.
  3. On-the-Fly Changes: Adjust audio routing in real time without closing or restarting the applications.

Script 2: remap_audio.sh

#!/usr/bin/env bash

# Function to get the sink input ID for a specific application
get_sink_input_id() {
  local app_name=$1
  pactl list sink-inputs | awk -v app_name="$app_name" '
    $1 == "Sink" && $2 == "Input" { sink_id = $3 }
    /application.name/ && $0 ~ app_name { sub(/^#/, "", sink_id); print sink_id }
  '
}

# Function to move an application to a specified sink
move_application_to_sink() {
  local app_name=$1
  local sink_name=$2

  echo "Looking for sink input ID for application: $app_name"
  sink_input_id=$(get_sink_input_id "$app_name")

  if [ -z "$sink_input_id" ]; then
    echo "No active sink input found for application: $app_name"
    return 1
  fi

  echo "Moving $app_name (Sink Input ID: $sink_input_id) to sink: $sink_name"
  pactl move-sink-input "$sink_input_id" "$sink_name"
}

# Move specific applications to the desired sink
move_application_to_sink "World of Warcraft" "Audio2"
move_application_to_sink "FINAL FANTASY V" "Audio2"

move_application_to_sink "Google Chrome" "Audio1"
move_application_to_sink "Firefox" "Audio1"
move_application_to_sink "Microsoft Edge" "Audio1"

move_application_to_sink "WEBRTC VoiceEngine" "Audio3" # e.g., Discord

How to Use It

  1. Make the script executable:
    chmod +x remap_audio.sh
    
  2. Adjust the application names in the script to match the ones you actually use. For instance, replace "World of Warcraft" with the name of your game or "WEBRTC VoiceEngine" with your chat app’s process name.
  3. Run the script to move the targeted applications to their respective sinks:
    ./remap_audio.sh
    
  4. If your application refuses to switch sinks, or if its name doesn’t match what’s in the script, open pavucontrol to manually assign it.

3. Removing All Virtual Sinks and Loopbacks

Purpose

If you need to reset your audio configuration, or if you just want to remove the virtual sinks once you’re done, the third script cleans everything up by unloading the modules associated with the null sinks and loopbacks.

Why Use It

  1. Cleanup/Reset: Easily revert to your default audio setup when you’re finished.
  2. Troubleshooting: If something breaks or you suspect a misconfiguration, start fresh by removing all custom sinks.

Script 3: remove_sinks.sh

#!/usr/bin/env bash

# Function to unload all modules by name pattern
unload_modules() {
  local pattern=$1
  echo "Finding modules matching pattern: $pattern"
  pactl list modules short | grep "$pattern" | while read -r module; do
    module_id=$(echo "$module" | awk '{print $1}')
    module_name=$(echo "$module" | awk '{print $2}')
    echo "Unloading module $module_id ($module_name)"
    pactl unload-module "$module_id"
  done
}

# Remove all sinks and loopbacks created for Audio1, Audio2, Audio3
unload_modules "module-null-sink"
unload_modules "module-loopback"

# Verify removal
echo "Remaining modules:"
pactl list modules short

echo "Audio sources and loopbacks removed successfully."

How to Use It

  1. Make the script executable:
    chmod +x remove_sinks.sh
    
  2. Run the script to unload the virtual sinks and loopbacks:
    ./remove_sinks.sh
    
  3. Confirm the sinks and loopbacks have been removed either by checking pavucontrol or running pactl list modules short.

Additional Tips

  1. Permissions: Make sure each script has executable permissions via chmod +x.
  2. Order of Operations:
    • Create Sinks (via create_sinks.sh).
    • Remap Applications (via remap_audio.sh).
    • Remove Sinks (via remove_sinks.sh) when done.
  3. Manual Adjustments with pavucontrol: If you run into issues—such as an application not appearing in the script—use the GUI tool pavucontrol to make changes on the fly.

Conclusion

These three scripts provide a flexible foundation for advanced audio routing on Linux systems, whether you’re a professional broadcaster, a podcaster, or just an enthusiast who wants finer control over your system’s audio. By creating and assigning specific null sinks, you can isolate, record, and manage different audio streams with ease—and then remove everything just as quickly when you’re finished.

  • Script 1: Virtual Sink Creation – Set up null sinks and loopbacks automatically.
  • Script 2: Remapping Applications – Dynamically move audio streams to your virtual sinks.
  • Script 3: Removal – Quickly revert to your default system audio configuration.

Take advantage of these scripts to simplify your workflow, capture only what you want in recordings or streams, and tailor your system’s audio exactly to your needs. If you found this helpful, share it with friends or colleagues who might benefit from better audio control on Linux!