I\'m trying to get the list of supported speech synthesis voices on iOS Safari.
As per the API, I should be able to get an array of voices by calling:
wi
I also encountered this and reported it as a bug to Apple. As of today the bug report is still open.
What I ended up doing as workaround was to hard-code an array of the 37 voices. If speechSynthesis.getVoices()
returns an empty array then use the hard-coded array instead.
var _voices = [];
// iOS 8
var _iOSvoices = [
{name: "pt-BR", voiceURI: "pt-BR", lang: "pt-BR", localService: true, default: true},
{name: "fr-CA", voiceURI: "fr-CA", lang: "fr-CA", localService: true, default: true},
{name: "sk-SK", voiceURI: "sk-SK", lang: "sk-SK", localService: true, default: true},
{name: "th-TH", voiceURI: "th-TH", lang: "th-TH", localService: true, default: true},
{name: "ro-RO", voiceURI: "ro-RO", lang: "ro-RO", localService: true, default: true},
{name: "no-NO", voiceURI: "no-NO", lang: "no-NO", localService: true, default: true},
{name: "fi-FI", voiceURI: "fi-FI", lang: "fi-FI", localService: true, default: true},
{name: "pl-PL", voiceURI: "pl-PL", lang: "pl-PL", localService: true, default: true},
{name: "de-DE", voiceURI: "de-DE", lang: "de-DE", localService: true, default: true},
{name: "nl-NL", voiceURI: "nl-NL", lang: "nl-NL", localService: true, default: true},
{name: "id-ID", voiceURI: "id-ID", lang: "id-ID", localService: true, default: true},
{name: "tr-TR", voiceURI: "tr-TR", lang: "tr-TR", localService: true, default: true},
{name: "it-IT", voiceURI: "it-IT", lang: "it-IT", localService: true, default: true},
{name: "pt-PT", voiceURI: "pt-PT", lang: "pt-PT", localService: true, default: true},
{name: "fr-FR", voiceURI: "fr-FR", lang: "fr-FR", localService: true, default: true},
{name: "ru-RU", voiceURI: "ru-RU", lang: "ru-RU", localService: true, default: true},
{name: "es-MX", voiceURI: "es-MX", lang: "es-MX", localService: true, default: true},
{name: "zh-HK", voiceURI: "zh-HK", lang: "zh-HK", localService: true, default: true},
{name: "sv-SE", voiceURI: "sv-SE", lang: "sv-SE", localService: true, default: true},
{name: "hu-HU", voiceURI: "hu-HU", lang: "hu-HU", localService: true, default: true},
{name: "zh-TW", voiceURI: "zh-TW", lang: "zh-TW", localService: true, default: true},
{name: "es-ES", voiceURI: "es-ES", lang: "es-ES", localService: true, default: true},
{name: "zh-CN", voiceURI: "zh-CN", lang: "zh-CN", localService: true, default: true},
{name: "nl-BE", voiceURI: "nl-BE", lang: "nl-BE", localService: true, default: true},
{name: "en-GB", voiceURI: "en-GB", lang: "en-GB", localService: true, default: true},
{name: "ar-SA", voiceURI: "ar-SA", lang: "ar-SA", localService: true, default: true},
{name: "ko-KR", voiceURI: "ko-KR", lang: "ko-KR", localService: true, default: true},
{name: "cs-CZ", voiceURI: "cs-CZ", lang: "cs-CZ", localService: true, default: true},
{name: "en-ZA", voiceURI: "en-ZA", lang: "en-ZA", localService: true, default: true},
{name: "en-AU", voiceURI: "en-AU", lang: "en-AU", localService: true, default: true},
{name: "da-DK", voiceURI: "da-DK", lang: "da-DK", localService: true, default: true},
{name: "en-US", voiceURI: "en-US", lang: "en-US", localService: true, default: true},
{name: "en-IE", voiceURI: "en-IE", lang: "en-IE", localService: true, default: true},
{name: "he-IL", voiceURI: "he-IL", lang: "he-IL", localService: true, default: true},
{name: "hi-IN", voiceURI: "hi-IN", lang: "hi-IN", localService: true, default: true},
{name: "el-GR", voiceURI: "el-GR", lang: "el-GR", localService: true, default: true},
{name: "ja-JP", voiceURI: "ja-JP", lang: "ja-JP", localService: true, default: true}
];
function populateVoices() {
// wait first
var watch = setTimeout(function() {
_voices = speechSynthesis.getVoices();
if (_voices.length === 0) {
// use hard-coded list because speechSynthesis.getVoices() didn't work
_voices = _iOSvoices;
}
clearTimeout(watch);
}, 100);
}
UPDATE
iOS 9 is somewhat better at this if you remove the delay.
function _populateVoices() {
_voices = speechSynthesis.getVoices();
if (_voices.length === 0) {
// use hard-coded list because speechSynthesis.getVoices() didn't work
_voices = _iOS9voices;
}
}
var _iOS9voices = [
{ name: "Maged", voiceURI: "com.apple.ttsbundle.Maged-compact", lang: "ar-SA", localService: true, "default": true },
{ name: "Zuzana", voiceURI: "com.apple.ttsbundle.Zuzana-compact", lang: "cs-CZ", localService: true, "default": true },
{ name: "Sara", voiceURI: "com.apple.ttsbundle.Sara-compact", lang: "da-DK", localService: true, "default": true },
{ name: "Anna", voiceURI: "com.apple.ttsbundle.Anna-compact", lang: "de-DE", localService: true, "default": true },
{ name: "Melina", voiceURI: "com.apple.ttsbundle.Melina-compact", lang: "el-GR", localService: true, "default": true },
{ name: "Karen", voiceURI: "com.apple.ttsbundle.Karen-compact", lang: "en-AU", localService: true, "default": true },
{ name: "Daniel", voiceURI: "com.apple.ttsbundle.Daniel-compact", lang: "en-GB", localService: true, "default": true },
{ name: "Moira", voiceURI: "com.apple.ttsbundle.Moira-compact", lang: "en-IE", localService: true, "default": true },
{ name: "Samantha (Enhanced)", voiceURI: "com.apple.ttsbundle.Samantha-premium", lang: "en-US", localService: true, "default": true },
{ name: "Samantha", voiceURI: "com.apple.ttsbundle.Samantha-compact", lang: "en-US", localService: true, "default": true },
{ name: "Tessa", voiceURI: "com.apple.ttsbundle.Tessa-compact", lang: "en-ZA", localService: true, "default": true },
{ name: "Monica", voiceURI: "com.apple.ttsbundle.Monica-compact", lang: "es-ES", localService: true, "default": true },
{ name: "Paulina", voiceURI: "com.apple.ttsbundle.Paulina-compact", lang: "es-MX", localService: true, "default": true },
{ name: "Satu", voiceURI: "com.apple.ttsbundle.Satu-compact", lang: "fi-FI", localService: true, "default": true },
{ name: "Amelie", voiceURI: "com.apple.ttsbundle.Amelie-compact", lang: "fr-CA", localService: true, "default": true },
{ name: "Thomas", voiceURI: "com.apple.ttsbundle.Thomas-compact", lang: "fr-FR", localService: true, "default": true },
{ name: "Carmit", voiceURI: "com.apple.ttsbundle.Carmit-compact", lang: "he-IL", localService: true, "default": true },
{ name: "Lekha", voiceURI: "com.apple.ttsbundle.Lekha-compact", lang: "hi-IN", localService: true, "default": true },
{ name: "Mariska", voiceURI: "com.apple.ttsbundle.Mariska-compact", lang: "hu-HU", localService: true, "default": true },
{ name: "Damayanti", voiceURI: "com.apple.ttsbundle.Damayanti-compact", lang: "id-ID", localService: true, "default": true },
{ name: "Alice", voiceURI: "com.apple.ttsbundle.Alice-compact", lang: "it-IT", localService: true, "default": true },
{ name: "Kyoko", voiceURI: "com.apple.ttsbundle.Kyoko-compact", lang: "ja-JP", localService: true, "default": true },
{ name: "Yuna", voiceURI: "com.apple.ttsbundle.Yuna-compact", lang: "ko-KR", localService: true, "default": true },
{ name: "Ellen", voiceURI: "com.apple.ttsbundle.Ellen-compact", lang: "nl-BE", localService: true, "default": true },
{ name: "Xander", voiceURI: "com.apple.ttsbundle.Xander-compact", lang: "nl-NL", localService: true, "default": true },
{ name: "Nora", voiceURI: "com.apple.ttsbundle.Nora-compact", lang: "no-NO", localService: true, "default": true },
{ name: "Zosia", voiceURI: "com.apple.ttsbundle.Zosia-compact", lang: "pl-PL", localService: true, "default": true },
{ name: "Luciana", voiceURI: "com.apple.ttsbundle.Luciana-compact", lang: "pt-BR", localService: true, "default": true },
{ name: "Joana", voiceURI: "com.apple.ttsbundle.Joana-compact", lang: "pt-PT", localService: true, "default": true },
{ name: "Ioana", voiceURI: "com.apple.ttsbundle.Ioana-compact", lang: "ro-RO", localService: true, "default": true },
{ name: "Milena", voiceURI: "com.apple.ttsbundle.Milena-compact", lang: "ru-RU", localService: true, "default": true },
{ name: "Laura", voiceURI: "com.apple.ttsbundle.Laura-compact", lang: "sk-SK", localService: true, "default": true },
{ name: "Alva", voiceURI: "com.apple.ttsbundle.Alva-compact", lang: "sv-SE", localService: true, "default": true },
{ name: "Kanya", voiceURI: "com.apple.ttsbundle.Kanya-compact", lang: "th-TH", localService: true, "default": true },
{ name: "Yelda", voiceURI: "com.apple.ttsbundle.Yelda-compact", lang: "tr-TR", localService: true, "default": true },
{ name: "Ting-Ting", voiceURI: "com.apple.ttsbundle.Ting-Ting-compact", lang: "zh-CN", localService: true, "default": true },
{ name: "Sin-Ji", voiceURI: "com.apple.ttsbundle.Sin-Ji-compact", lang: "zh-HK", localService: true, "default": true },
{ name: "Mei-Jia", voiceURI: "com.apple.ttsbundle.Mei-Jia-compact", lang: "zh-TW", localService: true, "default": true }
];