Avspeechsynthesizer Isspeaking Not Working in Swift

AVSpeechSynthesizer isSpeaking not working in Swift

It is just not updated in your case, because synthesiser.isSpeaking is not observable for SwiftUI. You have to use view model class and delegate callbacks to handle this state changes

Here is initial demo (you can add stop/pause/continue actions by yourself)

class SpeachViewModel: NSObject, ObservableObject, AVSpeechSynthesizerDelegate {
@Published var isSpeaking = false

private var synthesizer = AVSpeechSynthesizer()
override init() {
super.init()
synthesizer.delegate = self
}

deinit {
synthesizer.delegate = nil
}

func speak(_ utterance: AVSpeechUtterance) {
self.synthesizer.speak(utterance)
}

// MARK: AVSpeechSynthesizerDelegate
internal func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didStart utterance: AVSpeechUtterance) {
self.isSpeaking = true
}

internal func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
self.isSpeaking = false
}

internal func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didPause utterance: AVSpeechUtterance) {
self.isSpeaking = false
}

internal func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didCancel utterance: AVSpeechUtterance) {
self.isSpeaking = false
}

internal func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didContinue utterance: AVSpeechUtterance) {
self.isSpeaking = true
}
}

struct ContentView: View {

@ObservedObject var vm = SpeachViewModel()
var utterance = AVSpeechUtterance(string: "Hello World")

var body: some View {
VStack {
Text(vm.isSpeaking ? "Speaking" : "Not Speaking")
Button(action: {vm.speak(utterance)}) {
Text("Speak To Me")
}
}
}
}

AVSpeechSynthesizer isn't working under ios16 anymore

u need to assign a delegate

class Speaker: NSObject, AVSpeechSynthesizerDelegate {
let synthesizer = AVSpeechSynthesizer()
init() {
synthesizer.delegate = self
}

func speak(msg: String) {
let utterance = AVSpeechUtterance(string: msg)

utterance.rate = 0.57
utterance.pitchMultiplier = 0.8
utterance.postUtteranceDelay = 0.2
utterance.volume = 0.8

let voice = AVSpeechSynthesisVoice(language: "en-US")

utterance.voice = voice
synthesizer.speak(utterance)
}
}

now is how to use

let s = Speaker()

s.speak(msg: "The quick brown fox jumped over the lazy dog.")

AVSpeechSynthesizer - If AVSpeechSynthesizer is Speaking & if has stopped speaking

A quick look at the docs for AVSpeechSynthesizer reveals that it has a delegate property.

You should set the delegate and implement the AVSpeechSynthesizerDelegate protocol so that you can be notified of events for the speech synthesizer.

Events such as

- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer
didFinishSpeechUtterance:(AVSpeechUtterance *)utterance;

and

- (void)speechSynthesizer:(AVSpeechSynthesizer *)synthesizer
didStartSpeechUtterance:(AVSpeechUtterance *)utterance;

would be most interesting to you, considering you want to know when it starts and stops. There are also events for being canceled, paused, and continued, which you will probably also want to implement to hide and show your UI.

iOS - AVSpeechSynthesizer pause and continueSpeaking issue

I implemented the following code to check your problem (testings under Mojave 10.14.4, iOS 12.2, Xcode 10.2.1 and swift 5.0):

class SpeechSynthesis: UIViewController {

var synthesizer = AVSpeechSynthesizer()
var playQueue = [AVSpeechUtterance]()

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

for i in 1...10 {
let stringNb = "number " + String(i) + " of the speech synthesizer."
let utterance = AVSpeechUtterance(string: stringNb)
playQueue.append(utterance)
}

for utterance in playQueue {
synthesizer.speak(utterance)
}
}

@IBAction func pauseButton(_ sender: UIButton) {

if (synthesizer.isSpeaking == true) {
if (synthesizer.pauseSpeaking(at: .immediate) == true) {
print("PAUSE")
} else {
print("P.R.O.B.L.E.M. when pausing.")
}
}
}

@IBAction func resumeButton(_ sender: UIButton) {

if (synthesizer.isPaused == true) {
if (synthesizer.continueSpeaking() == true) {
print("CONTINUE")
} else {
print("P.R.O.B.L.E.M. when resuming.")
}
}
}
}

I noticed another problem with the boundary .word that doesn't always pause when triggered but when this constraint is changed to .immediate, everything is resuming from where it paused.

However, when it rarely pauses with the boundary .word, it always resumes from where it paused as well.

I don't know where your problem comes from but with the configuration mentioned above and this code snippet, the speech synthesizer resumes from where it paused.



Related Topics



Leave a reply



Submit