Automator – How to Stop Speech in Automator Action

applescriptautomatorspeechtext to speech

I can make an Applescript within automator so it reads text at N speed:

on run {input, parameters}
  repeat with thisText in input
      say thisText speaking rate 400
  end repeat
end run

However, is there a way to stop the speech at any given point? There is the option of clicking the cogwheel at the top menu bar, but I was looking for a shortcut-able way.

Best Answer

I have a few different solutions:

  • This applescript immediately kills all speech that is running on your computer:
do shell script "killall com.apple.speech.speechsynthesisd"
  • Alternatively, you could have a single script that checks to see if the speech is running and will kill that particular speech, (basically simulates the shortcut for alt-esc, BUT you can add the rate function to the script). I found a script online a while back that does this. Here's the link. I also made my own version that changes the rate (at the bottom of the post). The rate control is where it says [[rate 800]]. This script copies text to the clipboard and adds '[[rate 800]]' which apple tts voices interpret as a command to change to that rate. The clipboard is read at the modified speed. You can adjust up to like 1000 or something.

  • However, if you really just want to make your mac's default text to speech rate faster (which is what I suspect you are using this script for), I highly recommend you just change the default rate using a little hack I came up with a while back (It allows you to go up to 720 WPM). I have a video that describes it all. Basically, it changes the default rate using a script.

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
property this_say_Pid : missing value -- the persistent property

if this_say_Pid is not missing value then -- check the pid of all 'say' commands, if exists then quit the unix process
  set allSayPid to {}
  try
      set allSayPid to words of (do shell script "pgrep -x 'say'")
  end try
  if this_say_Pid is in allSayPid then -- the PID = an item in the list
      do shell script "/bin/kill " & this_say_Pid -- quit this process to stop the speech
      error number -128 -- quits the AppleScript
  end if
end if

-- Back up original clipboard contents:
set savedClipboard to my fetchStorableClipboard()

-- Copy selected text to clipboard:
tell application "System Events" to keystroke "c" using {command down}

delay 0.1

tell application "System Events"

  set varClip to "[[rate 800]]" & (the clipboard)
  delay 0.1
  set the clipboard to varClip

end tell


delay 0.1 -- Without this, the clipboard may have stale data.

-- Speak the clipboard:
--  pbpaste = the contents of the clipboard , this run the commands without waiting, and get the PID of the 'say' command 
set this_say_Pid to do shell script "LANG=en_US.UTF-8 pbpaste -Prefer txt | say > /dev/null 2>&1 & echo $!"

-- Restore original clipboard:
my putOnClipboard:savedClipboard

on fetchStorableClipboard()
  set aMutableArray to current application's NSMutableArray's array() -- used to store contents
  -- get the pasteboard and then its pasteboard items
  set thePasteboard to current application's NSPasteboard's generalPasteboard()
  -- loop through pasteboard items
  repeat with anItem in thePasteboard's pasteboardItems()
      -- make a new pasteboard item to store existing item's stuff
      set newPBItem to current application's NSPasteboardItem's alloc()'s init()
      -- get the types of data stored on the pasteboard item
      set theTypes to anItem's types()
      -- for each type, get the corresponding data and store it all in the new pasteboard item
      repeat with aType in theTypes
          set theData to (anItem's dataForType:aType)'s mutableCopy()
          if theData is not missing value then
              (newPBItem's setData:theData forType:aType)
          end if
      end repeat
      -- add new pasteboard item to array
      (aMutableArray's addObject:newPBItem)
  end repeat
  return aMutableArray
end fetchStorableClipboard


on putOnClipboard:theArray
  -- get pasteboard
  set thePasteboard to current application's NSPasteboard's generalPasteboard()
  -- clear it, then write new contents
  thePasteboard's clearContents()
  thePasteboard's writeObjects:theArray
end putOnClipboard: