-
-
Save woollsta/2d146f13878a301b36d7 to your computer and use it in GitHub Desktop.
/** | |
* Chunkify | |
* Google Chrome Speech Synthesis Chunking Pattern | |
* Fixes inconsistencies with speaking long texts in speechUtterance objects | |
* Licensed under the MIT License | |
* | |
* Peter Woolley and Brett Zamir | |
*/ | |
var speechUtteranceChunker = function (utt, settings, callback) { | |
settings = settings || {}; | |
var newUtt; | |
var txt = (settings && settings.offset !== undefined ? utt.text.substring(settings.offset) : utt.text); | |
if (utt.voice && utt.voice.voiceURI === 'native') { // Not part of the spec | |
newUtt = utt; | |
newUtt.text = txt; | |
newUtt.addEventListener('end', function () { | |
if (speechUtteranceChunker.cancel) { | |
speechUtteranceChunker.cancel = false; | |
} | |
if (callback !== undefined) { | |
callback(); | |
} | |
}); | |
} | |
else { | |
var chunkLength = (settings && settings.chunkLength) || 160; | |
var pattRegex = new RegExp('^[\\s\\S]{' + Math.floor(chunkLength / 2) + ',' + chunkLength + '}[.!?,]{1}|^[\\s\\S]{1,' + chunkLength + '}$|^[\\s\\S]{1,' + chunkLength + '} '); | |
var chunkArr = txt.match(pattRegex); | |
if (chunkArr[0] === undefined || chunkArr[0].length <= 2) { | |
//call once all text has been spoken... | |
if (callback !== undefined) { | |
callback(); | |
} | |
return; | |
} | |
var chunk = chunkArr[0]; | |
newUtt = new SpeechSynthesisUtterance(chunk); | |
var x; | |
for (x in utt) { | |
if (utt.hasOwnProperty(x) && x !== 'text') { | |
newUtt[x] = utt[x]; | |
} | |
} | |
newUtt.addEventListener('end', function () { | |
if (speechUtteranceChunker.cancel) { | |
speechUtteranceChunker.cancel = false; | |
return; | |
} | |
settings.offset = settings.offset || 0; | |
settings.offset += chunk.length - 1; | |
speechUtteranceChunker(utt, settings, callback); | |
}); | |
} | |
if (settings.modifier) { | |
settings.modifier(newUtt); | |
} | |
console.log(newUtt); //IMPORTANT!! Do not remove: Logging the object out fixes some onend firing issues. | |
//placing the speak invocation inside a callback fixes ordering and onend issues. | |
setTimeout(function () { | |
speechSynthesis.speak(newUtt); | |
}, 0); | |
}; |
Thank, It's helpful for me
Thanks, nice helpful script but I found 2 issues (on chrome 56):
- It was reading "DOT" as the start of the second sentence.
- End event wasn't firing due to "...cannot read [0] of null.." error.
This has been fixed here: https://gist.github.com/hsed/ef4a2d17f76983588cb6d2a11d4566d6.
I modified it to use my selected voice which wasn't working by adding newUtt.voice = utt.voice;
after initializing the newUtt from the chunk.
However, this caused timing issues. I have pauses in between chunks. It sounds un-natural.
Hello author! I'm putting an argument based on my fresh experience with speechSynthesis. I'm trying to understand your code but most of the things are not giving sense to me. I want to use this code to make my following code speak the given text up to the end. Can you guide me on how to do this?
const read = () => {
const textArea = document.getElementById("textarea");
const btn = document.getElementById("btn");
const input = textArea.value;
const msg = new SpeechSynthesisUtterance(input);
window.speechSynthesis.speak(msg);
}
const cancel = () => {
window.speechSynthesis.cancel();
}
THANKS IN ADVANCE!
This works perfectly on mobile as well, but how can i have control over resume and cancel methods? like on click the content is reading but i want some additional functionality also. I have created some states and based on that it should read my content. Like, isArticle = "playing" || "paused" || "resumed" || "canceled". playing will speak. paused will pause and canceled with stop.
Question though: why does it read out "dot"?