Reputation: 61
I'm trying to use AV Speech Synthesizer on an ARKit app (I've never used it before), but I keep getting the same error message "Unable to list voice folder."
I saw the same question being asked before, and all the answers mentioned iOS 16 being the difference, so they suggested moving the synthesizer declaration line outside the function or moving it directly under where I import AVFoundation.
let synthesizer = AVSpeechSynthesizer()
However, I still get the same error message no matter where I put this line. I'm pretty new to Swift and app development, so I suspect there's another problem, but the relevant code roughly looks like this:
import AVFoundation
let synthesizer = AVSpeechSynthesizer()
//within the view controller class:
func testSpeak() {
let utterance = AVSpeechUtterance(string: "screen has been tapped")
utterance.voice = AVSpeechSynthesisVoice(language: "en-US")
synthesizer.speak(utterance)
}
Are there any alternatives to using AVSpeechSynthesizer if I can't get it to work? I just need something that can read a few strings aloud to users.
Upvotes: 6
Views: 5281
Reputation: 184
Using SwiftUI
When I combined both of the answers above, so from @Vinoth Vino and @devdchaudhary I made it work.
AVSpeechSynthesizer
outside of the local scope and made it @State
variablehere is the full code, btw I am working with Czech language, therefore you will see cs
text in the code
import SwiftUI
import AVFoundation
struct ContentView: View {
@State private var speechSynthesizer: AVSpeechSynthesizer? // 1) taking outside of the local scope of function `speak()`
var body: some View {
Button {
speak()
} label: {
Text("Dotkni se mě.")
}
.buttonStyle(.borderedProminent)
}
func speak() {
let audioSession = AVAudioSession() // 2) handle audio session first, before trying to read the text
do {
try audioSession.setCategory(.playback, mode: .default, options: .duckOthers)
try audioSession.setActive(false)
} catch let error {
print("❓", error.localizedDescription)
}
speechSynthesizer = AVSpeechSynthesizer()
let speechUtterance = AVSpeechUtterance(string: "Vepřík")
speechUtterance.voice = AVSpeechSynthesisVoice(language: "cs")
speechSynthesizer?.speak(speechUtterance)
}
}
#Preview {
ContentView()
}
Upvotes: 4
Reputation: 9734
In SwiftUI, it worked when I added the synthesizer property with the @State
property wrapper. It's not working when I create the property inside the speak method.
struct SpeechView: View {
@State private var speechSynthesizer: AVSpeechSynthesizer?
var body: some View {
Button("Speak") {
speak(text: "Hello World")
}
}
func speak(text: String) {
let utterance = AVSpeechUtterance(string: text)
utterance.voice = AVSpeechSynthesisVoice(language: "en-US")
utterance.rate = 0.1
speechSynthesizer = AVSpeechSynthesizer()
speechSynthesizer?.speak(utterance)
}
}
Upvotes: 4
Reputation: 1065
Change let
to var
, then its works fine.
Declare synthesizer outside of the function and it should be var, not let
var synthesizer = AVSpeechSynthesizer()
Upvotes: 5
Reputation: 718
It means that you haven't changed a previous audioSession's category back to playback.
Are you also recording somewhere else?
If so set your audioSession back to playback when you finish recording like this.
do {
try audioSession?.setCategory(.playback, mode: .default, options: .duckOthers)
try audioSession?.setActive(false)
} catch {
// handle errors
}
Upvotes: 1