Change PulseAudio Input/Output from Shell?

As @Teresa-e-Junior pointed out pactl is the tool to use:

First of all we might want to get the IDs of our PA sinks. On my system this is what I get:

$ pactl list short sinks
0       alsa_output.pci-0000_01_00.1.hdmi-surround      module-alsa-card.c      s16le 6ch 44100Hz  SUSPENDED
1       alsa_output.pci-0000_00_1b.0.analog-stereo      module-alsa-card.c      s16le 2ch 44100Hz  RUNNING

Sink 1 is currently my default sink.
But now I want all my current and future streams to be played via HDMI (i.e. sink 0).

There is a command to set the default sink for PulseAudio, but it doesn't seem to have any effect on my PC:

$ pacmd set-default-sink 0 #doesn't work on my PC :(

Instead, new streams seem to be connected to the sink that had a stream moved to it most recently.

So let's tell pactl to move all currently playing streams to sink 0. We'll first need to list them:

$ pactl list short sink-inputs
290     1       176     protocol-native.c       float32le 2ch 44100Hz
295     1       195     protocol-native.c       float32le 2ch 44100Hz

Ok, we've got two streams (IDs 290 and 295) that are both attached to sink 1.
Let's move them to sink 0:

$ pactl move-sink-input 290 0
$ pactl move-sink-input 295 0

So, that should be it. Now we just have to make a script that does the work for us:

#!/bin/bash

if [ -z "$1" ]; then
    echo "Usage: $0 <sinkId/sinkName>" >&2
    echo "Valid sinks:" >&2
    pactl list short sinks >&2
    exit 1
fi

newSink="$1"

pactl list short sink-inputs|while read stream; do
    streamId=$(echo $stream|cut '-d ' -f1)
    echo "moving stream $streamId"
    pactl move-sink-input "$streamId" "$newSink"
done

You can call it with either a sink ID or a sink name as parameter (i.e. either 0 or something like alsa_output.pci-0000_01_00.1.hdmi-surround).

Now you could attach this script to a udev event or key shortcut.


The following commands can be used to manipulate the PulseAudio sound server:

pacmd - Used to reconfigure a PulseAudio sound server during runtime.
pactl - Used to control a running PulseAudio sound server.

Here are some examples of how they function:

pacmd list-sinks :: list name or index number of possible sinks

pacmd set-default-sink [sinkname] :: set the default output sink

pacmd set-default-source [sourcename] :: set the default input

pacmd set-sink-volume [index] [volume] :: set the sink volume

pacmd set-source-volume index volume :: volume control range 0 - 65536 (the lower the number the lower the volume)

These are only a few that I've pulled out of the wiki & man page. Reference this for more detailed information. Or you can view either commands --help or man page.

There is also a command line tool already out there that serves this purpose. It's name is ponymix. It's a command line mixer for PulseAudio. The link provided is to the projects github. It's developed by a friend and fellow Arch Linux Trusted User / Developer. If you're not running Arch you could just compile it from source using make and sudo make install.

$ ponymix --help
    usage: ponymix [options] <command>... 
Options:
 -h, --help              display this help and exit    
 -c, --card CARD         target card (index or name)
 -d, --device DEVICE     target device (index or name)
 -t, --devtype TYPE      device type
 -N, --notify            use libnotify to announce volume changes
     --source            alias to -t source
     --input             alais to -t source
     --sink              alias to -t sink
     --output            alias to -t sink
     --sink-input        alias to -t sink-input
     --source-output     alias to -t source-output
Device Commands:
  help                   display this message
  defaults               list default devices (default command)
  set-default            set default device by ID
  list                   list available devices
  list-short             list available devices (short form)
  list-cards             list available cards
  list-cards-short       list available cards (short form)
  get-volume             get volume for device
  set-volume VALUE       set volume for device
  get-balance            get balance for device
  set-balance VALUE      set balance for device
  adj-balance VALUE      increase or decrease balance for device
  increase VALUE         increase volume
  decrease VALUE         decrease volume
  mute                   mute device
  unmute                 unmute device
  toggle                 toggle mute
  is-muted               check if muted
Application Commands:
  move DEVICE            move target device to DEVICE
  kill DEVICE            kill target DEVICE
Card Commands:
  list-profiles          list available profiles for a card
  list-profiles-short    list available profiles for a card(short form)
  get-profile            get active profile for card
  set-profile PROFILE    set profile for a card

On my laptop running Fedora 20, HDMI output is not listed as a sink in the default profile, but as a different profile itself.

I have only 1 sink like this, nice music playing on my laptop speakers:

$ pactl list short sinks
8   alsa_output.pci-0000_00_1b.0.analog-stereo  module-alsa-card.c  s16le 2ch 44100Hz   RUNNING

If I run pactl set-card-profile 0 output:hdmi-stereo then nice music is playing through HDMI. I get:

$ pactl list short sinks
14  alsa_output.pci-0000_00_1b.0.hdmi-stereo    module-alsa-card.c  s16le 2ch 44100Hz   RUNNING

To get back to default I just run pactl set-card-profile 0 output:analog-stereo+input:analog-stereo. Either way the default is there again if I reboot.

The list of profiles for my card is somewhere on pactl list cards output.