How to change audio outputs in Linux / PulseAudio with a shell script / command line
If you want to have a shell script which does quick switching between your audio inputs / outputs. Useful for creating hotkeys, panel shortcuts etc.
Why?
Investigation story
The script to switch audio outputs
Why?
I have two audio cards, the internal one is connected to a high quality speaker for listening music, the external USB one is connected to a headset. Don't ask why :) it has it's reasons. What I wanted is to quickly switch between them.
Sure KDE offers a widget for doing that, as well as PulseAudio (which works under PipeWire now) offers pavucontrol, but they require several clicks – open the widget / application, find a device, change profile etc. I wanted one-click solution.
Investigation story
Then there is the pactl command line utility for managing PulseAudio.
man pactl
or pactl --help
reveals a bunch of commands. There is the list
command which probably detects which audio outputs I have?
pactl list
returns a ton of data to me.
pactl list short
still too much.
pactl list short cards
seems to be what I need.
$ pactl list short cards
704 alsa_card.pci-0000_07_00.1 alsa
705 alsa_card.pci-0000_07_00.6 alsa
3075 alsa_card.usb-046d_C270_HD_WEBCAM_200901010001-02 alsa
3110 alsa_card.usb-GeneralPlus_USB_Audio_Device-00 alsa
3111 alsa_card.usb-Sony_Interactive_Entertainment_Wireless_Controller-00 alsa
Well, now I know how PulseAudio sees my audio equipment. Can I manage it?
Checking the list of commands yet another time, I found set-card-profile
command. That might be the one. I could try it, but it wants card id and profile name.
Digging into the long list of data returned by pactl list
, I found both.
$ pactl list
...
Card #705
Name: alsa_card.pci-0000_07_00.6
...
device.product.name = "Family 17h (Models 10h-1fh) HD Audio Controller"
...
Profiles:
off: Off (sinks: 0, sources: 0, priority: 0, available: yes)
output:analog-stereo+input:analog-stereo: Analog Stereo Duplex (sinks: 1, sources: 1, priority: 6565, available: no)
output:analog-stereo: Analog Stereo Output (sinks: 1, sources: 0, priority: 6500, available: yes)
output:iec958-stereo+input:analog-stereo: Digital Stereo (IEC958) Output + Analog Stereo Input (sinks: 1, sources: 1, priority: 5565, available: no)
output:iec958-stereo: Digital Stereo (IEC958) Output (sinks: 1, sources: 0, priority: 5500, available: yes)
input:analog-stereo: Analog Stereo Input (sinks: 0, sources: 1, priority: 65, available: no)
pro-audio: Pro Audio (sinks: 2, sources: 2, priority: 1, available: yes)
...
Card #3110
Name: alsa_card.usb-GeneralPlus_USB_Audio_Device-00
...
device.product.name = "USB Audio Device"
...
Profiles:
off: Off (sinks: 0, sources: 0, priority: 0, available: yes)
output:analog-stereo+input:mono-fallback: Analog Stereo Output + Mono Input (sinks: 1, sources: 1, priority:6501, available: yes)
output:analog-stereo: Analog Stereo Output (sinks: 1, sources: 0, priority: 6500, available: yes)
output:iec958-stereo+input:mono-fallback: Digital Stereo (IEC958) Output + Mono Input (sinks: 1, sources: 1,priority: 5501, available: yes)
output:iec958-stereo: Digital Stereo (IEC958) Output (sinks: 1, sources: 0, priority: 5500, available: yes)
pro-audio: Pro Audio (sinks: 1, sources: 1, priority: 1, available: yes)
input:mono-fallback: Mono Input (sinks: 0, sources: 1, priority: 1, available: yes)
available: yes)
pro-audio: Pro Audio (sinks: 1, sources: 1, priority: 1, available: yes)
input:mono-fallback: Mono Input (sinks: 0, sources: 1, priority: 1, available: yes)
...
The script to switch audio outputs
#!/usr/bin/env bash
card_name=$1
case $card_name in
headset)
card_code=$(pactl list cards short | grep alsa_card.usb-GeneralPlus_USB_Audio_Device-00 | cut -f 1)
card_profile=output:analog-stereo+input:mono-fallback
;;
internal)
card_code=$(pactl list cards short | grep alsa_card.pci-0000_07_00.6 | cut -f 1)
card_profile=output:analog-stereo
;;
*)
echo "Please specify \"internal\" or \"headset\""
exit 1
esac
cards=$(pactl list cards short | cut -f 1)
for card in $cards; do
pactl set-card-profile $card off
done
pactl set-card-profile $card_code $card_profile
Enjoy :)
#tech #linux #shellscript #shellscripting #audio #pulseaudio #pipewire