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++;
}
}
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.)
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.
var msg = new SpeechSynthesisUtterance(); msg. text = "Hello World"; window. speechSynthesis.
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> ';
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With