在Firefox中当页面自动刷新时语音会被切断,但在Google Chrome中不会。

10

我遇到一个问题,在 Firefox 浏览器中,如果页面自动刷新,语音会被截断;但在 Google Chrome 中,即使页面自动刷新,语音也会说完。我该如何修复这个问题,让在 Firefox 中语音即使在页面自动刷新时也不会被截断?

msg = new SpeechSynthesisUtterance("please finish saying this entire sentence.");
window.speechSynthesis.speak(msg);

(function ($) {
  'use strict';
  if (window == window.top) {
    var body = $('body').empty();
    var myframe = $('<iframe>')
      .attr({ src: location.href })
      .css({ height: '95vh', width: '100%' })
      .appendTo(body)
      .on('load', function () {
        var interval;
        interval = 750; 
        setTimeout(function () {
          myframe.attr({ src: location.href });
        }, interval);
      });
  }
})(jQuery);

1
页面是如何自动刷新的?(例如通过HTML元标记?)还是您指按F5 / 点击刷新? - Frazer
@Frosty..(1)是否有可能制作一个基本的演示页面,展示整个问题的操作过程?也许我们可以修复这样的代码。(2)发布的代码不足以重新创建您的问题。您的自动刷新技术到底是什么?(是通过浏览器扩展程序?innerHTML 代码?JavaScript 代码?)如果我们知道了,或许就能想出一种解决方法。 - VC.One
@VC.One 我发布了刷新脚本。 - frosty
嗨,我在Firefox中能够做到最好的是这个:Web Speech demo(以及相关的source code)。如果它能满足您的需求,那么请与我联系,让它也适用于您的网站/内容。 - VC.One
我之所以问“是否可能制作一个基本的演示页面展示整个问题?”是为了弄清楚(看到)为什么您需要每750毫秒刷新一次。例如,如果是因为某些体育赛事分数而更新。在这种情况下,最好更新包含“得分”文本的div本身(而不是刷新整个页面)。 - VC.One
4个回答

3
我遇到了一个问题,即在Firefox中,如果页面自动刷新,则语音会被截断,但在谷歌浏览器中,即使页面自动刷新,语音也会说完。对于Firefox的描述行为是一个合理的预期实现。
浏览Firefox和Chromium的源代码speechSynthesis.speak()的实现基于与本地语音服务器的套接字连接。在*nix上,该服务器通常为speech-dispatcherspeechd(speech-dispatcher)。请参见如何以编程方式发送Unix套接字命令到由浏览器自动产生的系统服务器或将JavaScript转换为Chromium的C ++源代码?以了解在Chromium中尝试实现SSML解析的描述。
最终决定使用JavaScript编写自己的代码,以满足该要求,根据W3C规范SpeechSynthesisSSMLParser,在SE网站上提问、提交问题和错误,并在W3C邮件列表上发布,但没有证据表明SSML解析将作为Web Speech API的一部分包含在内。
一旦建立了连接,就会为调用.speak()创建一个队列。即使连接关闭,任务管理器仍可能显示由服务注册的活动进程。
在Chromium/Chrome中的该过程并非没有缺陷,最接近描述该问题的已提交问题是:

.volume属性问题

最令人震惊的问题是Chromium / Chrome的webkitSpeechRecognition实现将用户的音频记录下来并将该音频数据发布到远程服务,然后将文本返回给浏览器 - 而不明确地通知用户正在进行这项操作,标记为WONT FIX

Github上的相关W3C语音API问题


总之,我们不会将Firefox的行为描述为“问题”,但Chrome的行为可能存在“问题”。
深入研究浏览器中W3C Web Speech API的实现并非易事,原因有很多。其中包括商业TTS/SST服务和专有的闭源语音合成和语音识别在“智能手机”上的可用选项或明显关注点,而不是修复现代浏览器中W3C Web Speech API的各种问题。
speechd(语音分派程序)的维护者在服务器端(本地speech-dispatcher套接字)方面非常有帮助。
不能代表Firefox的维护者。估计如果与从重新加载的窗口中的.speak()继续执行音频输出的功能请求相关的漏洞与最近浏览器实施的自动播放策略一致,则不太可能。尽管您仍然可以提交Firefox错误报告,询问是否期望在当前窗口重新加载期间继续进行音频输出(来自任何API或接口),以及是否有任何偏好或策略可以设置以覆盖所述行为,如@zip的回答所建议的那样,并从实施者那里获得答案。
有个人和组织编写自由开源软件代码,活跃在相关领域并愿意帮助 SST/TTS 开发,其中许多人都活跃在 GitHub 上,这是另一个询问如何在 Firefox 浏览器中实现特定目标的选项。
除了向实现者请求功能请求之外,您还可以阅读源代码并尝试创建一个或多个解决方法。替代方案包括使用 meSpeak.js,但那仍然不一定解决 Firefox 在 window 重新加载期间有意阻止音频输出的问题。

