Adjusting a Mac's System Volume on the Command Line
Because I’m approximately 270 years old and listen to music (MP3 files, no less!) on my computer instead of a smart speaker, sometimes I find myself wanting to adjust my Mac’s system volume without needing to, say, get up from the couch. I’m sure there’s plenty of iOS apps that can do that with varying amounts of tracking and in-app-purchases, but because, once again, I’m practically 270 years old, I prefer to SSH into my computer and run a command.
Thanks to AppleScript, the amount of trickery required to make this possible is kept to a minimum: Keeping in mind that the built-in osascript
utility executes AppleScript code, running…
osascript -e "set volume output volume 100"
…will turn the volume up to its maximum – the number is interpreted as a percentage. You can also make things louder or quieter by some percentage points…
osascript -e "set volume output volume (output volume of (get volume settings) - 42)"
…or (un)mute the computer:
osascript -e "set volume with output muted"
osascript -e "set volume without output muted"
But, as you can see, these commands are a bit unintuitive and a lot unwieldy. To provide a better user experience in the “lazy couch potato” use case, I’ve written a few lines of bash that provide fewer-keystrokes access to these volume controls:
#!/bin/bash
USAGE="usage: vol [-h | --help | NUMBER_FROM_0_TO_100 | -DECREMENT | +INCREMENT]"
# if the argument isn't one of the expected values, display usage instructions
if [ "$1" == "-h" ] || [ "$1" == "--help" ] || ! [[ "$1" =~ ^$|^[+-]?[0-9]+$ ]]; then
echo "$USAGE"
exit 1
fi
# retrieve old volume
OLD_VOLUME="$(osascript -e "output volume of (get volume settings)")"
if [ -z "$1" ]; then
echo "$OLD_VOLUME %"
else
# default case: just set volume to specified value
NEW_VOLUME="$1"
# alternatively: decrement or increment?
if [[ "$1" == -* ]] || [[ "$1" == +* ]]; then
NEW_VOLUME=$(($OLD_VOLUME + $1))
fi
# clamp to [0, 100]
if [ "$NEW_VOLUME" -lt 0 ] ; then
NEW_VOLUME=0
fi
if [ "$NEW_VOLUME" -gt 100 ] ; then
NEW_VOLUME=100
fi
# give feedback
MUTED=""
if [ "$NEW_VOLUME" -eq 0 ]; then
MUTED="(muted)"
fi
echo "$OLD_VOLUME % -> $NEW_VOLUME % $MUTED"
# set
osascript -e "set volume output volume $NEW_VOLUME"
fi
Paste these lines of code into a file named vol
, place it in a directory that’s on your $PATH
and make sure the file’s executable: run chmod u+x vol
, for instance.
(A common choice of directory is ~/local/bin
– which you can put on your $PATH
by adding export PATH="$HOME/local/bin:$PATH
to your .bashrc
and/or .bash_profile
– but I tend to instead maintain small utilities like this as functions in my .bashrc
. To each their own.)
Here’s how to use the thusly-created vol
command:
$ vol --help
usage: vol [-h | --help | NUMBER_FROM_0_TO_100 | -DECREMENT | +INCREMENT]
$ vol
26%
$ vol 0
26% -> 0% (muted)
$ vol 30
0% -> 30%
$ vol +15
30% -> 45%
$ vol -3
45% -> 42%
But wait, there’s more!
Controlling your music player from the command line
The first Apple product I every used was iTunes (on Windows Vista!), and I stuck with it until it was rebranded as Music. I then switched to Swinsian, a native, fast, minimalist, but fully-featured music player. All three applications – iTunes, Music, and Swinsian – support a shared set of AppleScript hooks which the following script makes use of:
# select available player, preferring Swinsian over Music over iTunes
PLAYER="iTunes"
if [ -d "/System/Applications/Music.app" ]; then
PLAYER="Music"
fi
if [ -d "/Applications/Swinsian.app" ]; then
PLAYER="Swinsian"
fi
# do the things
if [ -z "$1" ]; then
osascript -e "tell application \"$PLAYER\" to playpause"
elif [ "$1" = "?" ]; then
osascript -e "tell application \"$PLAYER\" to get name of current track"
printf "\033[90mby \033[0m"
osascript -e "tell application \"$PLAYER\" to get artist of current track"
printf "\033[90mon \033[0m"
osascript -e "tell application \"$PLAYER\" to get album of current track"
elif [ "$1" = "prev" ]; then
osascript -e "tell application \"$PLAYER\" to play previous track"
elif [ "$1" = "next" ]; then
osascript -e "tell application \"$PLAYER\" to play next track"
else
osascript -e "tell application \"$PLAYER\" to $1"
fi
As above, paste this code into an executable file – mine’s called it
, short for iTunes. Once done, running the it
command without any arguments will pause or resume playback, adding ?
prints info about the currently-playing track, and prev
and next
do what you’d expect them to do. Anything else is passed directly to the player, enabling ad-hoc queries. (The first run will pop up a little window asking you to agree to your music player being controlled via AppleScript.)