I use my laptop with an external monitor which has speakers. When the monitor is attached through HDMI I can switch (using the GUI: Sound Setting --> Hardware) between the normal laptop audio output and the monitor output.

I repeat this procedure a lot of time and I started to wonder if I can automate it or, anyway, execute it in a faster way using the shell.

My distro is Ubuntu 12.04 with gnome 3.


I tried using pacmd, but list-sinks gives me only the device I'm currently using:

pacmd list-sinks | grep name:
name: <alsa_output.pci-0000_00_1b.0.hdmi-stereo>

After a switch from GUI:

pacmd list-sinks | grep name:
name: <alsa_output.pci-0000_00_1b.0.analog-stereo>

And if I try to change it I get:

pacmd set-default-sink alsa_output.pci-0000_00_1b.0.hdmi-stereo
Welcome to PulseAudio! Use "help" for usage information.
Sink alsa_output.pci-0000_00_1b.0.hdmi-stereo does not exist.

In this case the card is always the same. What is changing between a switch and another is the "card-profile".

So the solution which actually worked is:

pacmd set-card-profile <cardindex> <profilename>

In my case I found all the card profiles with:

pacmd list-cards

And after I can switch between monitor and laptop speakers with:

pacmd set-card-profile 0 output:hdmi-stereo


pacmd set-card-profile 0 output:analog-stereo+input:analog-stereo

Where 0 is the index of the card:

pacmd list-cards
Welcome to PulseAudio! Use "help" for usage information.
>>> 1 card(s) available.
    index: 0
    name: <alsa_card.pci-0000_00_1b.0>

And finally, in order to make the switch faster, I set up two alias in my .bashrc file:

alias audio-hdmi='pacmd set-card-profile 0 output:hdmi-stereo+input:analog-stereo'
alias audio-laptop='pacmd set-card-profile 0 output:analog-stereo+input:analog-stereo'

This way I can switch between audio from the monitor or from the laptop (headphones) typing in the shell: audio-hdmi or audio-laptop

  • Hm. My pacmd doesn't have 'list-cards' option... – ka3ak Feb 27 '17 at 17:51
  • After going through a lot of fiddling, this method worked for me on a i3wm + Debian setup. – rajudev Jul 21 '20 at 3:58
  • Mille Grazie <3, finally I have my internal/external soundcard switch alias for :bashrc: External pacmd set-card-profile 1 off && pacmd set-card-profile 0 output:analog-stereo, pacmd set-card-profile 0 off && pacmd set-card-profile 1 output:analog-stereo+input:analog-stereo – Frank Nocke Apr 4 at 14:34
  • Advice for anyone wanting to figure out what your specific setup needs after “output:”: pacmd list-cards > ~/Downloads/output1.txt , then change to the-other-settings and dump as output2.txt. Then diff things, by diff command or e.g more conveniently in vscode “compare selected”... – Frank Nocke Apr 4 at 14:36

I wrote a small indicator applet that lets you switch the sound output. No shell script but maybe helpful to you or other readers.




I created a very small script based on the previous ones, which not only switches the audio but also the video output. It uses the disper to switch between displays.

Here is the code:


CURRENT_PROFILE=$(pacmd list-cards | grep "active profile" | cut -d ' ' -f 3-)

if [ "$CURRENT_PROFILE" = "<output:hdmi-stereo>" ]; then
        pacmd set-card-profile 0 "output:analog-stereo+input:analog-stereo"
        disper -s
        pacmd set-card-profile 0 "output:hdmi-stereo"
        disper -S        

For me it is especially useful since I don't like to clone the displays. I either use one or the other. You may need to adapt the audio profiles to your specific system.


You can use pactl, read its man page for more information.


You can try this script: https://github.com/giner/helplinux/tree/master/scripts/switch-sound

Tested on Ubuntu 10.04 - 13.04 and Arch Linux


Lukas's python script (https://github.com/lkettenb/sound-output-switcher, posted above) to implement a notifier applet works well. It needs the appindicator package. That can be installed with

sudo apt-get install python-appindicator
  • 3
    Please include at least a few words in your answer explaining what the script is and why it's handy. – derobert Aug 22 '14 at 11:16

