OK. After some experimenting I have a solution. This works consistently on both the simulator and my iOS 17 iPhone.
Manually downloaded voices simply work.
Settings > Accessibility > Live Speech (English US) on both the sim and my iphone. I downloaded Alex, Ava (Premium), Evan(Enhanced)
Then used this block to obtain the exact identifier for the voice:
let englishVoices = AVSpeechSynthesisVoice.speechVoices().filter { $0.language.starts(with: "en") }
for voice in englishVoices {
let quality = voice.quality == .enhanced ? "Enhanced" : "Default"
print("\(voice.identifier): \(quality)")
}
TTS as usual:
func speak(text: String) {
let utterance = AVSpeechUtterance(string: text)
if let voice = AVSpeechSynthesisVoice(identifier: "com.apple.voice.enhanced.en-US.Evan") {
utterance.voice = voice
}
// Other configs
utterance.rate = AVSpeechUtteranceDefaultSpeechRate
utterance.pitchMultiplier = 1.0
utterance.volume = 1.0
speechSynthesizer.speak(utterance)
}
It works for Alex, Evan, and Ava which are all that I've tested so far. I'm planning on popping up an alert in my app for the user to download one of these (or another once I test) if they initiate TTS and don't already have one of these voices available. No, it's not ideal to do that but it's a functional workaround in the meantime. Otherwise I can fall back on one of the very terrible old voices (Trinoids, anyone?) that are working by default as listed in my reply above.
Also, I was incorrect about Fred and similar voices that have data in their .audioFileSettings dictionary not working on my device. I was, in fact, failing to release the audio context after speech recognition. My app uses both STT and TTS, although STT doesn't work reliably in the sim (this is a known issue) so I wasn't initiating it there. On my test iPhone, failing to return the AVAudioSession to category .ambient or .playback after SST caused the issue. Fred, Tessa, Kathy, Ralph, Zarvox etc. all work on both the simulator and my test iPhone now. Of course a) no one want's to use those voices; and b) The rest definitely don't work.
I tried setting values in the .audioFileSettings dictionary for other voices like Sara, Ellen etc. thinking that I might have some success. But of course, that property is read-only.
I think at this point I'm comfortable concluding that the issue is those empty .audioFileSettings dictionaries that are properties of each voice in the bundled iOS 17 SDK. Specifically, it is this class: https://developer.apple.com/documentation/avfaudio/avspeechsynthesisvoice that's the problem
New, user downloaded voices will have the necessary data in their audioFileSettings dictionaries, as do very old (and somewhat useless Apple voices bundled in the SDK)
This should be an easy, quick fix for an AV Framework engineer at Apple.
Topic:
Media Technologies
SubTopic:
Audio
Tags: