How to change pulseaudio sink with "pacmd set-default-sink" during playback?

178,238

Solution 1

PulseAudio pacmd is not capable of switching the default sinks while there is an actively playing stream to the sink input. However there is a way to still achieve this.

Changing default sink from command line

First we need to determine the index number of the sinks we want to switch. This can be done by calling:

pacmd list-sinks

Depending on our system this will give you a more or less lengthy list of sinks and properties that are at present accessible:

 >>> 2 sink(s) available.
      * index: 0
            name: <alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1>
            driver: <module-alsa-card.c>
    :
    :
        index: 1
            name: <alsa_output.pci-0000_00_14.2.analog-stereo>
            driver: <module-alsa-card.c>

The index or the name given here is what we need for adressing the sink by command line. The present default sink is marked with an asterix (here 0).

To be able to switch the default sinks from command line we may need to disable stream target device restore by editing the corresponing line in /etc/pulse/default.pa to:

load-module module-stream-restore restore_device=false

To change the default output sink to sink 1 we then run

pacmd set-default-sink 1

Sucess can be visualized by opening the Sound Settings menu.

Moving a stream to another sink

Changing the default sink while we have an active input stream playing to a given sink has no effect. This should rather be done by moving this input to another sink.

pacmd list-sink-inputs

will tell us the index of the input stream

>>> 1 sink input(s) available.
    index: 5
    driver: <protocol-native.c>

We now know that we want to move the input stream 5 to sink 1 by calling

pacmd move-sink-input 5 1

or back to sink 0 if we like. This will be done immediately without the need of stopping playback.

Changing default sink while playing

Of course we can combine those two commands to immediately switch default sinks during playback e.g. with

pacmd set-default-sink 1 & pacmd move-sink-input 5 1

A drawback of this method is that the input stream index changes every time we stop and restart the music player. So we always have to find out the current stream index before we can switch using the commmand line.

Solution 2

I have written a simple script to move all the sink-inputs automatically using pacmd.

Usage: ./move-sink-inputs.sh <sink number>

#!/usr/bin/env bash
echo "Setting default sink to: $1";
pacmd set-default-sink "$1"
pacmd list-sink-inputs | grep index | while read -r line; do
  echo "Moving input: ";
  echo "$line" | cut -f2 -d' ';
  echo "to sink: $1";
  pacmd move-sink-input "$(echo "$line" | cut -f2 -d' ')" "$1"
done

Solution 3

Improved version of @Gaco script

#!/usr/bin/env bash
case "${1:-}" in
  (""|list)
    pacmd list-sinks |
      grep -E 'index:|name:'
    ;;
  ([0-9]*)
    echo switching default
    pacmd set-default-sink $1 ||
      echo failed
    echo switching applications
    pacmd list-sink-inputs |
      awk '/index:/{print $2}' |
      xargs -r -I{} pacmd move-sink-input {} $1 ||
        echo failed
    ;;
  (*)
    echo "Usage: $0 [|list|<sink name to switch to>]"
    ;;
esac

my runtime copy is on github and it includes also automated switching of Master channel for kmix

Solution 4

CIRCLE-TOGGLE SINKS.

The Gaco script with just one more line to circle-toggle through available sinks.

#!/bin/bash 
new_sink=$(pacmd list-sinks | grep index | tee /dev/stdout | grep -m1 -A1 "* index" | tail -1 | cut -c12-)
echo "Setting default sink to: $new_sink";
pacmd set-default-sink $new_sink
pacmd list-sink-inputs | grep index | while read line
do
echo "Moving input: ";
echo $line | cut -f2 -d' ';
echo "to sink: $new_sink";
pacmd move-sink-input `echo $line | cut -f2 -d' '` $new_sink
done

Solution 5

Based on Gaco's answer, I rewrote it a bit for my personal use. Maybe someone finds it useful. It's for toggling my USB Speakers and USB Gaming headset.

#!/bin/bash
# get list of sinks/cards (for settings CARD1/CARD2)
# pacmd list-sinks | awk '/name:/ {print $0};' | awk '{ print $2}' | sed 's/<//g; s/>//g'
CARD1="alsa_output.usb-C-Media_INC._C-Media_USB_Audio-00"
CARD2="alsa_output.usb-Kingston_HyperX_Virtual_Surround_Sound_00000000-00"
CURRENT_SINK=$(pacmd stat | awk -F": " '/^Default sink name: /{print $2}' | awk 'BEGIN{FS=OFS="."} NF--' | sed 's/alsa_output/alsa_output/g')
function setCard() {
  if [ "$CURRENT_SINK" == "$1" ]
   then
     echo "Already using this Sink"
     exit 1
  fi
  NEW_SINK=$(pacmd list-sinks | awk '/index:/ {print $1 $2 $3} /name:/ {print $0};' | grep -m1 -B1 $1 | grep index | awk '{print $1}' | cut -d ":" -f2)
  SINK=$(pacmd set-default-sink $NEW_SINK)
  INPUT=$(pacmd list-sink-inputs | grep index | awk '{print $2}')
  pacmd move-sink-input $INPUT $NEW_SINK
  echo "Moving input: $INPUT to sink: $NEW_SINK";
  echo "Setting default sink to: $NEW_SINK";
  notify-send --urgency=low "Audio Switching" "SINK: $NEW_SINK"
}
function toggleSinks() {
  if [ "$CURRENT_SINK" == "$CARD1" ]
    then
      setCard $CARD2
    else
      setCard $CARD1
    fi
}
function showHelp() {
  echo "------------------------------------"
  echo "AUDIO SINK SWITCHER"
  echo " "
  echo "$0 [options]"
  echo " "
  echo "options:"
  echo "-h  --help        What you are looking at.."
  echo "-g, --gaming      Sets Gaming headset as output device"
  echo "-s, --speakers    Sets Speakers as output device"
  echo "-t, --toggle      Toggles the different output devices"
  echo " "
  echo "------------------------------------"
}
# check args length
if [ $# -eq 0 ]
  then
    echo "Toggling output devices (Speakers/Headset)"
    toggleSinks
fi
# arg options
while test $# -gt 0; do
    case "$1" in
                -h|--help)
                        showHelp
                        exit 1
                        ;;
                -g|--gaming)
                        setCard $CARD2
                        exit 1
                        ;;
                -s|--speakers)
                        setCard $CARD1
                        exit 1
                        ;;
                -t|--toggle)
                        toggleSinks
                        echo "Toggling output devices (Speakers/Headset)"
                        exit 1
                        ;;
                 *)
                        showHelp
                        exit 1
                        ;;
    esac
