TTS Alex voice is treated like available when it's actually not

Hello everybody!

In my app I allow the user to change TTS voices and English Alex voice is one of possible options. However, there are some cases when it's treated as available when it's actually not. It results in pronouncing the TTS utterance with another voice.

To prepare the list of available voices I use next code:
Code Block
NSMutableArray *voices = [NSMutableArray new];
for (AVSpeechSynthesisVoice *voice in [AVSpeechSynthesisVoice speechVoices]) {
[voices addObject:@{
@"id": voice.identifier,
@"name": voice.name,
@"language": voice.language,
@"quality": (voice.quality == AVSpeechSynthesisVoiceQualityEnhanced) ? @500 : @300
}];
}


To start the playback I use the next code (here it's simplified a bit):

Code Block
AVSpeechUtterance *utterance = [[AVSpeechUtterance alloc] initWithString:text];
utterance.voice = [AVSpeechSynthesisVoice voiceWithIdentifier:voice];
[AVSpeechSynthesizer speakUtterance:utterance];


Cases when AVSpeechSynthesisVoice returns Alex as available when it's not:
  1. The easiest way to reproduce it is on simulator. When I download Alex from iOS settings, the download button disappear, but when I press on the voice nothing happens. As a result it seems to be downloaded, however it can't be deleted.

  2. In some cases Alex is dowloaded correctly and is actually available in the app, but when I try to delete it, it looks like it's not fully deleted. As a result it's treated as available in my app, but in iOS settings it's shown as not downloaded.

  3. If the iPhone storage is close to the full state as much as possible and Alex voice hasn't been used recently, looks like it's being offloaded, so it's shown as available both in iOS settings and in my app, but in fact the utterance is being pronounced by another voice.

For all cases above in my app Alex looks like it's available, but when I pass it to the utterance it's pronounced with some different voice. Note that it happens only with this voice, I haven't seen such a case for others. Maybe this voice should be treated separately somehow?

Replies

Downloadable voices are indeed subject to purges when disk space is running low. When this happens, and you give us an identifier for a voice that no longer exists, we do try to speak the request with a voice matching the same language code as the voice you attempted to use. voiceWithIdentifier should return the voice that will be used in this case.

if This is not the behavior that you’re seeing, please file a bug through feedback assistant that includes a sysdiagnose taken after you queried for the Alex voice. For cases where the information you are getting back from the API is not consistent with the information you’re seeing in settings, please include a screenshot of the settings page as well.

For issues related to the voice not being available after download, please file a bug with a sysdiagnose taken after the download has completed.

I'm seeing the same issue here
AVSpeechSynthesisVoice.speechVoices()
returns the Alex voice.
let voice = AVSpeechSynthesisVoice(identifier: AVSpeechSynthesisVoiceIdentifierAlex)
returns the Alex voice (I checked the identifier, name etc. on the returned instance, BUT voice?.audioFileSettings is an empty dict).

But the voice actually used is Samantha (my device default).
Checking my device Settings > Accessibility > Spoken Content > English shows that Alex isn't even downloaded.

Some more observations I made:

  • I've never manually downloaded the Alex voice on this device.
  • Debugging the voice details for the Alex voice returns an empty Dictionary for voice?.audioFileSettings, while all other "available" voices will return a non-empty dict
  • After downloading Alex voice?.audioFileSettings does indeed return a non-empty dictionary
  • Using the no param constructor AVSpeechSynthesisVoice() will print an error message [AXSpeechAssetDownload] Could not find any name for this voice: (null) but it will return a non-nil voice, which has no language, name or identifier set. AVSpeechSynthesizer uses Samantha (device-default) in that case as well.

Bottom line, to check if Alex is really installed, check if voice?.audioFileSettings is a non-empty dict

I have seems problem. I never load Alex voice. In my app I filter voice from voices array and I see Alex voice available, but not read. Read some woman voice. This some bug? Maybe somebody how to solve this problem?