谢谢您解释为什么它不起作用,但是您有解决方案使其工作吗? - frosty

0

编辑:请参考下面使用 Promises 更优雅的解决方案!


以下代码片段是解决Firefox浏览器不一致性的方法,通过在间隔中检查synth.speaking并仅在其为false时触发重新加载,可以防止合成语音过早地中断: < p > (它在SO片段中无法正常工作,我认为它不喜欢iFrames中的iFrames或其他任何东西,只需将代码复制粘贴到文件中,并使用Firefox打开即可!)

<p>I'm in the body, but will be in an iFrame</p>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
 var synth = window.speechSynthesis;
 msg = new SpeechSynthesisUtterance("please finish saying this entire sentence.");
 synth.speak(msg);
 
 (function ($) {
  'use strict';
  if (window == window.top) {
   var body = $('body').empty();
   var myframe = $('<iframe>')
    .attr({ src: location.href })
    .css({ height: '95vh', width: '100%' })
    .appendTo(body)
    .on('load', function () {
     var interval;
     interval = setInterval(function () {
      if (!synth.speaking) {
       myframe.attr({ src: location.href });
       clearInterval(interval);
      }
     }, 750);
    });
  }
 })(jQuery);
</script>

一个更为详细的解决方案是完全不使用任何setTimeout()setInterval(),而是使用Promise。这样,页面将在消息合成完成后简单地重新加载,无论它有多长或多短。这也可以防止初始页面加载时出现“双重”/重叠语音。不确定这是否对您的情况有所帮助,但是这就是解决方案:

<button id="toggleSpeech">Stop Speaking!</button>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
 if (window == window.top) {
  window.speech = {
   say: function(msg) {
    return new Promise(function(resolve, reject) {
     if (!SpeechSynthesisUtterance) {
      reject('Web Speech API is not supported');
     }
     
     var utterance = new SpeechSynthesisUtterance(msg);
     
     utterance.addEventListener('end', function() {
      resolve();
     });
     
     utterance.addEventListener('error', function(event) {
      reject('An error has occurred while speaking: ' + event.error);
     });
     
     window.speechSynthesis.speak(utterance);
    });
   },
   speak: true,
  };
 }
 
 
 (function($) {
  'use strict';

  if (window == window.top) {
   var body = $('body').empty();
   var myframe = $('<iframe>')
    .attr({ src: location.href })
    .css({ height: '95vh', width: '100%' })
    .appendTo(body)
    .on('load', function () {
     var $iframe = $(this).contents();

     $iframe.find('#toggleSpeech').on('click', function(e) {
      console.log('speaking will stop when the last sentence is done...');
      window.speech.speak = !window.speech.speak;
     });
     
     window.speech.say('please finish saying this entire sentence.')
      .then(function() {
       if ( window.speech.speak ) {
        console.log('speaking done, reloading iframe!');
        myframe.attr({ src: location.href });
       }
      });
    });
  }
 })(jQuery);
</script>

注意:自Chrome 70版本以来,不再允许立即调用window.speechSynthesis.speak(new SpeechSynthesisUtterance(msg)),否则会出现错误speechSynthesis.speak() without user activation is no longer allowed...,更多详情请参见此处。因此,在Chrome中技术上用户必须激活脚本才能使其正常工作!


0
不确定为什么会有行为上的差异... guest271314 在他的回答中可能有所指。但是,你可以通过拦截重载事件并等待话语完成来防止 FF 停止 tts:onbeforeunload 处理程序。
msg = new SpeechSynthesisUtterance("say something");
window.speechSynthesis.speak(msg);
window.onbeforeunload = function(e) {
  if(window.speechSynthesis.speaking){
    event.preventDefault();
    msg.addEventListener('end', function(event) {
      //logic to continue unload here
    });
  }
};

-2

Firefox:

首先,在浏览器地址栏中输入并搜索“about:config”。这将带您到另一个页面,其中会弹出一个提示框询问是否要冒任何风险,您需要接受。从列表中查找名为“accessibility.blockautorefresh”的首选项,然后右键单击它。屏幕上会出现一些选项列表,请选择“切换”选项,然后将其设置为True而不是False。此更改将阻止Firefox浏览器上的自动刷新。请记住,此选项是可逆的!


7
这与Frosty的问题无关,他的问题是为什么不同的浏览器在特定情况下的行为不同。你正在针对另一个问题给出浏览器使用建议。请确保你实际上回答了原始问题。谢谢。 - Marcus Müller
你好 Marcus,我像你要求的那样给出了解决 Firefox 问题的方案,你看是否可行? - zip
@zip 你说_"这将阻止Firefox的自动刷新"_,但提问者并不想阻止它。他希望当前的音频继续播放(没有中断或停止),即使进行一些自动刷新。 - VC.One

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接