Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Speech Synthesis API Highlight words as they are spoken

Currently, I'm making a simple app where text is spoken using the speech synthesis API. I want to highlight the words (bold) as they are being spoken. I currently have a very basic implementation doing this using the 'onboundary' event. However, I'm wondering if there's a better/nicer way of doing it, as my implementation is based on a few presumptions.

var words;
var wordIdx;
var text;
var utterance = new SpeechSynthesisUtterance();
utterance.lang = 'en-UK';
utterance.rate = 1;

window.onload = function(){
    document.getElementById('textarea').innerText = 'This is a text area.  It is used as a simple test to check whether these words are highlighted as they are spoken using the web speech synthesis API (utterance).';

    document.getElementById('playbtn').onclick = function(){
        text    = document.getElementById('textarea').innerText;
        words   = text.split(' ');
        wordIdx = 0;

        utterance.text = text;
        speechSynthesis.speak(utterance);
    }

    utterance.onboundary = function(event){
        var e = document.getElementById('textarea');
        var it = '';

        for(var i = 0; i < words.length; i++){
            if(i === wordIdx){
                it += '<strong>' + words[i] + '</strong>';
            } else {
                it += words[i];
            }

            it += ' ';
        }

        e.innerHTML = it;
        wordIdx++;
    }
}
like image 750
BoyUnderTheMoon Avatar asked Jun 30 '16 10:06

BoyUnderTheMoon


People also ask

What is Speech synthesis utterance?

The SpeechSynthesisUtterance interface of the Web Speech API represents a speech request. It contains the content the speech service should read and information about how to read it (e.g. language, pitch and volume.)

What is the purpose of the Speak () function?

speak() The speak() method of the SpeechSynthesis interface adds an utterance to the utterance queue; it will be spoken when any other utterances queued before it have been spoken.

How do I make Javascript speak?

var msg = new SpeechSynthesisUtterance(); msg. text = "Hello World"; window. speechSynthesis.


1 Answers

Your code doesn't work, but i just wrote an example that works the way you want. Open the fiddle to see it working

var utterance = new SpeechSynthesisUtterance();
var wordIndex = 0;
var global_words = [];
utterance.lang = 'en-UK';
utterance.rate = 1;


document.getElementById('playbtn').onclick = function(){
    var text    = document.getElementById('textarea').value;
    var words   = text.split(" ");
    global_words = words;
    // Draw the text in a div
    drawTextInPanel(words);
    spokenTextArray = words;
    utterance.text = text;
    speechSynthesis.speak(utterance);
};

utterance.onboundary = function(event){
    var e = document.getElementById('textarea');
    var word = getWordAt(e.value,event.charIndex);
    // Show Speaking word : x
    document.getElementById("word").innerHTML = word;
    //Increase index of span to highlight
    console.info(global_words[wordIndex]);

    try{
        document.getElementById("word_span_"+wordIndex).style.color = "blue";
    }catch(e){}

    wordIndex++;
};

utterance.onend = function(){
        document.getElementById("word").innerHTML = "";
    wordIndex = 0;
    document.getElementById("panel").innerHTML = "";
};

// Get the word of a string given the string and the index
function getWordAt(str, pos) {
    // Perform type conversions.
    str = String(str);
    pos = Number(pos) >>> 0;

    // Search for the word's beginning and end.
    var left = str.slice(0, pos + 1).search(/\S+$/),
        right = str.slice(pos).search(/\s/);

    // The last word in the string is a special case.
    if (right < 0) {
        return str.slice(left);
    }
    // Return the word, using the located bounds to extract it from the string.
    return str.slice(left, right + pos);
}

function drawTextInPanel(words_array){
console.log("Dibujado");
        var panel = document.getElementById("panel");
    for(var i = 0;i < words_array.length;i++){
        var html = '<span id="word_span_'+i+'">'+words_array[i]+'</span>&nbsp;';
        panel.innerHTML += html;
    }
}

Please play with the following fiddle :

Highlight spoken word SpeechSynthesis Javascript fiddle

It highlight the spoken word in div with blue, you can customize it with bold style, but the important is the idea.

Note: remember that the onboundary event is only triggered for the native (local) voice synthesis. Changing the voice as specified in the Google Examples (i.e Google UK English Male) for a google remote voice, will make your code fail as the SpeechSynthesis API seems to only play a sound generated by the google servers.

like image 131
Carlos Delgado Avatar answered Sep 20 '22 21:09

Carlos Delgado