done
Share:
178,238

Related videos on Youtube

Author by

wasakwasak

Updated on September 18, 2022

Comments

  • wasakwasak 3 months

    I need to switch the pulseaudio server of a currently playing audio stream.

    Pulseaudio server is set up with IP 192.168.1.105

    $>cat /etc/pulse/default.pa
    ...
    load-module module-esound-protocol-tcp auth-anonymous=1
    load-module module-native-protocol-tcp auth-anonymous=1
    load-module module-zeroconf-publish
    ...
    

    On the source side VLC media player is playing a song.

    I created a new tunnel sink with pulseaudio on source side.

    pacmd load-module module-tunnel-sink server=192.168.1.105
    pacmd set-default-sink 1
    

    But while playing audio the server couldn't be changed immediately. Only after stopping the player and replay, it's ok.

    From "gnome-volume-control" or "gnome-control-center sound" switching of output devices is applied immediately.

    How can I apply switching the output sink immediately from command line during playback of a sound file?

  • nanofarad
    nanofarad about 10 years
    Welcome to Ask Ubuntu! Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference.
  • Pathogen
    Pathogen over 7 years
    Awesome! I extended this a little further for my own use: I wanted an icon on my taskbar that would toggle between two audio cards. I wrote a tiny script in Ruby to determine the current sink and call out to this shell script to make the change (pastebin.com/xb3i2ejW). After that, I put both scripts in ~/bin and customized a KDE icon to run the ruby script. This could be done more elegantly, or entirely in shell script, but it works for me.
  • Reuben Mallinson almost 7 years
    Thanks for this. Here's a version that switches to the last (? - I only have two) unused output: pastebin.com/raw/sidH7QPb i.e. it toggles the output, suitable for mapping to a hot key.
  • Leif Liddy
    Leif Liddy almost 6 years
    You can reference a sink by its index OR by its name pactl list short sinks > 4 bluez_sink.FC_A8_9A_2C_EB_0B module-bluez5-device.c s16le 1ch 8000Hz IDLE now just reference the name pactl set-default-sink bluez_sink.FC_A8_9A_2C_EB_0B
  • Takkat
    Takkat almost 6 years
    @LeifLiddy: Thank you for the note. In more recent versions of Pulseaudio you can indeed reference to the name of a sink on set-default-sink but you will still need the index number on move-sink-input.
  • Zhigalin - Reinstate CMs
    Zhigalin - Reinstate CMs about 5 years
    And what if 0 sink input(s) available.? But that shitty flash player is still playing audio?
  • Zhigalin - Reinstate CMs
    Zhigalin - Reinstate CMs about 5 years
    And I see flash player in the client(s) logged in section of pacmd list
  • Takkat
    Takkat about 5 years
    @Zhigalin Flash is long dead on my systems so I can't reall say... it may play directly through ALSA.
  • bodo
    bodo over 4 years
    +1 for using pactl list short. You can simplify the following line by doing the cut directly after: pactl list short sink-inputs | cut -f1 | while read streamId works for me.
  • oblitum
    oblitum over 4 years
    The /etc/pulse/default.pa setting was crucial for me. THANKS!
  • Paul Bastian almost 4 years
    great, simple and scaling!
  • Michal Przybylowicz
    Michal Przybylowicz almost 3 years
    Thank You that is exactly what I needed ! I use now two "soundcards" one is external USB DAC/AMP which I use to listening to music and one is built-in soundcard (realtek) which I use to talk via voice apps. Now I can easily toggle between them.
  • Abraham Murciano Benzadon
    Abraham Murciano Benzadon almost 3 years
    Great script, really appreciate it! Here I was getting ready to spend my day writing a script and figuring out how sound cards work in the process
  • jameh
    jameh over 2 years
    THANKS, really useful script.
  • br4nnigan
    br4nnigan over 1 year
    any idea why this does not work in .profile?
  • Christian Fritz
    Christian Fritz 10 months
    perfect! just what I was looking for, thanks! Now I can put it on a keyboard shortcut.