Is there any way to randomize the alert sound effect in Mac OS? In system prefs I am able to select which sound effect I want to hear. Is there a way for the system to choose a random sound each time?
2 Answers
This isn't built into macOS so this is something you are going to have to script and do a bit of customization. You will need the following:
- Custom location for your sound
- Script to randomize the sound
- launchd plist to run the script at a set interval
Custom Location for Sound
System sounds are in the /System/Library/Sounds
directory which I don't recommend attempting to modify. You can copy them to ~/Libary/Sounds
or another custom directory of your choosing. This way, you can add your own custom sounds without interfering with the System sounds themselves.
Script to Randomize Soundfile
The script below will generate a random number between 0 and the number of files you have in your sound directory. It will then create an array of all the file names and then select a random filename (array element) which it will then copy that file to another file called CustomAlert.aif
. You can customize the filename and path to suit your needs.
#!/bin/bash
#
# script filename: randomAlert.sh
#User Defined Variables
sdir="/Users/foobar/test"
sfname="CustomAlert.aif"
#Remove Custom Alert Sound if already Exists
if [ -f ${sdir}/${sfname} ]; then
rm -f ${sdir}/${sfname}
fi
#Get Number of Files in Directory
numfiles=(*)
numfiles=${#numfiles[@]}
#Generate Random Number
rnum=$(( $RANDOM % ${numfiles} + 0 ))
#Put names of files into array
fnames=(*)
#Copy file to Alert Sound File
cp ${sdir}/${fnames[${rnum}]} ${sdir}/${sfname}
exit
Make sure the script's permissions is set to allow execution:
chmod +x randomAlert.sh
Finally, make sure the script is in a "safe" location (a folder in your home directory is always a good place)
Launchd plist
To have the script run, you need to use the launchd
service. The plist can go in any one of 3 locations:
~/Library/LaunchAgents
- For just one user, run as the user (i.e. yourself)/Library/LaunchAgents
- For all users, run as the user/Library/LaunchDaemons
- As a system daemon (run as root)
I recommend either of the first two; it doesn't make sense to run as a system daemon.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.randomSound</string>
<key>ProgramArguments</key>
<array>
<string>/Users/USERNAME/Path_to_Scripts/randomAlert.sh</string>
</array>
<key>StartCalendarInterval</key>
<array>
<dict>
<key>Hour</key>
<integer>00</integer>
<key>Minute</key>
<integer>00</integer>
</dict>
</dict>
</plist>
Once you have copied it to the appropriate directory, you need to launch it with launchctl
launchctl load com.user.randomSound.plist
Set your Alert Sound to the Custom File
In your settings, set the alert to CustomAlert.aif
. Even though the sound will change, the name of the file will stay the same.
That's it! Every 24 hours, your script will kick off and set a new random alert sound.
Bash and "Launchd plist" both sound very frightening to me...
So I came up with a solution that involves Python and a cron job instead. (Shout out to the answer above and this other one: Change default alert sound from terminal in Mac OSX)
I wrote a longer blog post explaining this in more details and using custom alert sounds: Randomizing the Alert Sound on a Mac
But here's the TLDR:
1- You can set the alert sound via the shell.
For instance, this:
defaults write .GlobalPreferences com.apple.sound.beep.sound /System/Library/Sounds/Sosumi.aiff
Sets "Sosumi" as your alert sound.
2- You can iterate over your sound files with Python and call the command from step 1.
#!/usr/bin/env python3
import subprocess, random, glob
sounds = glob.glob('/System/Library/Sounds/*.aiff')
sound = random.choice(sounds)
print('randomly selected sound: ', sound)
command = 'defaults write .GlobalPreferences com.apple.sound.beep.sound /System/Library/Sounds/{}.aiff'.format(sound)
# You could also define an array of sounds yourself,
# if you don't want every .aiff file to be a possibility
# sounds=['sound1', 'sound2', 'sound3']
# sound=random.choice(sounds)
# command = 'defaults write .GlobalPreferences com.apple.sound.beep.sound /System/Library/Sounds/{}.aiff'.format(sound)
subprocess.call(command, shell=True)
3- You can call the Python script from step 2 with cron.
I use nano to edit my crontab file (but go ahead and use Vim or emacs if you're cool 😉).
env EDITOR=nano crontab -e
Assuming you named the script from step 2 "randomize.py", adapt the path and put this in your crontab file:
MAILTO=""
* * * * * python3 /Wherever/youWill/store/thisFile/randomize.py
Voilà! You now have a script that randomizes your alert sound every minute.
I run it every hour now, so * * * * *
became 59 * * * *
.
-
I agree re bash - if it has more than 5 lines use a proper language but launchd is easy with a GUI like Launch Control– mmmmmmCommented Sep 12, 2021 at 0:47