SpeechSynthesis in Android-Chrome: cannot change English voice from US English
Asked Answered
E

2

6

I'm using the speech synthesis API on Android-Chrome. The issue is that although there are 4 English voices available, it is always US English that is used by the browser, no matter what the code specifies. I can use other languages e.g. French, just not other English voices e.g en-AU, GB, or IN.

This code filters British English voice objects from the getVoices array and uses the first to utter the word 'tomato'. The problem is that the word is always pronounced "to-may-lo" not "to-mar-to" which means my text doesn't rhyme as it should.

The voice object that was used is displayed and (on the phones I've tried) is an GB one.

The html...

<!DOCTYPE html>
<html lang="en-GB">
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Let's not call the whole thing off</title>
        <script src="tomato.js" defer></script>
    </head>
    <body>
        <div id="tomato" lang="en-GB">Tomato</div>
        <div id="platform"></div>
    </body>
</html>

And the script...

var platform = document.getElementById("platform");
var tomato = document.getElementById("tomato");

var voices = [];
var voicesGB = [];
voices = speechSynthesis.getVoices();
speechSynthesis.onvoiceschanged = function() {
    voices = speechSynthesis.getVoices();
    voicesGB = voices.filter(voice => /en(-|_)GB/.test(voice.lang));
};

function speak(word) {
    var msg = new SpeechSynthesisUtterance();
    msg.default = false;
    msg.text = word;
    msg.voice = voicesGB[0];
    msg.lang = voicesGB[0].lang;
    window.speechSynthesis.speak(msg);
    for (var p in msg.voice) {
        platform.innerHTML += p + ': ' + msg.voice[p] + '<br>\n';
    }
}

tomato.addEventListener("click",() => {speak('tomato');});

And a jsbin: https://jsbin.com/xefukemuga/edit?html,js,output Run this in Android Chrome and tap the word 'tomato'.

I have searched all over and tried various fixes. How do you control what voice Android-Chrome uses?

Eisk answered 24/10, 2018 at 17:42 Comment(6)
Did you fix it? I had a similar issue and found a workaround, see my answer here: #56729154Bona
Well, I see your code filters on '_' so maybe that is not the issue unless voicesGB[0].long still has a dash.Bona
@Bona the code filters on dash or underscore: /en(-|_)GB/Eisk
I saw, but I assume what ends up in msg.lang would match what the platform stores, but if not, maybe you have replace '-' with '_'? Or have you resolved the issue already some other way? I'm still interested in this problem as it doesn't make sense why the platforms don't follow the clear standard.Bona
@Bona No, the issue is still unresolved.Eisk
OK. For me too. The same app sometimes uses the correct voice and sometimes the American English voice. Even with no source code changes or phone settings changes. Refreshing cache does not seem to make a difference. If I find out more I will post. Thank youBona
M
6

The only way to work around this issue on Android version 5.0.2 is to change the default voice in the Android settings and then restart the device. That will let you use the voice you want, but the other English ones will then be unavailable. Here is some more detail:

SpeechSynthesis.getVoices() will return several options for English (United States, Australia, Nigeria, India, and United Kingdom) but only one is available at a time. You can pick which one by going to the Settings app, then Controls->Language and input->Text-to-speech options. Select the gear icon next to Google Text-to-speech Engine, then under Language you can update the exact locale you want to use. If you select "Install voice data" you can even select from a sample of different voices for some locales. You need to restart the device after changing this setting for it to take effect.

The voice used on an Android device when you play a SpeechSynthesisUtterance will depend on what you have selected in the Android settings. You can choose which language you want to play from javascript (see below for details) but you have no control over the locale or exact voice used.

This problem occurs on Chrome and Firefox, so it is likely a problem with the Android platform's implementation of the speechSynthesis API. It's unlikely that a browser update will fix this, but different versions of Android might. (My test device is on Android 5.0.2, so if this is fixed in a future update, please let me know).

Muscid answered 22/4, 2020 at 13:22 Comment(3)
Thanks, yes I'd done this on my phone and whilst it now uses the en-GB voice, of course I now cannot use the US, Indian or Australian (or other) voices! Also I've since realised that this affects any language with more than 1 voice e.g. Spanish has es-ES and es-US but only the es-US voice is used. I had already tried the tip from your linked page, to set the lang attribute of the utterance, but this does not work. Thanks for your reply and good luck resolving your Mac problem.Eisk
Yeah, it's not a "fix" as much as a workaround for getting a single voice you want. Android is just busted, and it doesn't seem to matter which tts engine you use (I've tried the default google one, Samsung, and Vocalizer TTS). I'd be interested if later versions of android have fixed this.Muscid
I'm happy to say with Android version 13 (I'm using a Pixel 7) no reboot is required! Just switch and the next time you use the JS code, it uses the language you chose. You don't even need to reload the web app. I tested on Firefox and it works great.Nightclub
N
1

With the latest version of Android (13) you can switch the system settings (System -> Languages & input -> Text-to-speech output). If you change the language to "English (United Kingdom)" you can then use that in your web app. This is obviously not ideal for your users, but if you are developing an app only for yourself, it works great.

Nightclub answered 21/5, 2023 at 12:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.