Swift iOS文字转语音不适用于“延迟”功能;循环中 [英] Swift iOS Text To Speech not working with "delay" in loop

查看:136
本文介绍了Swift iOS文字转语音不适用于“延迟”功能;循环中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试让iOS文本语音合成器说短语列表,各短语之间的延迟有所不同。例如,我可能想说你好,然后等待5秒,然后有人在吗?,然后等待10秒,然后说你好? ...等等。

I'm trying to have the iOS text-to-speech synthesizer "say" a list of phrases with a variable delay between the phrases. For example, I may want to it say "Hello", then wait 5 seconds, then "Is anyone there?", then wait 10 seconds, then say "Hello?"...etc.

我在下面做了一个简单的例子,说明了我正在尝试做的事情。我知道语音合成器正在讲话,其他语音被添加到队列中并按接收顺序进行讲话。

I've made a simple example below that illustrates what I am trying to do. I know that the speech synthesizer is speaking, additional utterances are added to a queue and spoken in the order they are received.

我已经尝试了多种方法来实现此延迟在循环。使用打印语句测试延迟可以确认它们是否有效,但是它们似乎正在干扰text-speach-function功能,该功能说的是第一个短语,但是要等到for循环完成后再说其余的内容。我认为这些类型的任何延迟都会起作用,因为我假设语音合成器是事件驱动的。

I've tried many ways to achieve this delay in the loop. Testing delays with a print statement confirms they are working, but they seem to be interfering with the text-speach-functionality which says the first phrase but waits until the for-loop is done before saying the rest. I thought that any of these types of delays would work as I assume the speech synthesizer is event driven.

我希望能获得一些帮助,或者至少是了解它为何无法正常工作。谢谢!

I'd appreciate some help, or at least an insight it to why it isn't working. Thanks!

这是示例代码:iPhone 6模拟器,Xcode 7.3

Here is the example code: iPhone 6 simulator, Xcode 7.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.

        }
    }
}

我尝试过的一些延迟方法:

Here are some of the delay methods that I have tried:


  1. 将类设置为语音合成器的委托并运行while循环直到合成器完成。

  1. Setup the class as a delegate for the speech synthesizer and run a while loop until the synthesizer is finished.

基于时间的延迟: referenceDate = NSDate()while(NSDate()。timeIntervalSinceDate(referenceDate)< 0.5){}

我从堆栈中尝试过延迟解决方案,例如:快速循环延迟

I've tried "delay" solutions from stack, like this one: Swift delay in loop

func delay(delay:Double ,闭包:()->()){
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(),关闭)
}

Sleep()


推荐答案

这样的事情如何?

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)
                }
            }
        }
    }    
}

注意:


  • 将元组数组传递给说话。一个元组对包含一个要说的短语和一个等待下一个短语说的等待时间。

  • 数组,说出该短语,并在等待延迟后再次将数组的其余部分(如果不是空的话)传递给说话

  • delay 由@matt编写,来自此处。 / li>
  • An array of tuples is passed to speak. A tuple pair contains a phrase to speak and a delay to wait before the next phrase is spoken.
  • speak takes the first item from the array, speaks the phrase and passes the rest of the array (if not empty) to speak again after waiting for the delay.
  • delay was written by @matt and comes from here.

由于上次延迟没有任何用处,因此您可以将其转回并获得第一个延迟后说出的短语。

Since the last delay does nothing useful, you can turn it around and have the first phrase spoken after a delay.

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.")])

这篇关于Swift iOS文字转语音不适用于“延迟”功能;循环中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