iosavspeechsynthesizer

AVSpeechSynthesizer freezes iOS app for a few seconds


Using AVSpeechSynthesizer in my ARKit app makes the app freeze for a few seconds before a sound is emitted. I've created this helper class:

public class TextToSpeech {
    class func speak(text: String) {
        let utterance = AVSpeechUtterance(string: text)
        utterance.voice = AVSpeechSynthesisVoice(language: "EN")
        utterance.rate = 0.3
        let synthesizer = AVSpeechSynthesizer()
        synthesizer.speak(utterance)
    }
}

However, when I call its class function, the app freezes for a few seconds.

class MyViewController: UIViewController {
    ...

    @objc func didTapButton() {
        TextToSpeech.speak(text: "test") // it works but it freezes the app temporarily
    }
}

It doesn't matter where in the code I call this. I've tried to enclose this call in a DispatchQueue but it still doesn't work. How can I fix this freeze? Is this normal behavior?


Solution

  • Looks like it's connected with the internal AVSpeechSynthesizer queue. You can try to make it manage the thing in background, since there's no mention about AVSpeechSynthesizer is main thread only. Do so by adding the last line (synthesizer.speak(utterance)) call to the background queue capturing references to the synthesizer and utterance objects like that:

    DispatchQueue.global(qos: .default).async { 
        synthesizer.speak(utterance) 
    } 
    

    I think the reason why you have ui blocked is because synthesizer instance has to block current thread to speak. So you must wait till synthesizer finish speaking before being deallocated on the exit from your speak() method.

    UPD: changed queue from .background to .default in the code sample – thanks to comments from Andriy below