浏览器自带api语音播报speechSynthesis.speak()无法自动播报问题分析及非完美解决方案

在这里插入图片描述

1 需求描述

最近遇到一个需求,就是前端页面要实时监听后端传过来的数据,同时当后端传过来这条数据时前端界面要语音播报这条数据。

2 分析与解决方案

这里主要说说语音播报的部分。本来觉得用浏览器自带的API来实现直接写一句话就ok了,但是没想到居然有一个bug。那就是这条语音有时候能播报,有时候就没有声音了?为什么呢,查了半天,是浏览器的安全限制的问题,需要用户交互才能播放声音,这个问题困扰了一两天,找到了如下两条解决方案:

  • 第一个就是用按钮点击,当我们播报声音时,第一次播报必须得是用户用交互动作操作才行,显然我这里不能让用户点击,因为它是后台自动播报的,嘿嘿,这可难不到我,写了个模拟按钮点击事件,就ok啦~
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>语音播报</title>
  </head>
  <body>
    <h3>点击下方按钮可以进行语音播报</h3>
    <hr />
    <button onclick="areSpeak('哈哈哈哈哈,这是声音~')">播放声音</button>&nbsp;&nbsp;<button onclick="beQuiet()">停止播放</button>
  </body>
  <script>
    //#region 语音播报封装
    const areSpeak = newMsg => {
      // 初次播报使用模拟按钮触发
      virtualClick(SpeakVoice)
      speakWithDelay(newMsg)
    }

    /**
     * 语音播报
     * @param msg 播报的信息
     */
    const SpeakVoice = (msg = '') => {
      const speech = new SpeechSynthesisUtterance(msg)
      // 设置兼容中文
      const voices = window.speechSynthesis.getVoices()
      speech.voice = voices.filter(function (voice) {
        return voice.localService == true && voice.lang == 'zh-CN'
      })[0]
      window.speechSynthesis.speak(speech)
    }

    /**
     * 语音播报 带延迟 异步
     * 搭配async await
     * @param msg 播报的信息
     */
    const speakWithDelay = (utterance, delay = 1000) => {
      return new Promise(resolve => {
        const speech = new SpeechSynthesisUtterance(utterance)
        // 设置兼容中文
        let voices = window.speechSynthesis.getVoices()
        speech.voice = voices.filter(function (voice) {
          return voice.localService == true && voice.lang == 'zh-CN'
        })[0]
        speech.onend = () => {
          setTimeout(resolve, delay)
        }
        window.speechSynthesis.speak(speech)
      })
    }

    /**
     * 模拟按钮点击
     * @param callback
     */
    const virtualClick = callback => {
      let button = document.createElement('button')
      button.textContent = '点击我'

      // 添加点击事件处理程序
      button.addEventListener('click', function () {
        console.log('按钮被点击了')
        callback && callback()
      })

      // 模拟用户点击事件
      let event = new MouseEvent('click', {
        view: window,
        bubbles: true,
        cancelable: true
      })
      button.dispatchEvent(event)
    }

    const beQuiet = () => {
      console.log('停止')
      window.speechSynthesis.cancel()
      SpeakVoice('')
    }
    //#endregion
  </script>
</html>

  • 第二种解决方案就是用其他第三方的库,不过基于浏览器的安全限制,可能也会存在无法在后台自动播放的情况,所以这里还是没有采用其他第三方的库。

3 参考链接

官方文档:

https://developer.mozilla.org/zh-CN/docs/Web/API/SpeechSynthesis

其他小伙伴的博客:

https://blog.csdn.net/pridas/article/details/119097189

https://blog.csdn.net/qq_47247479/article/details/126933326

4 源码地址

https://github.com/JACK-ZHANG-coming/frontEnd-all-knowledge/tree/master/examples/funnyDemo/a05%E8%AF%AD%E9%9F%B3%E6%92%AD%E6%8A%A5%E5%8A%9F%E8%83%BD

如果屏幕前的小伙伴有什么好的解决方案也可以分享一下哦

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
1. 实现自动播报语音 在 HTML 中,可以使用 `SpeechSynthesis` API 来实现自动播放语音。这个 API 提供了一些方法和事件,可以控制语音的播放和暂停。 下面是一个简单的例子: ```javascript // 创建 SpeechSynthesisUtterance 对象 const msg = new SpeechSynthesisUtterance(); msg.text = 'Hello world!'; // 播放语音 window.speechSynthesis.speak(msg); ``` 在谷歌浏览器中,需要用户授权才能使用 `SpeechSynthesis` API。可以在用户点击页面时触发语音播放,然后请求授权。 ```javascript document.addEventListener('click', () => { // 请求授权 window.speechSynthesis.requestPermission().then(() => { // 创建 SpeechSynthesisUtterance 对象 const msg = new SpeechSynthesisUtterance(); msg.text = 'Hello world!'; // 播放语音 window.speechSynthesis.speak(msg); }); }); ``` 2. 解决 Chrome 浏览器自动播放音频问题 在 Chrome 浏览器中,自动播放音频是被禁止的,需要用户手动操作才能播放。为了解决这个问题,可以在用户的交互事件中触发音频的播放。 在 Vue 中,可以在 `mounted` 生命周期中监听 `click` 事件,然后触发音频播放。 ```vue <template> <div> <button @click="playAudio">Play Audio</button> </div> </template> <script> export default { mounted() { // 监听点击事件 document.addEventListener('click', this.playAudio); }, beforeDestroy() { // 移除监听事件 document.removeEventListener('click', this.playAudio); }, methods: { playAudio() { // 创建音频对象 const audio = new Audio('/path/to/audio.mp3'); audio.play(); }, }, }; </script> ``` 3. 将 MP3 语音打包到线上 可以使用 Webpack 的 `file-loader` 来打包 MP3 文件。 首先,需要在 Vue 项目中安装 `file-loader`: ```bash npm install file-loader --save-dev ``` 然后,在 Webpack 配置文件中添加 loader: ```javascript module.exports = { module: { rules: [ { test: /\.(mp3)$/, use: [ { loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'audio/', }, }, ], }, ], }, }; ``` 这个配置表示,当 Webpack 遇到 `.mp3` 文件时,会使用 `file-loader` 加载文件,并将文件打包到 `audio/` 目录下。 在 Vue 组件中使用打包后的 MP3 文件: ```vue <template> <div> <button @click="playAudio">Play Audio</button> </div> </template> <script> export default { methods: { playAudio() { // 创建音频对象 const audio = new Audio('/audio/audio.mp3'); audio.play(); }, }, }; </script> ```
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值