【问题标题】:SpeechSynthesis API onend callback not workingSpeechSynthesis API onend 回调不起作用
【发布时间】: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 上。

标签: javascript google-chrome text-to-speech speech-synthesis google-text-to-speech


【解决方案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】:

          唯一对我有用的是避免localServicetrue 的声音。这些声音从未触发过onend,而其他声音(localService 为假)确实触发了onend

          【讨论】:

            【解决方案9】:

            此外,在 Chrome(但不是 Safari)上,如果您尝试说出空字符串,则永远不会调用回调。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2022-09-27
              • 2019-02-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-09-13
              • 2013-11-20
              相关资源
              最近更新 更多