1
Tell application "System Preferences" 
    set "default voice" to "Agnes" 
end tell 

The result is:

Can’t set "default voice" to "anna". Access not allowed.

0

5 Answers 5

6

There are two problems with your approach:

  • The dictionary for the System Preferences app contains no default voice element or any other for changing the TTS (text-to-speech) default voice (as of OS X 10.11); in fact, it seems that Apple provides no programmatic way of changing the default voice (not even via its NSSpeechSynthesizer Cocoa class).
  • By double-quoting default voice, you're trying to assign a value to a string literal, which will always fail.

Note: An earlier version of this answer pointed to a Bash script named voice in a Dropbox location; this script has since been renamed to voices, had its syntax revised, and is now properly published as an open-source project - see below.

Unfortunately, as of OSX 10.11 (El Capitan), there is no documented programmatic way to change the default voice.

It can be done, but doing so requires on undocumented system internals, so future compatibility is not guaranteed.

voices is a CLI I wrote that does just that - verified to work on OSX 10.11 down to OSX 10.8.

You could then do the following from AppleScript :

do shell script "/path/to/voices -d {voiceName}"

For instance, if you place voices in /usr/local/bin and want to switch to Agnes as the default voice, use:

do shell script "/usr/local/bin/voices -d Agnes"

If you happen to have Node.js installed, you can install voices to /usr/local/bin with

npm install voices -g

Otherwise, follow the instructions here.

4
  • This works splendid. Thank you for the script. Now it's finally easy for me to let my Mac read out German and US articles when needed.
    – patrick
    Commented Jun 30, 2014 at 13:31
  • @pattulus: I'm glad to hear it; my pleasure.
    – mklement0
    Commented Jun 30, 2014 at 13:56
  • @pattulus: The original script no longer fully worked on OSX 10.10 - I've published a fixed and revised version under the name voices at github.com/mklement0/voices.
    – mklement0
    Commented Jun 30, 2015 at 2:51
  • 1
    Thanks for thinking of me. I really missed this script.
    – patrick
    Commented Jun 30, 2015 at 6:27
3

Changes to ~/Library/Preferences/com.apple.speech.voice.prefs.plist seem to be applied immediately.

d=com.apple.speech.voice.prefs
if [[ $(defaults read $d SelectedVoiceName) = Kathy ]]; then
  defaults write $d SelectedVoiceCreator -int 1835364215
  defaults write $d SelectedVoiceID -int 201
  defaults write $d SelectedVoiceName Alex  
else
  defaults write $d SelectedVoiceCreator -int 1836346163
  defaults write $d SelectedVoiceID -int 2
  defaults write $d SelectedVoiceName Kathy
fi

Another option using UI scripting:

tell application "System Preferences"
    reveal anchor "TTS" of pane "com.apple.preference.speech"
end tell
tell application "System Events" to tell process "System Preferences"
    tell pop up button 1 of tab group 1 of window 1
        delay 0.1
        click
        if value is "Alex" then
            click menu item "Kathy" of menu 1
        else
            click menu item "Alex" of menu 1
        end if
    end tell
end tell
quit application "System Preferences"

Without the delay the value was Loading Voices… if System Preferences wasn't open before.

2
  • The GUI scripting approach is interesting, but it is (inevitably) visually disruptive and may fail due to timing issues, if System Preferences is not currently running. Writing to .../com.apple.speech.voice.prefs.plist is what my voice utility (linked to in my answer) does, too - challenge is to find SelectedVoiceCreator/SelectVoiceID values for all legacy voices. voice contains this info precompiled - modern voices allow extraction of this info on demand. Background here: evernote.com/shard/s69/sh/5f95cd0e-9a75-4739-9c7d-5462be20aa09/…
    – mklement0
    Commented May 21, 2013 at 16:38
  • Sadly, as of at least OSX 10.10, changes to ~/Library/Preferences/com.apple.speech.voice.prefs.plist are no longer picked up instantly (except by the say CLI). eplt's answer contains a workaround.
    – mklement0
    Commented Jul 28, 2015 at 17:27
1

To get it working with Yosemite, you will need to add the following 2 lines to the bottom of the script provided by mklement0 above:

