Hi everyone, I wanted to take the time to write an article about some voiceover optimizations I've made. These have sped up voiceover tremendously and make my workflow amazingly fast.
running the shell scripts mentioned below:
To run any of the scripts described in the next section, copy the code into a new txt file. If using text edit, make sure you open the preferences and under the "Open and Save" tab, you select the format as plain text.
If you had a document open before completing the step above, make sure to close it and open a new document.
after you copy the code into your blank file, do the following: (note, these instructions apply to Text Edit)
- type a useful name for the command file you made.
- make sure to add the extension ".command" to your document.
- if you find your document and it says ".command.txt", feel free to just delete the ".txt" part, and then move on to the next step.
- now, for each of your documents, open terminal and type the following command:
chmod +RWX path/to/file
This gives the system permission to execute your script.
- now, you should have everything set up for the command scripts mentioned below.
Shell scriptsThe first optimizations I wanted to talk about were the several shell scripts I have made. All of these scripts have been made in shell script, so whether your mac uses zsh or bash, you should be fine. You can find out what shell your mac uses by doing the following:
- Open a terminal on your mac. You can do this from spotlight or open the utilities folder in your applications folder.
- once in a new terminal window, type the following command:
You may either hear /bin/bash, or /bin/zsh depending on your mac. Either is fine.
Voiceover speed booster
About a year ago I tried to make an app using automator that would give voiceover max priority to the system. Let's just say I didn't know then what I know now, and sorry for the confusion about that previous article.
This code when run, will automatically renice (give a specified process priority to) the voiceover process.
In this case, this code will set it to the max process priority (-20). The lower the number the more cpu the process can use. The max number (20, the equivalent of the slowest setting) would cause voiceover to probably run slower than usual.navigation
if you are just looking for code snippets, navigate at heading level 6.Voiceover speed booster code
code begins here:
#!/bin/bash id=$(pgrep VoiceOver) if [ -n "$id" ]; then sudo renice -n -20 -p "$id" else say "VoiceOver is not running." fi killall Terminal
app speed booster
Same basic thing here, except this time, the script asks you for the name of the app. Then, it performs the same task as performed in the code above. the script also checks to see if you have entered an invalid app name and will let you know about that.
One thing to note: Some times with some apps (from my testing messages and safari), you may get a "Bad PID Argument". The cause of this is the "pgrep" command I use to get the process id returns multiple values. When passed to the renice command, it throws that error. If anyone knows how to fix that and pass all values to the renice command to have there priorities changed, please let me know. At the end of the program, the app kills terminal and returns you to the previous app you were using.App booster code
code begins here:
#!/bin/bash echo "Which app do you want to boost? Type the name exactly as it is written:" read app id=$(pgrep "$app") # Check if the PID was found if [ -n "$id" ]; then sudo renice -n -20 -p "$id" echo "boosted $app." sleep 1.5 killall Terminal else echo "Invalid app name. The specified app is not running." sleep 10 killall terminal fi
Does this fix the dreaded "safari not responding" bug?
I wanted to answer this, because I would assume someone would be posting on here asking that same question.
from my testing, I have not had that bug as bad as some people have. I can't give you a definitive yes or no answer, but I can tell you this. You will not know until you try.
setting these scripts up for one click actions
we can assign these scripts to useful keyboard commander keys.
For those unfamiliar, the keyboard commander allows you to hold the option key, and then press another key on your mac, and it will perform a specified action. There are many default ones that come set up by default, including
- option+t: announce time and date
- option+M, open mail
- Option+u, read unread mail message count
Here is how you can set up keyboard commander to work with the previously mentioned scripts, as well as open apps and or files you access on a daily basis.
Here's how to set it up.
- To open voiceover utility, Press VO+F8(function8)
- Now, navigate to the "Utility categories" table.
- Now find the "commanders" category.
- Once in the commanders category, find the "Keyboard Commander" tab.
- Here, you will find a table of all of your currently assigned keyboard command keys, as well as an "add" button, a "remove" button, and a "help" button which brings you to the Voiceover User guide
- Find the add button and add all of the letters, numbers, and special symbols(shift+number row) you want to use as commands.
- Next to each key text field is a pop-up where you can choose the command you want to run. I would highly encourage you to take a look in all of the categories, because you might find a few hidden gems, such as the ability to quickly fast forward or rewind in read all. Yes, the mac can do that.
after you have taken advantage of the shell scripts and keyboard commander, there are a few things you can do to further enhance the Voiceover Experience.
portable preferences on line in iCloud!
yep, you heard that right, portable preferences in iCloud.
For those unfamiliar, "portable preferences" is a voiceover feature that allows you to sink your preferences from one computer to another by storing your preferences on a flash drive or other external storage media.
There is a way to store these preferences in iCloud. This involves tricking the system into thinking you have a drive connected that it can use for portable preferences. This is relatively easy to do.
set up online portable preferences
First, we need to open disc utility to create a disc image that can be used for voiceover Preferences.
- Navigate to the utilities folder in your applications folder. alternatively, press command+shift+u to jump directly there.
- Now, navigate to disc utility. once in disc utility, do the following:
- press command+n to create a new image.
- Give your disc image a name. (for the script that can run at startup and prevent it from unmounting (see later section), name the disc image
inside of the folder /applications/Voiceover_Preference_sinker).
- leave the format and partition information alone.
- Make sure the disk image format is set to read/write so Voiceover can write to it.
- unless you want to add inscription, leave inscription set to none.
- the size of 100MB is fine. The voiceover preferences only use up about 5MB. I would say 20MB at a minimum just to be safe.
- Now, enter the name for the volume itself once it is mounted. For that script that keeps the dmg mounted, choose "Portable_Preferences" without quotes.
I have been teasing that there is a script that I made which keeps the dmg from accidentally getting ejected or unmounted. You can put this apple script in an automator app and have it autolaunch at login.contributions to whom they are due:
This was a tedious process finding out how to make a script that does something seemingly so simple. All the script does is check to see if the specified dmg is mounted. If it isn't, remount it.
I assumed that this was going to only take me a few hours to complete, but man was I wrong.
Several hours later, I had a semi-working script that was more advanced. This more advanced version showed a dialog asking if you wanted to restart sinking if the volume was ejected. This turned out to have several implications, such as the dialog showing up even if the dmg was mounted. Thus, I have removed that from this version, because it works.
I will point out, that Chat GPT did help with a lot of the debugging. I put it together after doing some googling and finding nothing much as far as this exact situation. I made sure that my work was original, in a since that I wanted the script to do exactly what I wanted it to do, and that is what it does.
I felt it was my obligation to at least mention that Chat GPT did help with this particular script.instructions for keeping the dmg mounted at all times
First, open auto-mater and create a new application.
- search for the "AppleScript" action and press enter on it.
- in the script textfield, delete everything that was there and enter the following script. on run set diskImagePath to "/Applications/Voiceover_preference_sinker/VO_Prefs.dmg" repeat try set isMounted to isDMGMounted(diskImagePath) if not isMounted then set quotedDiskImagePath to quoted form of diskImagePath do shell script "hdiutil attach " & quotedDiskImagePath delay 5 -- Add a delay to allow the DMG to mount end if delay 0 on error -- Handle errors here end try end repeat end run on isDMGMounted(diskImagePath) try do shell script "hdiutil info | grep -q " & quoted form of diskImagePath return true on error return false end try end isDMGMounted
This article has probably gone on for way too long, so I should better wrap it up. ;-)
There is an app called Hammerspoon which can allow you to run several different automations including some that can control Voiceover.
You can find a complete list of hammerspoon modules that make the accessibility better as well as a few others here.
Some of my favorites include triggrd which can allow you to monitor system events, including making custom sounds for when certain actions happen like apps opening, usb connected/disconnected, etc. This one is so useful I don't know how I lived without it.
I hope you have found these scripts and tips useful to get the most out of Voiceover. Some of those especially the voiceover speed booster and the app speed booster really make a difference. My favorite way to use the app speed booster is if my download manager is being a pain, just use the booster on it and it starts going faster. If you have any improvements or want to add to any of my scripts, please feel free to let me know and maybe we could improve voiceover even more!
Thanks again for taking the time to read this (and sorry for the extremely long article), and I will be here to answer any questions and help people if they need it.