4

I've got a speech.synthesis web app that works well, but I want to change some text to a male voice and vice-versa. It works perfectly in Chrome and Mac desktops but for the life of me I can't get it to work on mobile ios (iPhone 11.3.1), both iphone and ipad. Here's the relevant bit (react):

 createSpeech(text) {
    let speech = new SpeechSynthesisUtterance(text);
    let gender = this.state.gender;

    speech.volume = 1; 
    speech.rate =  1;  
    speech.pitch = 1;  
    speech.lang = 'en-US';
    speech.voice = voices[gender];
    speech.voiceURI = voices[gender].voiceURI;

    return speech;
  }

The voices are loaded (one male, and one female) into a variable called voices. This is working. Then the above bit is run on each sentence.

Again, this works perfectly in Chrome and Mac desktops that I tested. On my iPhone, however, I always get the default voice that has been set on the phone itself.

The weird thing is that I can switch to a different language other than english, say italian or spanish, and get the correct voice, but English always only plays as the internally set default voice.

Does anybody know WHY this is happening? Is it a bug? Am I missing something? Has anybody gotten iphone to get a different voice in english other than the one set?

Coco
  • 1,550
  • 3
  • 24
  • 43

2 Answers2

1

SpeechSynthesisUtterance need browser support to provide different voices. In other word, the browser decides which voice to do synthesising.

So it's normal to see sound varies in different systems and browsers because the fundamental support also varies.

If you wish to have a fixed voice in different platforms you'd prefer to use a online API.

This guy also have some related research: http://ejb.github.io/2015/06/07/html5-speech-synthesis-api.html

Yijia Su
  • 314
  • 1
  • 5
1

On iOS, there appears to be a long-standing bug where the voices you get back from getVoices() are not all available to be selected. Specifically, you can only select one voice per locale. The system knows the other voices are there, and if you try to select one of the "forbidden" ones, you will get the voice that is available for the that locale. So for en-US, "Samantha" works, but if you try to select "Alex" you will just get "Samantha". If you want an English male voice, you would need to pick "Daniel" (en-GB). Trying to use the female en-GB voice "Serena" will also get you "Daniel". Notice that there is one voice per locale, not one per language. So for English, you can choose Samantha (en-US), Daniel (en-GB), Karen (en-AU), Moira (en-IR), Tessa (en-SA), Rishi (en-IN). For a full list, check out https://talkrapp.com/speechSynthesis.html

Some languages appear to work because there is only one voice in that locale. But any locale with more than one voice (zh-CN, ru-RU, es-ES, es-MX, it-IT, fr-FR, fr-CA, etc.) will be affected.

This is purely conjecture, but it is an odd coincidence that back in iOS 8 & iOS 9, the names of the voices returned were the "locale". So historically there was good reason to only support one voice per locale. When they updated the system to use the actual voice names, they didn't do it in way that let you select all of the voices, but getVoices() does have access to them.

Doug
  • 351
  • 3
  • 6