Original Link to the file from mklement0: https://dl.dropboxusercontent.com/u/10047483/voice

Add the two lines below to restart SpeechSynthesisServer, otherwise you can't use the shortcut key to immediately access the new default voice:

killall SpeechSynthesisServer
open /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/SpeechSynthesis.framework/Versions/A/SpeechSynthesisServer.app
1
  • Thanks for that; I've incorporated it the fix into my voices CLI published at github.com/mklement0/voices. (Turns out that my earlier suggestion to only run pkill com.apple.speech.speechsynthesisd didn't fully work - the voice change was picked up per se, but custom speaking rates weren't honored - aside from working properly, your fix is also faster.)
    – mklement0
    Commented Jul 28, 2015 at 17:25
0

This is working:

property currentVoice : "Vicki"

set systemVoices to {"Agnes", "Albert", "Alex", "BadNews", "Bahh", "Bells", "Boing", "Bruce", ¬
 "Bubbles", "Cellos", "Deranged", "Fred", "GoodNews", "Hysterical", "Junior", "Kathy", ¬
 "Organ", "Princess", "Ralph", "Trinoids", "Vicki", "Victoria", "Whisper", "Zarvox"}

    repeat

     activate me

     set theResult to display dialog "Say What?" default answer ¬

      "" buttons {"Quit", "Speak", "Change Voice"} ¬

      default button "Speak" cancel button "Quit"


if button returned of theResult is "Quit" then exit repeat

 else if button returned of theResult is "Change Voice" then

  set currentVoice to item 1 of ¬

(choose from list systemVoices with prompt "Choose new voice.")

 end if

 if text returned of theResult is not "" then

  say text returned of theResult using currentVoice volume 1

 end if

end repeat
1
  • 1
    While this is handy for playing with voices interactively (it prompts for text to speak, with the option to select from a list of voices), it doesn't change the system's default voice. (Also, the list of voices is hard-coded; "BadNews" should be "Bad News".)
    – mklement0
    Commented Jun 30, 2014 at 14:45
0

Since this question is 12 yrs old, I have an updated answer: This AppleScript changes the default System Voice (for me) in System 10.14.6 (Mojave). This script opens "System Preferences", then Navigates to the "Accessibility" panel, selects "Speech", then switches from one voice to another. *Note: Users may be required to add Apple's "Script Editor" app to "Accessibility" in the "Security & Privacy" panel of System Preferences (mine is set that way).

--OPEN SYSTEM PREFERENCES:
tell application "System Preferences" to activate
tell application "System Events"
    
    --OPEN THE ACCESSIBILITY PANEL:
    tell application process "System Preferences"
        if name of window 1 is "System Preferences" then
            repeat until (name of window 1 is "Accessibility")
                click button "Accessibility" of scroll area 1 of window "System Preferences" of application process "System Preferences" of application "System Events"
                delay 1
            end repeat
        end if
        
        --SELECT THE SPEECH MENU:
        tell window "Accessibility"
            tell table 1 of scroll area 1
                repeat with nmbr from 1 to (count of every row) --probably row 7
                    set UIelement to first UI element of row nmbr
                    if name of UIelement is "Speech" then
                        set selected of (row nmbr of table 1 of scroll area 1 of window "Accessibility" of application process "System Preferences" of application "System Events") to true
                    end if
                end repeat
            end tell
            
            --TOGGLE VOICE:
            set SystemVoice to value of pop up button "System Voice:" of group 1 of window "Accessibility" of application process "System Preferences" of application "System Events"
            if SystemVoice is not "Alex" then
                set SystemVoice to "Alex"
            else if SystemVoice is "Alex" then
                set SystemVoice to "Victoria"
            end if
            click pop up button "System Voice:" of group 1
            delay 1
            click menu item SystemVoice of menu 1 of pop up button "System Voice:" of group 1
            delay 1
        end tell
        
        --CLOSE SYSTEM PREFERENCES:
        set CloseButton to first button of window 1 whose description is "close button"
        click CloseButton
    end tell
end tell

--CONFIRM VOICE SETTINGS:
say "System voice is set to, " & SystemVoice
return SystemVoice

Not the answer you're looking for? Browse other questions tagged or ask your own question.