SpeechSynthesis API onend 回调不起作用
Posted
技术标签:
【中文标题】SpeechSynthesis API onend 回调不起作用【英文标题】:SpeechSynthesis API onend callback not working 【发布时间】:2014-06-22 10:25:57 【问题描述】:我在 Google Chrome v34.0.1847.131 上使用 Speech Synthesis API。该 API 从 v33 开始在 Chrome 中实现。
文本转语音在大多数情况下都有效,除非将回调分配给onend
。比如下面的代码:
var message = window.SpeechSynthesisUtterance("Hello world!");
message.onend = function(event)
console.log('Finished in ' + event.elapsedTime + ' seconds.');
;
window.speechSynthesis.speak(message);
有时会调用onend
,有时不会调用它。时机似乎完全关闭了。当它被调用时,打印出来的elapsedTime
总是像1399237888
这样的纪元时间。
【问题讨论】:
仅仅因为规范是在 w3 中编写的......并不意味着它们在所有浏览器中都可以正常工作或工作,特别是如果它们是新的和实验性的,如语音合成......并不是说这种能力是某种形式技术突破,但它是第一次被带到浏览器。 感谢您的检查。看到其他人遇到这个问题是令人鼓舞的。我想这可能只是一个半生不熟的实现,所以这个问题可能没有答案。 检查一下...出于某种奇怪的原因,如果您注销话语对象message
,那么它可以正常工作。 :D jsfiddle.net/QYw6b
事实上我认为问题是在声明消息对象后立即调用 speak 函数是问题..如果你这样做` setTimeout(function()speechSynthesis.speak(u);, 100);` 它可以工作......或者攻击说话功能来点击事件它也可以正常工作。
我仍然在适用于 Windows 的 chrome v46 上看到这个。我不记得它发生在 Chrome for android 上。
【参考方案1】:
根据this comment Kevin Hakanson 在the answer 中提到的错误,这可能是垃圾收集的问题。在调用 speak
seems to do the trick 之前将话语存储在变量中:
window.utterances = [];
var utterance = new SpeechSynthesisUtterance( 'hello' );
utterances.push( utterance );
speechSynthesis.speak( utterance );
【讨论】:
谢谢!一旦我改变了我的话语变量的范围,我就不再有问题了。我同意可能存在与浏览器内部 GC 相关的错误。 成功了!为了让像我这样的初学者清楚,使SpeechSynthesisUtterance
变量的范围更广,例如全局,就行了。
推送是干什么的?什么是话语?
utterances
是在第一行创建的数组。 push
在数组末尾添加一项:developer.mozilla.org/en-US/docs/Web/javascript/Reference/…
好人!仅将当前话语存储在全局 window
上,并在所有讲话完成后将其删除 — 非常适合我!【参考方案2】:
虽然这是我发现它的工作方式,但我不确定这是否是正确的行为......
先不要马上调用speak函数,使用回调。
第二,要获得时间,请使用timeStamp
而不是elapsedTime
。您也可以使用performance.now()
。
var btn = document.getElementById('btn');
speechSynthesis.cancel()
var u = new SpeechSynthesisUtterance();
u.text = "This text was changed from the original demo.";
var t;
u.onstart = function (event)
t = event.timeStamp;
console.log(t);
;
u.onend = function (event)
t = event.timeStamp - t;
console.log(event.timeStamp);
console.log((t / 1000) + " seconds");
;
btn.onclick = function () speechSynthesis.speak(u);;
演示:http://jsfiddle.net/QYw6b/2/
时间过去了,这两个事件肯定会触发。
【讨论】:
虽然在这个例子中它确实有效,但只要你使用非英语语音,它就会停止触发 onend 事件。【参考方案3】:您可以像我为 Speakerbot (http://www.speakerbot.de/) 那样使用 EventListener 来开始和结束。
说话时我的脸会变。
newUtt = new SpeechSynthesisUtterance();
newUtt.addEventListener('start', function ()
console.log('started');
)
newUtt.addEventListener('end', function ()
console.log('stopped');
)
【讨论】:
【参考方案4】:我发现这里建议的两种解决方案都不适用于an app I just wrote。我能想出的唯一解决方案是(有点)忙于等待:
function speak( text, onend )
window.speechSynthesis.cancel();
var ssu = new SpeechSynthesisUtterance( text );
window.speechSynthesis.speak( ssu );
function _wait()
if ( ! window.speechSynthesis.speaking )
onend();
return;
window.setTimeout( _wait, 200 );
_wait();
你可以在this codepen找到一个完整的例子
【讨论】:
我喜欢你通过调用cancel()
来启动函数的方式,这解决了我的问题。虽然对我来说speechSynthesis.speaking
确实比它应该的要长得多,所以忙碌的等待对我没有用。【参考方案5】:
这看起来类似于 2015 年 7 月 12 日报告的 Chromium 错误。
问题509488:Web Speech API:SpeechSynthesisUtterance 对象的“结束”事件有时未调度
【讨论】:
【参考方案6】:在说话似乎有效之前打印话语...... 如果我删除控制台,就会出现这个问题,不知道为什么
console.log("utterance", utterThis);
synth.speak(utterThis);
【讨论】:
【参考方案7】:我还发现使这项工作可靠的唯一方法是使用 .cance。我使用 17 秒超时。我所有的录音都不到 20 秒,所以这对我有用。
utterance.onstart = function (event)
setTimeout(function()window.speechSynthesis.cancel();,17000);
;
在我尝试每 8-10 条消息时遇到此问题之前。一旦我添加了 .cancel ,它似乎总是有效的。调用时我也会调用 set timeout。
setTimeout(function()window.speechSynthesis.speak(utterance);,100);
【讨论】:
【参考方案8】:唯一对我有用的是避免localService
是true
的声音。这些声音从未触发过onend
,而其他声音(localService 为假)确实触发了onend
。
【讨论】:
【参考方案9】:此外,在 Chrome(但不是 Safari)上,如果您尝试说出空字符串,则永远不会调用回调。
【讨论】:
以上是关于SpeechSynthesis API onend 回调不起作用的主要内容,如果未能解决你的问题,请参考以下文章