Jump to content
flome

A little help with highlighting spoken text in MacOS

Recommended Posts

I'm trying create a workflow to utilize the MacOS Say command. With this command, I'd like to queue up several paragraphs for it to speak and highlight the spoken paragraph. I'm close, but I'm running into issue with the clipboard management. It was my understanding that the /bin/bash scripts can queue commands up in sequence. In which case the below code should execute like this; 

 

1. Copy the query (which in my workflow is the selected text).

2. Open find in Safari

3. Paste the clipboard contents.

4. Say the selected text.

 

It looks like the LAST copied text ends up being pasted, instead of in sequence. The say command adheres to the sequence properly. The other commands do not, what am I missing?

 

screenshot of the workflow is attached.

 

pbcopy < "{query}"
osascript -e 'tell application "System Events" to keystroke "f" using command down'
osascript -e 'tell application "System Events" to keystroke "v" using command down'
say "{query}" -r 250

 

2017-03-20_15-02-06.png

Share this post


Link to post
Posted (edited)

First, a few notes.

  • pbcopy < "{query}" is wrong. It should instead be pbcopy <<< "{query}". The former is trying to read from a file (that does not exist) while the latter is reading from input.
  • You’re doing a lot of work in AppleScript from bash. Instead, use AppleScript directly for everything.
  • When asking for help with a Workflow, it helps if you post a link to download the Workflow, not just screenshots. Not only does it help us get started quicker, you never know if the problem isn’t on a configuration you missed.
  • You don’t need to copy the text and paste it. You can just write it out. I’m betting the problem lies somewhere there.


Try this one. The code it uses is instead AppleScript:

tell application "System Events"
    keystroke "f" using command down

    repeat with c from 1 to count characters of "{query}"
        keystroke (character c of "{query}")
    end repeat
end tell

say "{query}" speaking rate 250


The reason for the whole repeat loop instead of simply keystroke "{query}" is the latter can type too fast and mix characters, while the former will have a negligible delay between each character, ensuring it all gets typed correctly.

Edited by vitor

Share this post


Link to post
14 hours ago, flome said:

It was my understanding that the /bin/bash scripts can queue commands up in sequence. In which case the below code should execute like this; 

 

I don't think it works quite like you imagine. When your script is running, I don't think Alfred queues subsequent calls. Or rather, it does queue them, but doesn't run all subsequent calls, only the last one.

 

Like if I search for "sandwiches", Alfred will run a query for "s", and when that finishes it runs another query with the latest input at the time the first run finishes, perhaps for "sandwi". It does not queue and run the script for all the intermediate queries ("sa", "san", "sand" etc.) because that would be bonkers.

 

As such, I think you might have to manage your own queue (and make sure your script capturing the input in Alfred returns immediately, or it won't be callable).

Share this post


Link to post

@deanishe I’m not entirely sure I understood your whole point, but from what I understand @flome wants (and the way I built the new workflow to work) he would not be searching for “sandwiches” (one query), but instead for “s” “a” “n” (…) (multiple sequential queries). In that case, Alfred does queue them as expected and runs them all.

Share this post


Link to post

I was under the impression that Alfred sometimes drops queued actions on the floor if an earlier actions is still running. Just tested and I was wrong.

 

I didn't look at the workflow you posted because I was on my phone earlier.

Share this post


Link to post
1 hour ago, deanishe said:

I was under the impression that Alfred sometimes drops queued actions on the floor if an earlier actions is still running.

 

Good thing it doesn’t, as I depend on the queue heavily, for DownVid. It’s not uncommon that I add a bunch of videos at once, some quite large. It’d be a shame to lose some in the process.

Share this post


Link to post
15 hours ago, vitor said:

Try this one. The code it uses is instead AppleScript

 

Thanks for this. I didn't know you could invoke say directly with AppleScript. However, the reason I was trying to avoid doing a direct "Keystroke" of the query was due to the delay it created. I have to wait until the whole paragraph is scrolled through, which makes the use of the workflow much more cumbersome. This is why I was attempting to use copy/paste which is much quicker. 

 

The workflow you sent works, but there are two issue I have:

1. The aforementioned delay. Is there any way we could use the clipboard or an external file?

2. The keystroke makes a sound after it completes, it uses the default mac alert sound. I'd like to figure out how to remove that sound. 

 

The first question may lead to this possibility: Obviously this would be down the road, and first things first, but I'd like to eventually enhance this workflow to be able to select a whole block of text, be it an article or chapter for example, and have the workflow parse out the text for sentences using the period as a delimiter. Then perform the "say" command on each sentence, highlighting each sentence using the method we're talking about here. 

 

Thanks again for your help. 

Share this post


Link to post
Posted (edited)

Yes, you can still do it with copy and paste and no delay:

set the clipboard to "{query}"

tell application "System Events"
	keystroke "f" using command down
	keystroke "v" using command down
end tell

say "{query}" speaking rate 250

Download the new version.

 

As for the sound, it’s not the keystroke doing it, it’s the Play Sound node at the end. I copied it from your screenshot.

Edited by vitor

Share this post


Link to post

@vitor That works! How do I cancel the commands that are queued up? For example, if I want to effectively stop the say commands and all subsequent commands? When I was using bash, I was doing a pkill.

Share this post


Link to post
Posted (edited)

@vitor Thank you for the help. I added a feature to split all text into paragraphs and I limited the "find" text selection feature to the original document/window/tab. I think it works rather well. Here's the final workflow, or at least as far as it works for me.

 

Canceling can be done with a separate hotkey. I wanted to make it the same hotkey (to toggle off if no selection), but since the osascript is set to run sequentially, it'll run the pkill at the end which won't work.

 

Here it is.

 

I'm still new to both AS and Workflows, and so if you notice anything quirky with it feel free to let me know.

 

 

Edited by flome
New workflow version which includes handling for non-scriptable applications.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×