0

I wrote the code to speak the text of current page.

Here is my code :

$('#speak').on('click', function () {

    if(!('speechSynthesis' in window)){
        alert('This browser doesn\'t support this feature.\n Try again with Chrome browser');
        return;
    }

    navigator.browserInfo= (function(){

        var ua= navigator.userAgent, tem,
        iOS = !!ua.match(/ip(ad|od|hone)/i),
        webkit = !!ua.match(/Webkit/i),
        iOSChrome = iOS && webkit && !ua.match(/Version/i) && ua.match(/CriOS/i) && !ua.match(/EdgeOS/i) && !ua.match(/OPiOS/i),
        M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];

        if(iOSChrome){
            return {'browser': 'Chrome'};
        }

        if(/trident/i.test(M[1])){
            tem=  /\brv[ :]+(\d+)/g.exec(ua) || [];
            return 'IE '+(tem[1] || '');
        }

        if(M[1]=== 'Chrome'){
            tem= ua.match(/\b(OPR|Edge?)\/(\d+)/);
            if(tem!= null) return tem.slice(1).join(' ').replace('OPR', 'Opera').replace('Edg ', 'Edge ');
        }

        M= M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?'];
        if((tem= ua.match(/version\/(\d+)/i))!= null) M.splice(1, 1, tem[1]);
            return {'browser': M[0], 'version': M[1]};
        })();

    if(navigator.browserInfo.browser != 'Chrome'){
        alert('Try again with Chrome browser.');
        return;
    }

    if ($(this).attr('data-opt') == 'cancel') {

        timer(1);
        window.speechSynthesis.cancel();
        $(this).attr('data-opt', 'speak');

        return;
    }

    var text = '';

    if(currentPage == 1)
        text = '';
    else
        text = currentPage >= 35? $('.page' + (currentPage + 1))[0].innerText : $('.page' + currentPage)[0].innerText;

    if (text.trim() == null || text.trim() == '') {

        text = 'There is no text to speak.';
    }

    speak(text);
});

function timer(end) {
    if (end != null) {
        clearTimeout(myTimeout);
        return;
    }
    window.speechSynthesis.pause();
    window.speechSynthesis.resume();
    myTimeout = setTimeout(timer, 10000);
}

function speak(text) {

    if (window.speechSynthesis.speaking) {
        console.error('speechSynthesis.speaking');
        return;
    }

    window.speechSynthesis.cancel();

    if(navigator.userAgent.search('Android') == -1)
        myTimeout = setTimeout(timer, 10000);

    var msg = new SpeechSynthesisUtterance(text);
    msg.pitch = 1;
    msg.rate = 1;

    for (var i = 0; i < window.speechSynthesis.getVoices().length; i++) {

        if (window.speechSynthesis.getVoices()[i].lang == 'ko-KR') {
            msg.voice = window.speechSynthesis.getVoices()[i];
            break;
        }
    }

    msg.onend = function () {
        timer(1);
        $('#speak').attr('data-opt', 'speak');
    };

    msg.onerror = function(event){
        if(navigator.userAgent.search('Mobile') == -1){
            alert('An error has occurred with the speech synthesis: ' + event.error);
        }else{
            console.log('An error has occurred with the speech synthesis: ' + event.error);
        }
        timer(1);
        window.speechSynthesis.cancel();
        $('#speak').attr('data-opt', 'speak');
    };

    $.when(window.speechSynthesis.speak(msg)).then(function () {
        $('#speak').attr('data-opt', 'cancel');
    });
}

A brief explanation of my code : When you click the #speak button first of all the callback function start to filter if this browser support web speech API and if this browser is chrome after passing all the filtering it gets text from the current page's innerText property and finally speak the text.

It seems it works fine in the most case perfectly working on desktop.

The problem i'm facing is it just stops working on mobile especially iOS after speaking all the text or sometimes random, i don't know why it stops so suddenly without any errors..

Since i wrote the timer function i don't think it's the typical problem that appears with long text.

Any help it would be appreciated thank you in advance.

  • 2
    `msg.onend` *might possibly* be the issue, see https://stackoverflow.com/questions/54861046/why-does-a-speechsynthesisutterance-sometimes-not-fire-an-end-event-in-chromiu – Snow Aug 21 '19 at 00:58
  • Do you experience this on both Safari and Chrome? – Kaiido Aug 21 '19 at 01:22
  • @Kaiido No, it’s only available on Chrome since i put the filter – I have 10 fingers Aug 21 '19 at 02:13
  • @Snow Thank you for your comment. I read your question just now did you resolve your problem?? – I have 10 fingers Aug 21 '19 at 12:00
  • I fixed it by saving the current active `SpeechSynthesisUtterance` instance in a semi-permanent outer variable (which gets referenced in multiple locations), to ensure that it doesn't get garbage collected prematurely – Snow Aug 21 '19 at 21:00

0 Answers0