Videos
Hi there,
I've been frustrated that Windows lacks a universal text-to-speech shortcut, like the one on macOS that works across all applications. With ChatGPT’s help, I built a script to fill that gap, and I’m sharing it here to help others!
When Ctrl + Space are pressed any highlighted text will be spoken using Windows Natural Voices.
-------- How to Set It Up on Windows 11 -----------
Install Required Software
Download AutoHotkey
Run the setup, and complete the installation.
Download NaturalVoiceSAPIAdapter
Go to the releases page, scroll down to “Assets,” and download
NaturalVoiceSAPIAdapter_v0.2_x86_x64.zip.Unzip and place the folder in your preferred install location. I recommend C:\Program Files.
Run
installer.exe(if prompted by Windows, choose "Allow").Install the 64-bit version, then close the installer.
Note: Do not delete NaturalVoiceSAPIAdapter install folder or the TTS will stop working.
Install Natural Voices
Open Accessibility Settings
Go to the Start Menu > type Settings and open Settings > Accessibility > Narrator.
Next to “Add natural voices,” click Add and download your chosen voices.
These voices offer higher quality than the default text-to-speech settings in Windows.
Restart your computer once installation is complete.
Check the Text-to-Speech Voices are available to AutoHotkey
Open the Control Panel from the Start Menu, and search for speech.
Click on Change text to speech settings, then go to the Text to Speech tab.
If Natural Voice SAPI Adapter is working, the natural voices should appear in the dropdown menu.
Note: some users may not see Speech Options in the Control Panel, if this is the case please continue on to the end of this guide as it may still have installed correctly.
Create the Script File
Open AutoHotkey Dash
Go to Start Menu > type AutoHotkey Dash and start the application.
Click New Script. In the New Script dialog, name it (e.g., Read Aloud), choose the Empty type, and click Create.
Edit the Script
In the folder that opens, right-click the new script file, select Edit with Notepad, and paste the code below.
To change the voice, edit the line after
global preferredVoice :=with the desired voice name. It has to be a voice that was in the drop-down in the Text to Speech tab discussed above. The default shortcut isCtrl + Spacebut this can be changed by editing the Script.Save and close the file.
Run the Script
Double-click the script file to start. To stop, right-click the AutoHotkey tray icon.
Optional: Auto-Start on Login
To start the script automatically on login, open the Run dialog (Win + R), type
shell:startup, and click OK.Copy and paste a shortcut of your script into this folder.
```ahk
; Paste from here
; Possible Voices:
; Microsoft Thomas Online (Natural) - English (United Kingdom)
; Microsoft Sonia Online (Natural) - English (United Kingdom)
; Microsoft Ryan Online (Natural) - English (United Kingdom)
; Microsoft Libby Online (Natural) - English (United Kingdom)
; Microsoft Steffan Online (Natural) - English (United States)
; Microsoft Aria (Natural) - English (United States)
; Microsoft Christopher Online (Natural) - English (United States)
; Global variables for better performance and memory management
global preferredVoice := "Microsoft Ryan Online (Natural) - English (United Kingdom)"
global lastText := ""
global isSpeaking := false
global speaker := ""
^Space::
{
; Save current clipboard content
ClipSaved := ClipboardAll
; Clear clipboard and get selected text
Clipboard := ""
Send ^c
ClipWait, 1 ; Fixed ClipWait syntax
selectedText := Clipboard
Clipboard := ClipSaved ; Restore original clipboard content
; Check if speech is currently active
if (isSpeaking)
{
; If the selected text is new, stop current speech and start reading the new text
if (selectedText != lastText && selectedText != "")
{
try {
speaker.Speak("", 3) ; Stop any ongoing speech
speaker := ""
isSpeaking := false
}
catch e {
speaker := ""
isSpeaking := false
}
}
else
{
try {
speaker.Speak("", 3)
speaker := ""
isSpeaking := false
}
catch e {
speaker := ""
isSpeaking := false
}
return
}
}
; Proceed if there is selected text
if (selectedText != "")
{
lastText := selectedText
try {
; Create new COM object for SAPI.SpVoice if needed
if (!speaker)
{
speaker := ComObjCreate("SAPI.SpVoice")
; Set the preferred voice
voices := speaker.GetVoices()
for voice in speaker.GetVoices()
{
if (InStr(voice.GetDescription(), preferredVoice))
{
speaker.Voice := voice
break
}
}
}
; Start speaking the new text asynchronously
speaker.Speak(selectedText, 1)
isSpeaking := true
}
catch e {
speaker := ""
isSpeaking := false
}
}
}
; Cleanup on script exit
#SingleInstance Force
OnExit("ExitFunc")
ExitFunc(ExitReason, ExitCode)
{
global speaker
if (speaker)
{
speaker := ""
}
return
}
; End of content to Paste'''