I created the following python script that does the following:

  1. Toggle the default device to the next device on the list (with wrap around) regardless of the id's
  2. Moves all running applications to this device.
  3. Sends a notifications to the GUI with the device name.
#!/usr/bin/env python3
import subprocess
# Toggle default device to the next device (wrap around the list)
cards_info = subprocess.run(['pacmd','list-sinks'], stdout=subprocess.PIPE)
card_indexes = subprocess.run(['grep', 'index'], stdout=subprocess.PIPE, input=cards_info.stdout)
indexes_list = card_indexes.stdout.decode().splitlines()
card_descriptions = subprocess.run(['grep', 'device.description'], stdout=subprocess.PIPE, input=cards_info.stdout)
indices = [i for i, s in enumerate(indexes_list) if '*' in s]
if (len(indices) != 1):
    print("Error finding default device")
default_index = indices[0]
next_default = 0
if (default_index != (len(indexes_list) - 1)):
    next_default = default_index + 1
next_default_index =  (indexes_list[next_default].split("index: ",1)[1])
subprocess.run(['pacmd','set-default-sink %s' %(next_default_index)], stdout=subprocess.PIPE)

# Move all existing applications to the new default device
inputs_info = subprocess.run(['pacmd','list-sink-inputs'], stdout=subprocess.PIPE)
inputs_indexes = subprocess.run(['grep', 'index'], stdout=subprocess.PIPE, input=inputs_info.stdout)
inputs_indexes_list = inputs_indexes.stdout.decode().splitlines()
for line in inputs_indexes_list:
    input_index =  (line.split("index: ",1)[1])
    subprocess.run(['pacmd','move-sink-input %s %s' %(input_index, next_default_index)], stdout=subprocess.PIPE)

# Send notification to the GUI
descriptions_list = card_descriptions.stdout.decode().splitlines()
if (len(descriptions_list) == len(indexes_list)):
    description =  (descriptions_list[next_default].split("= ",1)[1])[1:-1]
    args = ["notify-send", "Default audio card changed", 'Default audio card was set to %s' %(description)]
    subprocess.run(args, stdout=subprocess.PIPE)

Assigned a keyboard shortcut to the script, and my life is happy now


As I told here (probably a duplicate), an alternative to Sound Switcher Indicator (which requieres adding a PPA):

In one line

In my case was hdmi-stereo-extra1+input profile, so in one line would be: [[ $(pacmd list-cards | grep "active profile" | cut -d " " -f 3-) = "<output:hdmi-stereo-extra1+input:analog-stereo>" ]] && pacmd set-card-profile 0 "output:analog-stereo+input:analog-stereo" || pacmd set-card-profile 0 "output:hdmi-stereo-extra1+input:analog-stereo".

You can use a custom shortcut to execute it with bash -c (will warn you if there is any conflict with other shortcut):

enter image description here

Also you can add an alias to your .bashrc.

In a script

I made some changes based on @user829996 (and here @user56655) answer:

set -euo pipefail # strict mode

activeProfile() { pacmd list-cards | grep "active profile" | cut -d " " -f 3-; }
CURRENT_PROFILE="$(eval activeProfile)"

# If it doesn't work run  pacmd list-cards  and try the other outputs from profile section

if [ "$CURRENT_PROFILE" = "<output:hdmi-stereo-extra1+input:analog-stereo>" ] ; then
  pacmd set-card-profile 0 "$ANALOG_PROFILE"
    pacmd set-card-profile 0 "$HDMI_PROFILE"


If useful. I've got bluetooth headphones and needed to setup switching betweed headset and a2dp profiles for them. Solved with adding these functions:

talk() {
  card=$(pacmd list-cards | grep 'name:' | grep bluez | cut -d: -f2 | sed -e 's/[< >]//g')
  pacmd set-card-profile $card headset_head_unit

mus() {
  card=$(pacmd list-cards | grep 'name:' | grep bluez | cut -d: -f2 | sed -e 's/[< >]//g')
  pacmd set-card-profile $card a2dp_sink

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.