And*_*kin 39 javascript google-chrome speech-synthesis
尝试在Chrome 33中使用语音合成API时遇到问题.它与较短的文本完美配合,但如果我尝试更长的文本,它就会停在中间.在它停止一次后,语音合成在Chrome中的任何位置都不起作用,直到浏览器重新启动.
示例代码(http://jsfiddle.net/Mdm47/1/):
function speak(text) {
var msg = new SpeechSynthesisUtterance();
var voices = speechSynthesis.getVoices();
msg.voice = voices[10];
msg.voiceURI = 'native';
msg.volume = 1;
msg.rate = 1;
msg.pitch = 2;
msg.text = text;
msg.lang = 'en-US';
speechSynthesis.speak(msg);
}
speak('Short text');
speak('Collaboratively administrate empowered markets via plug-and-play networks. Dynamically procrastinate B2C users after installed base benefits. Dramatically visualize customer directed convergence without revolutionary ROI. Efficiently unleash cross-media information without cross-media value. Quickly maximize timely deliverables for real-time schemas. Dramatically maintain clicks-and-mortar solutions without functional solutions.');
speak('Another short text');
Run Code Online (Sandbox Code Playgroud)
它在第二个文本的中间停止说话,之后我就无法说出任何其他页面.
它是浏览器错误还是某种安全限制?
Pet*_*ley 53
我已经有一段时间使用谷歌Chrome语音合成这个问题了.经过一番调查,我发现了以下内容:
speechSynthesis.cancel();为了回应这些问题,我编写了一个能够克服字符限制的函数,将文本分成较小的话语,然后一个接一个地播放.显然你会得到一些奇怪的声音,因为句子可能被分成两个单独的话语,每个话语之间有一个小的时间延迟,但是代码会尝试将这些点分成标点符号,以使声音中断不那么明显.
更新
我已经在https://gist.github.com/woollsta/2d146f13878a301b36d7#file-chunkify-js公开发布了这个解决方案.非常感谢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);
};
Run Code Online (Sandbox Code Playgroud)
如何使用它...
//create an utterance as you normally would...
var myLongText = "This is some long text, oh my goodness look how long I'm getting, wooooohooo!";
var utterance = new SpeechSynthesisUtterance(myLongText);
//modify it as you normally would
var voiceArr = speechSynthesis.getVoices();
utterance.voice = voiceArr[2];
//pass it into the chunking function to have it played out.
//you can set the max number of characters by changing the chunkLength property below.
//a callback function can also be added that will fire once the entire text has been spoken.
speechUtteranceChunker(utterance, {
chunkLength: 120
}, function () {
//some code to execute when done
console.log('done');
});
Run Code Online (Sandbox Code Playgroud)
希望人们觉得这很有用.
彼得的答案的问题是当你设置语音合成队列时它不起作用.该脚本将新的块放在队列的末尾,因此不按顺序排列.示例:https://jsfiddle.net/1gzkja90/
<script type='text/javascript' src='http://code.jquery.com/jquery-2.1.0.js'></script>
<script type='text/javascript'>
u = new SpeechSynthesisUtterance();
$(document).ready(function () {
$('.t').each(function () {
u = new SpeechSynthesisUtterance($(this).text());
speechUtteranceChunker(u, {
chunkLength: 120
}, function () {
console.log('end');
});
});
});
/**
* 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);
};
</script>
<p class="t">MLA format follows the author-page method of in-text citation. This means that the author's last name and the page number(s) from which the quotation or paraphrase is taken must appear in the text, and a complete reference should appear on your Works Cited page. The author's name may appear either in the sentence itself or in parentheses following the quotation or paraphrase, but the page number(s) should always appear in the parentheses, not in the text of your sentence.</p>
<p class="t">Joe waited for the train.</p>
<p class="t">The train was late.</p>
<p class="t">Mary and Samantha took the bus.</p>
Run Code Online (Sandbox Code Playgroud)
就我而言,答案是在将字符串添加到队列之前将其"chunk".见这里:http://jsfiddle.net/vqvyjzq4/
许多道具给彼得的想法和正则表达式(我还有待征服.)我确信javascript可以清理,这更像是一个概念证明.
<script type='text/javascript' src='http://code.jquery.com/jquery-2.1.0.js'></script>
<script type='text/javascript'>
var chunkLength = 120;
var pattRegex = new RegExp('^[\\s\\S]{' + Math.floor(chunkLength / 2) + ',' + chunkLength + '}[.!?,]{1}|^[\\s\\S]{1,' + chunkLength + '}$|^[\\s\\S]{1,' + chunkLength + '} ');
$(document).ready(function () {
var element = this;
var arr = [];
var txt = replaceBlank($(element).text());
while (txt.length > 0) {
arr.push(txt.match(pattRegex)[0]);
txt = txt.substring(arr[arr.length - 1].length);
}
$.each(arr, function () {
var u = new SpeechSynthesisUtterance(this.trim());
window.speechSynthesis.speak(u);
});
});
</script>
<p class="t">MLA format follows the author-page method of in-text citation. This means that the author's last name and the page number(s) from which the quotation or paraphrase is taken must appear in the text, and a complete reference should appear on your Works Cited page. The author's name may appear either in the sentence itself or in parentheses following the quotation or paraphrase, but the page number(s) should always appear in the parentheses, not in the text of your sentence.</p>
<p class="t">Joe waited for the train.</p>
<p class="t">The train was late.</p>
<p class="t">Mary and Samantha took the bus.</p>
Run Code Online (Sandbox Code Playgroud)
2017 年,这个 bug 仍然存在。作为屡获殊荣的 Chrome 扩展程序Read Aloud的开发者,我碰巧非常了解这个问题。好吧,开玩笑的获奖部分。
我使用的解决方法是一种相当复杂的分块算法,它尊重标点符号。对于拉丁语言,我将最大块大小设置为 36 个单词。如果您愿意,代码是开源的:https : //github.com/ken107/read-aloud/blob/315f1e1d5be6b28ba47fe0c309961025521de516/js/speech.js#L212
36 个字的限制在大多数情况下效果很好,保持在 15 秒以内。但也会有卡住的情况。为了从中恢复,我使用了 16 秒计时器。
这是我最终得到的结果,它只是将我的句子拆分为“。”
var voices = window.speechSynthesis.getVoices();
var sayit = function ()
{
var msg = new SpeechSynthesisUtterance();
msg.voice = voices[10]; // Note: some voices don't support altering params
msg.voiceURI = 'native';
msg.volume = 1; // 0 to 1
msg.rate = 1; // 0.1 to 10
msg.pitch = 2; //0 to 2
msg.lang = 'en-GB';
msg.onstart = function (event) {
console.log("started");
};
msg.onend = function(event) {
console.log('Finished in ' + event.elapsedTime + ' seconds.');
};
msg.onerror = function(event)
{
console.log('Errored ' + event);
}
msg.onpause = function (event)
{
console.log('paused ' + event);
}
msg.onboundary = function (event)
{
console.log('onboundary ' + event);
}
return msg;
}
var speekResponse = function (text)
{
speechSynthesis.cancel(); // if it errors, this clears out the error.
var sentences = text.split(".");
for (var i=0;i< sentences.length;i++)
{
var toSay = sayit();
toSay.text = sentences[i];
speechSynthesis.speak(toSay);
}
}
Run Code Online (Sandbox Code Playgroud)
一个简单有效的解决方案是定期恢复。
function resumeInfinity() {
window.speechSynthesis.resume();
timeoutResumeInfinity = setTimeout(resumeInfinity, 1000);
}
Run Code Online (Sandbox Code Playgroud)
您可以将其与onend和onstart事件相关联,因此仅在必要时调用简历。就像是:
var utterance = new SpeechSynthesisUtterance();
utterance.onstart = function(event) {
resumeInfinity();
};
utterance.onend = function(event) {
clearTimeout(timeoutResumeInfinity);
};
Run Code Online (Sandbox Code Playgroud)
我是偶然发现的!
希望有帮助!
我最终对文本进行了整理,并对处理各种惩罚,如句号,逗号等有了一些了解.例如,如果它是数字的一部分(即$ 10,000),你不想在逗号上打破文本. .
我已经测试了它,似乎可以处理任意大量的输入,它似乎不仅可以在桌面上工作,还可以在Android手机和iphone上工作.
在以下网址设置合成器的github页面:https://github.com/unk1911/speech
您可以在以下网址查看:http: //edeliverables.com/tts/
小智 5
我已经解决了这个问题,同时拥有一个计时器函数,该函数调用pause()和resume()函数并再次设置计时器。在onend事件中,我清除了计时器。
var myTimeout;
function myTimer() {
window.speechSynthesis.pause();
window.speechSynthesis.resume();
myTimeout = setTimeout(myTimer, 10000);
}
...
window.speechSynthesis.cancel();
myTimeout = setTimeout(myTimer, 10000);
var toSpeak = "some text";
var utt = new SpeechSynthesisUtterance(toSpeak);
...
utt.onend = function() { clearTimeout(myTimeout); }
window.speechSynthesis.speak(utt);
...
Run Code Online (Sandbox Code Playgroud)
这似乎运作良好。