首页 > 解决方案 > 等待 ios speechSynthesizer.speak 完成话语

问题描述

我有一个字符串列表,需要在屏幕上显示并同时使用 SpeechSynthesizer.speak 转换为语音

我面临的问题是我无法弄清楚如何等待一个话语完成并且他们转移到下一个话语。发生的情况是文本一个接一个地显示,而没有与音频同步。

func speechAndText(text: String){
    let speechUtterance = AVSpeechUtterance(string: text)
    speechUtterance.rate = AVSpeechUtteranceMaximumSpeechRate/2.0
    speechUtterance.pitchMultiplier = 1.2
    speechUtterance.volume = 1
    speechUtterance.voice = AVSpeechSynthesisVoice(language: "en-GB")
    
    DispatchQueue.main.async {
        self.textView.text = text
    }
    self.speechSynthesizer.speak(speechUtterance)

}

func speakPara(_ phrases: [String]) {
    if let phrase = phrases.first {
            let group = DispatchGroup()
            group.enter()
            
            DispatchQueue.global(qos: .default).async {
                self.speechAndText(text: phrase)
                group.leave()
            }
            
            group.wait()
            
            let rest = Array(phrases.dropFirst())
            if !rest.isEmpty {
                self.speakPara(rest)
            }
    }
}

speakPara函数获取要发音的字符串列表,并一次发送一个字符串speechAndText以转换为语音并在显示器上书写。

任何帮助,将不胜感激。谢谢你。

标签: iosswiftspeech

解决方案


不需要 GCD,你可以使用AVSpeechSynthesizer.

设置self为委托:

self.speechSynthesizer.delegate = self

didFinish通过说出下一段文字来实施。

extension YourClass : AVSpeechSynthesizerDelegate {
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, 
                             didFinish utterance: AVSpeechUtterance) {
        currentIndex += 1
        if currentIndex < phrases.lastIndex {
            self.speechAndText(text: phrases[currentIndex])
        }
    }
}

currentIndex并且phrases是两个实例属性。phrases存储您要朗读的字符串数组,并currentIndex存储当前朗读的文本的索引。speakPara可以像这样实现:

func speakPara(_ phrases: [String]) {
    // reset both helper properties
    self.phrases = phrases 
    self.currentIndex = 0

     // stop speaking whatever it was speaking and start speaking the first item (if any)
    self.speechSynthesizer.stopSpeaking(at: .immediate)
    phrases.map { self.speechAndText(text: $0) }
}

推荐阅读