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

后端 未结 2 621
囚心锁ツ
囚心锁ツ 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:05

    I implement that JS functionality for my site for Desktop, Android and iOS.

    As I understood, for Mobile, the speech utterance is regulated by GENERAL PHONE SETTINGS, so user need go to TTS setting and choose preferable voice for specify language, and maybe download the good voice. For example, iOS Alex voice is closed to 800mb and it works offline. List of supported languages you can find on vendor site for specific Android or iOS version.

    So finally we have:

    First, we need to have function to check is it mobile:

    // Detecting a mobile browser

    window.mobilecheck = function() {
        var check = false;
        (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4)))check = true})(navigator.userAgent||navigator.vendor||window.opera);
        return check;
    };
    

    Second, initialization part, piece of Angular code, that you can change in your project, so I have SpeechSynthesisService($log, $q, $cookies, $timeout, commonService) with following code:

        var languagesEnglish = {
            'en-US' : {desc: 'English (United States)', voices: []},
            'en-GB' : {desc: 'English (United Kingdom)', voices: []}
        };
        // 'ru_RU' android codes
        var languagesRussian = {
            'ru-RU' : {desc: 'Russian', voices: []}
        };
    
        var speakerEng = {lang: 'en-US', desc: 'English (United States)', voice: null};
        var speakerRu = {lang: 'ru-RU', desc: 'Russian', voice: null};
        var englishSpeakers = [];
    
        if ('speechSynthesis' in window) {
            if (window.mobilecheck()) {
                englishSpeakers = prepareEnglishSpeakers();
                initVoicesJob.resolve();
            }
    
            window.speechSynthesis.onvoiceschanged = function() {
                if (initVoicesJob.promise.$$state.status) return;
                $log.debug(currentTime() + " InitVoice: onvoiceschanged");
                desktopInitializeVoices();
                englishSpeakers = prepareEnglishSpeakers();
                initVoicesJob.resolve();
            };
        }
    

    So in application I have active speakerEng and active speakerRu, for mobile version the voices arrays are empty.

    Third, when I want in application to say any text I call the following function:

        function sayAnyText(speaker, voiceVolume, text) {
            if (isNotSupportSpeechSynthesis()) {
                var tJob = $q.defer();
                $timeout(function() {
                    tJob.resolve();
                });
                return tJob.promise;
            }
    
            var phrases = [];
            if (text.constructor === Array) {
                for (var ti = 0, tn = text.length; ti

    The main piece is following:

    msg.lang = speaker.lang;
    if (speaker.voice) msg.voice = speaker.voice;
    

    1.we always set a language 2.for desktop version speaker has a voice, for mobile version not.

    p.s. I tested it, and it works for iOS9 (iPhone 6), Android 5.0.1 (Samsung Galaxy 4), and desktop Chrome 48.0. Feel free to ask if you have any questions or if you need more code.

提交回复
热议问题