Skip to content

Instantly share code, notes, and snippets.

@simonesestito
Last active June 6, 2025 09:51
Show Gist options
  • Save simonesestito/d2d5b3e572233b8be7fd512adb509b09 to your computer and use it in GitHub Desktop.
Save simonesestito/d2d5b3e572233b8be7fd512adb509b09 to your computer and use it in GitHub Desktop.
PulseAudio: use multiple speakers
#!/bin/bash
set -x
# TODO: Update this strings with the actual values for your speakers
# TODO: Remember to also adjust the volumes to balance them (depending on their power and their distance from your location)
SPEAKER_1_NAME=$(pactl list sinks | grep Name | grep -Eo 'alsa_output\.pci-.+hdmi-stereo')
SPEAKER_1_VOLUME=85%
SPEAKER_2_NAME=$(pactl list sinks | grep Name | grep -Eo 'alsa_output\.pci-.+analog-stereo')
SPEAKER_2_VOLUME=100%
COMPOSITE_SPEAKER_NAME=Dual_Monitor
COMPOSITE_SPEAKER_DESCRIPTION="Dual Monitor"
COMPOSITE_SPEAKER_VOLUME=50%
PACTL_LOOPBACK_MODULE_ARGS="channels=2 latency_msec=100 adjust_time=0 rate=48000"
# Initially, remove previous state
pactl unload-module module-null-sink 2>/dev/null
pactl unload-module module-loopback 2>/dev/null
if [ "$1" = "-d" -o "$1" = "--disable" ]; then
# Do not proceed any further, but make the single speaker at a decent volume
pactl set-sink-volume $SPEAKER_2_NAME $COMPOSITE_SPEAKER_VOLUME
# Mute everything
pactl set-sink-mute "$SPEAKER_1_NAME" true
pactl set-sink-mute "$SPEAKER_2_NAME" true
exit 0
fi
set -e
# 1. Create a fake sink null
pactl load-module module-null-sink sink_name=$COMPOSITE_SPEAKER_NAME sink_properties="'device.description=\"$COMPOSITE_SPEAKER_DESCRIPTION\"'"
# 2. Connect fake sink to SPEAKER_1
pactl load-module module-loopback source=$COMPOSITE_SPEAKER_NAME.monitor "sink=$SPEAKER_1_NAME" $PACTL_LOOPBACK_MODULE_ARGS
# 3. Connect fake sink to SPEAKER_2
pactl load-module module-loopback source=$COMPOSITE_SPEAKER_NAME.monitor "sink=$SPEAKER_2_NAME" $PACTL_LOOPBACK_MODULE_ARGS
# 4. Set volume of the composite speaker to 50%
pactl set-sink-mute $COMPOSITE_SPEAKER_NAME false
pactl set-sink-volume $COMPOSITE_SPEAKER_NAME "$COMPOSITE_SPEAKER_VOLUME"
# 5. Set volume of SPEAKER_1
pactl set-sink-mute $SPEAKER_1_NAME false
pactl set-sink-volume $SPEAKER_1_NAME $SPEAKER_1_VOLUME
# 6. Set volume of SPEAKER_2
pactl set-sink-mute $SPEAKER_2_NAME false
pactl set-sink-volume $SPEAKER_2_NAME $SPEAKER_2_VOLUME
# 7. Set the fake sink as the default audio sink
pactl set-default-sink $COMPOSITE_SPEAKER_NAME
echo "Setup completed."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment