Web speech API: Consistently get the supported speech synthesis voices on iOS safari

后端 未结 2 619
囚心锁ツ
囚心锁ツ 2021-02-06 11:04

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         


        
2条回答
  •  灰色年华
    2021-02-06 12:00

    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 }
    ];
    

提交回复
热议问题