'Processing text in bash - extracting the volume of a program from pactl sink-inputs output

Looking for a way to extract the volume from

pactl list sink-inputs

Output example:

Sink Input #67
        Driver: protocol-native.c
        Owner Module: 12
        Client: 32
        Sink: 0
        Sample Specification: s16le 2ch 44100Hz
        Channel Map: front-left,front-right
        Format: pcm, format.sample_format = "\"s16le\""  format.channels = "2"  format.rate = "44100"  format.channel_map = "\"front-left,front-right\""
        Corked: no
        Mute: no
        Volume: front-left: 19661 /  30% / -31.37 dB,   front-right: 19661 /  30% / -31.37 dB
                balance 0.00
        Buffer Latency: 100544 usec
        Sink Latency: 58938 usec
        Resample method: n/a
        Properties:
                media.name = "'Alerion' by 'Asking Alexandria'"
                application.name = "Clementine"
                native-protocol.peer = "UNIX socket client"
                native-protocol.version = "32"
                media.role = "music"
                application.process.id = "16924"
                application.process.user = "gray"
                application.process.host = "gray-kubuntu"
                application.process.binary = "clementine"
                application.language = "en_US.UTF-8"
                window.x11.display = ":0"
                application.process.machine_id = "54f542f950a5492c9c335804e1418e5c"
                application.process.session_id = "3"
                application.icon_name = "clementine"
                module-stream-restore.id = "sink-input-by-media-role:music"
                media.title = "Alerion"
                media.artist = "Asking Alexandria"                           

I want to extract the

30

from the line

 Volume: front-left: 19661 /  30% / -31.37 dB,   front-right: 19661 /  30% / -31.37 dB

Note: There may be multiple sink inputs, and I need to extract the volume only from Sink Input #67

Thanks

P.S. Need this for a script of mine which should increase or decrease the volume of my music player. I'm completely new to both linux and bash so I couldn't figure a way to resolve the problem.

Edit: My awk version

gray@gray-kubuntu:~$ awk -W version
mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan

compiled limits:
max NF             32767
sprintf buffer      2040


Solution 1:[1]

Since you are pretty new to use standard text processing tools, I will provide an answer with a detailed explanation. Feel free to use it for future.

Am basing this answer using the GNU Awk I have installed which should likely also work in mawk installed in your system.

pactl list sink-inputs | \
    mawk '/Sink Input #67/{f=1; next} f && /Volume:/{ n=split($0,matchGroup,"/"); val=matchGroup[2]; gsub(/^[[:space:]]+/,"",val); gsub(/%/,"",val); print val; f=0}'

Awk processes one line at a time which is based on a /pattern/{action1; action2} syntax. In our case though, we match the line /Sink Input #67/ and enable a flag(f) to mark the next occurrence of Volume: string in the lines below. Without the flag set it could match the instances for other sink inputs.

So once we match the line, we split the line using the de-limiter / and get the second matched element which is stored in the array(matchGroup). Then we use the gsub() calls twice once, to replace the leading white-spaces and other to remove the % sign after the number.

Solution 2:[2]

This script I wrote might be what you wanted. It lets me adjust the volume easily using the pacmd and pactl commands. Seems to work well when I'm using a GNOME desktop, (Wayland or Xorg), and it's working on RHEL/Fedora and Ubuntu so far. I haven't tried using it with other desktops/distros, or with surround sound systems, etc.

Drop it in your path, and run it without any values to see the current volume. Alternatively set the volume by passing it a percentage. A single value sets both speakers, two values will set left, and right separately. In theory you shouldn't use a value outside of 0%-200%, but the script doesn't check for that (and neither does PulseAudio apparently), so be careful, as a volume higher than 200% may harm your speakers.

[~]# volume
L    R   
20%  20% 
[~]# volume 100% 50%
[~]# volume
L    R   
100% 50% 
[~]# volume 80%
[~]# volume
L    R   
80%  80% 
#!/bin/bash

[ ! -z "$1" ] && [ $# -eq 1 ] && export LVOL="$1" && export RVOL="$1"
[ ! -z "$1" ] && [ ! -z "$2" ] && [ $# -eq 2 ]  && export LVOL="$1" && export RVOL="$2"

SINK=$(pacmd list-sinks | grep -e '* index:' | grep -Eo "[0-9]*$")

if [ -z "$LVOL" ] || [ -z "$RVOL" ]; then
  # pacmd list-sinks | grep -e '* index:' -A 20 | grep -e 'name:' -e '^\s*volume:.*\n' -e 'balance' --color=none
  printf "%-5s%-4s\n%-5s%-4s\n" "L" "R" $(pacmd list-sinks | grep -e '* index:' -A 20 | grep -e '^\s*volume:.*\n' --color=none | grep -Eo "[0-9]*%" | tr  "\n" " " | sed "s/ $/\n/g")
  exit 0
elif [[ ! "$LVOL" =~ ^[0-9]*%$ ]] || [[ ! "$RVOL" =~ ^[0-9]*%$ ]]; then
  printf "The volume should specified as a percentage, from 0%% to 200%%.\n"
  exit 1
elif [ "$SINK" == "" ]; then
  printf "Unable to find the default sound output.\n"
  exit 1
fi

pactl -- set-sink-volume $SINK $LVOL $RVOL

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Inian
Solution 2 ladar