KML
KML

Reputation: 2322

How do I pause and resume AVSpeechSynthesizer / AVSpeechUtterance in swift?

I have implemented text-to-speech in my app and it works fine with the code I currently use. Basically an algo creates a text, and then if the user clicks on the UIButton the text is being spoken.

Challenge: I want to enable the same UIButton to pause the synthesizer, if the button has already been tapped (i.e. text is currently being spoken) and then resume speaking where it left off, if the button is being tapped again.

I know there are a few functions in the AVFoundation Reference but I am unable to implement them correctly.

Does anyone know how to do this in Swift?

import UIKit
import AVFoundation


    @IBOutlet var generatedText: UILabel!

@IBAction func buttonSpeakClicked(sender: UIButton){
    var mySpeechSynthesizer:AVSpeechSynthesizer = AVSpeechSynthesizer()
    var mySpeechUtterance:AVSpeechUtterance = AVSpeechUtterance(string:generatedText.text)
    mySpeechUtterance.rate = 0.075

mySpeechSynthesizer .speakUtterance(mySpeechUtterance)
}

Upvotes: 12

Views: 6824

Answers (3)

Priyankchoudhary
Priyankchoudhary

Reputation: 836

Here how you can achieve this

First create a class variable of AVSpeechSynthesizer and initialize it

let synth = AVSpeechSynthesizer()

This is the button click method ( for playing the audio, or pausing it if it is already playing

@IBAction func onAVButtonClicked(_ sender: Any) {     
        if synth.isSpeaking {
            // when synth is already speaking or is in paused state

            if synth.isPaused {
                synth.continueSpeaking()
            }else {
            synth.pauseSpeaking(at: AVSpeechBoundary.immediate)
            }
        }else{
            // when synth is not started yet

            let string = attrStr.string
            let utterance = AVSpeechUtterance(string: string)
            utterance.voice = AVSpeechSynthesisVoice(language: "en-US")                    
            synth.speak(utterance)
        }
    }

Upvotes: 2

colossatr0n
colossatr0n

Reputation: 2365

In Main.storyboard, make two UIElements:

  • a UITextView from which the text will be read.
  • a UIButton to play, pause, and resume reading the text.

Create an outlet from the UITextView to the @IBOutlet and an action from the UIButton to the @IBAction in the code below. The following code is a working example, and should be your ViewController.swift:

import UIKit
import AVFoundation

class ViewController: UIViewController {

    // Synth object
    let synth = AVSpeechSynthesizer()
    // Utterance object
    var theUtterance = AVSpeechUtterance(string: "")

    // Text element that the synth will read from.
    @IBOutlet weak var textView: UITextView!

    // Function that starts reading, pauses reading, and resumes
    // reading when the UIButton is pressed.
    @IBAction func textToSpeech(_ sender: UIButton) {
        // The resume functionality
        if (synth.isPaused) {
            synth.continueSpeaking();
        }
        // The pause functionality
        else if (synth.isSpeaking) {
            synth.pauseSpeaking(at: AVSpeechBoundary.immediate)
        }
        // The start functionality
        else if (!synth.isSpeaking) {
            // Getting text to read from the UITextView (textView).
            theUtterance = AVSpeechUtterance(string: textView.text)
            theUtterance.voice = AVSpeechSynthesisVoice(language: "en-GB")
            theUtterance.rate = 0.5
            synth.speak(theUtterance)
        }
    }

    // Standard function
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    // Standard function
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

Upvotes: 4

lancy
lancy

Reputation: 857

AVSpeechSynthesizer Class Reference

Have you tried these methods? - pauseSpeakingAtBoundary: and - continueSpeaking

And these are some properties, (paused and speaking ) that can help you determine the state of the synthesizer.

Code like this should work: mySpeechSynthesizer.pauseSpeakingAtBoundary(AVSpeechBoundary.Immediate)

Upvotes: 8

Related Questions