Pulseaudio: setting volume from command line

Update

Due to the very kind feedback and nice improvements i rewrote it a bit.
(mainly copy and pasted it from the input in the comments) :)

I did not add the unmute function to the plus and minus calls as ettam suggested in the comments.
coz i dont want this for various reasons.
i understand that this is usefull for most ppl.
so, if you want your sink to get unmuted if you increase or decrease the volume see ettam’s comment.

Usage:

#get it from github

#increase volume by $VOL_STEP

#decrease volume by $VOL_STEP

#mute

#get fancy volumen bar

Thanks to everybody who commented and improved the script a bit.

Outdated

This script is the original(old/outdated) version. its just kept here for reference reasons.

A quick shell script to in/decrease (and mute) my pulseaudio device.

Usage:

copy and paste it to pa-vol.sh
chmod it executeable.
change the SINK_NAME to your device name.

#increase volume by $VOL_STEP

#decrease volume by $VOL_STEP

#mute


Comments

  1. Thanks for the nice script, I took the liberty and tuned it up a bit.
    I’ve added possibility to very simply set the maximum allowed volume and number of steps to to be that volume divided to:

    #!/bin/bash
    
    SINK_NAME="alsa_output.pci-0000_00_1b.0.analog-stereo"
    VOL_MAX="0x20000"
    STEPS="16" # 2^n
    VOL_STEP=$((VOL_MAX / STEPS))
    
    VOL_NOW=<code>pacmd dump | grep -P &quot;^set-sink-volume $SINK_NAME\s+&quot; | perl -p -i -e 's/.+\s(.x.+)$/$1/'</code>
    MUTE_STATE=<code>pacmd dump | grep -P &quot;^set-sink-mute $SINK_NAME\s+&quot; | perl -p -i -e 's/.+\s(yes|no)$/$1/'</code>
    
    function plus() {
            VOL_NEW=$((VOL_NOW + VOL_STEP))
            if [ $VOL_NEW -gt $((VOL_MAX)) ]; then
                    VOL_NEW=$((VOL_MAX))
            fi
            pactl set-sink-volume $SINK_NAME <code>printf &quot;0x%X&quot; $VOL_NEW</code>
    }
    
    function minus() {
            VOL_NEW=$((VOL_NOW - VOL_STEP))
            if [ $(($VOL_NEW)) -lt $((0x00000)) ]; then
                    VOL_NEW=$((0x00000))
            fi
            pactl set-sink-volume $SINK_NAME <code>printf &quot;0x%X&quot; $VOL_NEW</code>
    }
    
    function mute() {
            if [ $MUTE_STATE = no ]; then
                    pactl set-sink-mute $SINK_NAME 1
            elif [ $MUTE_STATE = yes ]; then
                    pactl set-sink-mute $SINK_NAME 0
            fi
    }
    
    function get() {
            BAR=&quot;&quot;
            if [ $MUTE_STATE = yes ]; then
                    BAR=&quot;mute&quot;
                    ITERATOR=$((STEPS / 2 - 2))
                    while [ $ITERATOR -gt 0 ]; do
                            BAR=&quot; ${BAR} &quot;
                            ITERATOR=$((ITERATOR - 1))
                    done
            else
                    DENOMINATOR=$((VOL_MAX / STEPS))
                    LINES=$((VOL_NOW / DENOMINATOR))
                    DOTS=$((STEPS - LINES))
                    while [ $LINES -gt 0 ]; do
                            BAR=&quot;${BAR}|&quot;
                            LINES=$((LINES - 1))
                    done
                    while [ $DOTS -gt 0 ]; do
                            BAR=&quot;${BAR}.&quot;
                            DOTS=$((DOTS - 1))
                    done
            fi
            echo &quot;$BAR&quot;
    }
    
    case &quot;$1&quot; in
            plus)
                    plus
            ;;
            minus)
                    minus
            ;;
            mute)
                    mute
            ;;
            get)
                    get
    esac
    
    
    • hey michael.

      i am glad that it is of any use for you.
      and thanks a lot for the nice improvement.

  2. very useful. tks.

  3. Hello,
    VERY USEFUL!!! you have solved my issue with volume keyboard control! THANK YOU!
    I have also added the “unmute” to Volume up/down.


    #!/bin/bash
    SINK_NAME="alsa_output.pci-0000_00_1b.0.analog-stereo"
    VOL_STEP="0x01000"
    VOL_NOW=
    pacmd dump | grep -P "^set-sink-volume $SINK_NAME\s+" | perl -p -i -e 's/.+\s(.x.+)$/$1/'
    case "$1" in
    plus)
    MUTE_STATE=pacmd dump | grep -P "^set-sink-mute $SINK_NAME\s+" | perl -p -i -e 's/.+\s(yes|no)$/$1/'
    if [ $MUTE_STATE = yes ]
    then
    pactl set-sink-mute $SINK_NAME 0
    fi
    VOL_NEW=$((VOL_NOW + VOL_STEP))
    if [ $VOL_NEW -gt $((0x10000)) ]
    then
    VOL_NEW=$((0x10000))
    fi
    pactl set-sink-volume $SINK_NAME printf "0x%X" $VOL_NEW

    ;;
    minus)
    MUTE_STATE=pacmd dump | grep -P "^set-sink-mute $SINK_NAME\s+" | perl -p -i -e 's/.+\s(yes|no)$/$1/'
    if [ $MUTE_STATE = yes ]
    then
    pactl set-sink-mute $SINK_NAME 0
    fi
    VOL_NEW=$((VOL_NOW - VOL_STEP))
    if [ $(($VOL_NEW)) -lt $((0x00000)) ]
    then
    VOL_NEW=$((0x00000))
    fi
    pactl set-sink-volume $SINK_NAME printf "0x%X" $VOL_NEW
    ;;
    mute)

    MUTE_STATE=pacmd dump | grep -P "^set-sink-mute $SINK_NAME\s+" | perl -p -i -e 's/.+\s(yes|no)$/$1/'
    if [ $MUTE_STATE = no ]
    then
    pactl set-sink-mute $SINK_NAME 1
    elif [ $MUTE_STATE = yes ]
    then
    pactl set-sink-mute $SINK_NAME 0
    fi
    esac

  4. Hi, i really found this script useful as a workaround of LXDE mute/unmute keyboard key issue, and also (as a token of grattitude) i modified a bit the script. Now it autodetects the SINK_NAME


    #!/bin/bash

    SINK_NAME=$(pacmd dump | grep -m 1 -o "alsa.*stereo")
    VOL_STEP="0x01000"

    VOL_NOW=pacmd dump | grep -P "^set-sink-volume $SINK_NAME\s+" | perl -p -i -e 's/.+\s(.x.+)$/$1/'

    case "$1" in
    plus)
    VOL_NEW=$((VOL_NOW + VOL_STEP))
    if [ $VOL_NEW -gt $((0x10000)) ]
    then
    VOL_NEW=$((0x10000))
    fi
    pactl set-sink-volume $SINK_NAME printf "0x%X" $VOL_NEW

    ;;
    minus)
    VOL_NEW=$((VOL_NOW - VOL_STEP))
    if [ $(($VOL_NEW)) -lt $((0x00000)) ]
    then
    VOL_NEW=$((0x00000))
    fi
    pactl set-sink-volume $SINK_NAME printf "0x%X" $VOL_NEW
    ;;
    mute)

    MUTE_STATE=pacmd dump | grep -P "^set-sink-mute $SINK_NAME\s+" | perl -p -i -e 's/.+\s(yes|no)$/$1/'
    if [ $MUTE_STATE = no ]
    then
    pactl set-sink-mute $SINK_NAME 1
    elif [ $MUTE_STATE = yes ]
    then
    pactl set-sink-mute $SINK_NAME 0
    fi
    esac

    • i find
      $(pactl stat | grep "alsa_output" | awk '{split($0,output,": "); print output[2]}')
      to be a more reliable source for the current sink

  5. This is great!

    Thanks!

  6. Detecting default sink is at fault – it detects alsa only.
    Now, when I make combined sink as default then everything goes down.

    Then this is how it should be done:
    SINK_NAME=pacmd dump | mawk '/set-default-sink/ {print $2}'
    (I’m using MAWK as it’s lighter than GAWK, but AWK could be used here as it’s symlink to what is current default AWK in system)
    It could be done with one “pacmd dump” command to gather all needed information, so will address that later.

    • hey Kitsunenobaka!

      thanks for your input.
      obv, you are right. i, for myself never used combined sinks.

      however…i changed the detection of the default sink to what you suggested. just perlified it coz i simply prefer it over awk :)

  7. And it’s not only for combined.
    if you connect bluetooth headset then it will work witt it also.

  8. This is good work. Thank you.

  9. Hi,

    I use these commands. I hope to help:

    [plus]
    pactl set-sink-volume @DEFAULT_SINK@ -- +10%
    (the characters ‘--’ can be omitted in this case)

    [minus]
    pactl set-sink-volume @DEFAULT_SINK@ -- -10%

    [mute]
    pactl set-sink-mute @DEFAULT_SINK@ toggle

    pd: Sorry if my english is not good. I speak spanish :)

  10. Thank you so much, great script, saved me a LOT of time!

  11. Thanks dude! this script saved my skin here! thanks a lot.

Leave a Reply

Your email address will not be published / Required fields are marked *