Swift iOS Text To Speech 无法在循环中使用 "delay"
Swift iOS Text To Speech not working with "delay" in loop
我正在尝试让 iOS 文本到语音合成器 "say" 一个短语列表,短语之间的延迟可变。例如,我可能希望它说 "Hello",然后等待 5 秒,然后 "Is anyone there?",然后等待 10 秒,然后说 "Hello?"...等等。
我在下面做了一个简单的例子来说明我正在尝试做的事情。我知道语音合成器正在说话,额外的话语被添加到队列中并按照收到的顺序说话。
我已经尝试了很多方法来实现这种循环延迟。使用 print 语句测试延迟确认它们正在工作,但它们似乎干扰了文本语音功能,该功能说第一个短语但等到 for 循环完成后再说其余部分。我认为任何这些类型的延迟都会起作用,因为我假设语音合成器是事件驱动的。
我希望得到一些帮助,或者至少了解它为什么不起作用。谢谢!
这里是示例代码:iPhone6模拟器,Xcode7.3
import UIKit
import AVFoundation
class ViewController: UIViewController {
let speechSynthesizer = AVSpeechSynthesizer()
var phraseArray: [String] = ["One", "Two", "Three", "Four", "Five", "Six", "Seven"]
override func viewDidLoad() {
super.viewDidLoad()
for phrase in phraseArray{
let speechUtterance = AVSpeechUtterance(string: phrase)
speechSynthesizer.speakUtterance(speechUtterance)
//"delay()" goes here. It needs to be a variable length delay.
}
}
}
以下是我尝试过的一些延迟方法:
将 class 设置为语音合成器的委托,并 运行 一个 while 循环,直到合成器完成。
基于时间的延迟:referenceDate = NSDate() while(NSDate().timeIntervalSinceDate(referenceDate) < 0.5) {}
我尝试了 "delay" 堆栈解决方案,例如:
func delay(delay:Double, closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
睡眠()
这样的事情怎么样:
import UIKit
import AVFoundation
func delay(_ delay:Double, closure:@escaping ()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}
class ViewController: UIViewController {
let speechSynthesizer = AVSpeechSynthesizer()
override func viewDidLoad() {
super.viewDidLoad()
speak([("Hello", 5.0), ("Is there anyone there?", 10.0), ("Hello?", 0.0)])
}
func speak(_ phrases: [(phrase: String, wait: Double)]) {
if let (phrase, wait) = phrases.first {
let speechUtterance = AVSpeechUtterance(string: phrase)
speechSynthesizer.speak(speechUtterance)
let rest = Array(phrases.dropFirst())
if !rest.isEmpty {
delay(wait) {
self.speak(rest)
}
}
}
}
}
备注:
- 一个元组数组被传递给
speak
。元组对包含要说的短语和在说下一个短语之前等待的延迟。
speak
从数组中取出第一项,说出短语并在等待延迟后将数组的其余部分(如果不为空)再次传递给 speak
。
delay
由@matt 编写,来自 here。
由于最后的延迟没有任何用处,您可以将其反过来,让第一个短语在延迟后说出。
func speak(_ phrases: [(wait: Double, phrase: String)]) {
if let (wait, phrase) = phrases.first {
delay(wait) {
let speechUtterance = AVSpeechUtterance(string: phrase)
self.speechSynthesizer.speak(speechUtterance)
let rest = Array(phrases.dropFirst())
if !rest.isEmpty {
self.speak(rest)
}
}
}
}
你会像这样使用这个:
// Wait 5 seconds before starting...
speak([(5.0, "I'm sorry Dave."), (2.0, "I can't do that.")])
我正在尝试让 iOS 文本到语音合成器 "say" 一个短语列表,短语之间的延迟可变。例如,我可能希望它说 "Hello",然后等待 5 秒,然后 "Is anyone there?",然后等待 10 秒,然后说 "Hello?"...等等。
我在下面做了一个简单的例子来说明我正在尝试做的事情。我知道语音合成器正在说话,额外的话语被添加到队列中并按照收到的顺序说话。
我已经尝试了很多方法来实现这种循环延迟。使用 print 语句测试延迟确认它们正在工作,但它们似乎干扰了文本语音功能,该功能说第一个短语但等到 for 循环完成后再说其余部分。我认为任何这些类型的延迟都会起作用,因为我假设语音合成器是事件驱动的。
我希望得到一些帮助,或者至少了解它为什么不起作用。谢谢!
这里是示例代码:iPhone6模拟器,Xcode7.3
import UIKit
import AVFoundation
class ViewController: UIViewController {
let speechSynthesizer = AVSpeechSynthesizer()
var phraseArray: [String] = ["One", "Two", "Three", "Four", "Five", "Six", "Seven"]
override func viewDidLoad() {
super.viewDidLoad()
for phrase in phraseArray{
let speechUtterance = AVSpeechUtterance(string: phrase)
speechSynthesizer.speakUtterance(speechUtterance)
//"delay()" goes here. It needs to be a variable length delay.
}
}
}
以下是我尝试过的一些延迟方法:
将 class 设置为语音合成器的委托,并 运行 一个 while 循环,直到合成器完成。
基于时间的延迟:
referenceDate = NSDate() while(NSDate().timeIntervalSinceDate(referenceDate) < 0.5) {}
我尝试了 "delay" 堆栈解决方案,例如:
func delay(delay:Double, closure:()->()) { dispatch_after( dispatch_time( DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)) ), dispatch_get_main_queue(), closure) }
睡眠()
这样的事情怎么样:
import UIKit
import AVFoundation
func delay(_ delay:Double, closure:@escaping ()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}
class ViewController: UIViewController {
let speechSynthesizer = AVSpeechSynthesizer()
override func viewDidLoad() {
super.viewDidLoad()
speak([("Hello", 5.0), ("Is there anyone there?", 10.0), ("Hello?", 0.0)])
}
func speak(_ phrases: [(phrase: String, wait: Double)]) {
if let (phrase, wait) = phrases.first {
let speechUtterance = AVSpeechUtterance(string: phrase)
speechSynthesizer.speak(speechUtterance)
let rest = Array(phrases.dropFirst())
if !rest.isEmpty {
delay(wait) {
self.speak(rest)
}
}
}
}
}
备注:
- 一个元组数组被传递给
speak
。元组对包含要说的短语和在说下一个短语之前等待的延迟。 speak
从数组中取出第一项,说出短语并在等待延迟后将数组的其余部分(如果不为空)再次传递给speak
。delay
由@matt 编写,来自 here。
由于最后的延迟没有任何用处,您可以将其反过来,让第一个短语在延迟后说出。
func speak(_ phrases: [(wait: Double, phrase: String)]) {
if let (wait, phrase) = phrases.first {
delay(wait) {
let speechUtterance = AVSpeechUtterance(string: phrase)
self.speechSynthesizer.speak(speechUtterance)
let rest = Array(phrases.dropFirst())
if !rest.isEmpty {
self.speak(rest)
}
}
}
}
你会像这样使用这个:
// Wait 5 seconds before starting...
speak([(5.0, "I'm sorry Dave."), (2.0, "I can't do that.")])