I want to analyse String
and check whether it contains certain keywords like "1 minute" during text is pronounced by system.
I'm facing issue when AVSpeechSynthesizer
takes the whole string at a time and perform its operation. I don't have control to analyse string during the playing time to check those keywords occurs.
My code as follow for text-to-speech:
func Speech() {
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .mixWithOthers)
try AVAudioSession.sharedInstance().setActive(true)
print("Session is Active")
} catch {
print(error)
}
if !speechSynthesizer.isSpeaking {
self.VoiceString = self.VoiceString+self.DirectionsString
let speechUtterance = AVSpeechUtterance(string: self.VoiceString)
var voiceToUse: AVSpeechSynthesisVoice?
speechUtterance.voice = voiceToUse
speechUtterance.rate = Float(self.RangeSlider.selectedMinValue/2)
speechSynthesizer.speak(speechUtterance)
}
else {
speechSynthesizer.continueSpeaking()
}
animateActionButtonAppearance(shouldHideSpeakButton: true)
}
Is it possible to detect specific string by using
AVSpeechSynthesizer
or have you any other approach?
You should implement delegate of AVSpeechSynthesizer
and add following code:
var myText = "This is my text, which will be detect on text-to-speech operation"
override func viewDidLoad() {
super.viewDidLoad()
speechSynthesizer.delegate = self
}
Implemented willSpeakRangeOfSpeechString
which will called every spoken word by system in text string. You can implement String
type's contains()
method to detect particular string in your text.
extension TextToSpeechVC: AVSpeechSynthesizerDelegate {
func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, willSpeakRangeOfSpeechString characterRange: NSRange, utterance: AVSpeechUtterance) {
let string = self.myText[characterRange.lowerBound..<characterRange.upperBound]
if string.trim == "operation" {
print("string = \(string)")
}
}
}
Add String
extension for subscript of range.
extension String {
var trim: String {
return self.trimmingCharacters(in: .whitespacesAndNewlines)
}
subscript (bounds: CountableClosedRange<Int>) -> String {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return String(self[start...end])
}
subscript (bounds: CountableRange<Int>) -> String {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return String(self[start..<end])
}
}
I hope this will help you.