Reputation: 1342
I would like to convert this AppleScript into Swift.
Where the input is a string (myText: String), and the output is the string being spoken at a variable speed (readingSpeed: Int).
AppleScript:
on run {input, parameters}
say input using "Alex" speaking rate 540
return input
end run
I had considered using SpeakCFString, but could not make it work.
Upvotes: 0
Views: 120
Reputation: 3772
Two approaches here, one using a shell task to call out to say
, and another using the NSSpeechSynthesizer class.
NSTask Implementation:
import Foundation
let input = Process.arguments[1..<Process.arguments.count].joinWithSeparator(" ")
let task = NSTask()
task.launchPath = "/usr/bin/say"
task.arguments = ["-v", "alex", input]
task.launch()
task.waitUntilExit()
print(input)
exit(task.terminationStatus)
NSSpeechSynthesizer implementation:
import Foundation
import AppKit
class Speaker {
var synth: NSSpeechSynthesizer!
var speaking: Bool {
get {
return synth.speaking
}
}
init() {
setupSynth(nil)
}
init(voice: String?) {
setupSynth(voice)
}
func setupSynth(voice: String?) {
var voice = voice
if voice == nil {
voice = NSSpeechSynthesizer.availableVoices()[0]
}
synth = NSSpeechSynthesizer(voice: voice)
}
func say(text: String) -> Bool {
return synth.startSpeakingString(text)
}
}
func say(text: String) -> Bool {
let speaker = Speaker()
if (speaker.say(text)) {
let loop = NSRunLoop.currentRunLoop()
let mode = loop.currentMode ?? NSDefaultRunLoopMode
while loop.runMode(mode, beforeDate: NSDate(timeIntervalSinceNow: 0.1)) && speaker.speaking {}
return true
}
return false
}
let input = Process.arguments[1..<Process.arguments.count].joinWithSeparator(" ")
say(input)
print(input)
Both of these you can run in the same way:
$ swift speak.swift hello world
Upvotes: 2