likes
comments
collection
share

通过WebSocket的长连接实现语音搜索功能(整理中。。)

作者站长头像
站长
· 阅读数 45

如果发现 有问题 或者觉得 有遗漏 的地方,欢迎留言讨论

关于WebSocket的优缺点

这个网上文档太多了,自行查阅 推荐入口

准备

之前是准备用 STOMPJS 流文本定向消息协议开发,但涉及到语音转文字,emmm...

所以此功能的语音部分涉及到语音识别器,语音识别器语音转文字是调用第三方的 SpeechRecognizer,版权原因这里不讲第三方的,大家可以自己去集成第三方sdk;这里可以分享两个接入语音识别器踩到的几个坑,如下:

工程在 Chrome 浏览器打开,获取音频设备权限问题

Vue 工程在 Chrome 浏览器打开,无法获取音视频设备,控制台提示获取音频设备权限问题, 我们可以通过以下方式解决:

一、网页使用https方式访问

此操作需要依赖web服务提供者实现https的访问方式。(需要安全证书)

二、修改浏览器安全配置(最直接、简单)

  1. 浏览器地址栏输入: chrome://flags/#unsafely-treat-insecure-origin-as-secure
  2. 开启Insecure origins treated as secure

在输入栏内输入你需要访问音频设备的地址url,然后将右侧Disabled 改成 Enabled,浏览器会提示重启(Relaunch)

通过WebSocket的长连接实现语音搜索功能(整理中。。) 3. 浏览器会提示重启(Relaunch),Relaunch 即可

关于谷歌浏览器的禁止autoplay政策

autoplay: 这个属性是<video><audio>所属的,表示在用户进入页面的时候自动开始播放声音或者播放视频,但是,这个属性会在谷歌浏览器中失效,因为谷歌浏览器在用户体验和安全性方面做出自己的限制,默认阻止音视频的自动播放。

解决方法也很简单,修改下权限就可以了~

通过WebSocket的长连接实现语音搜索功能(整理中。。)

新版本里面不叫 Autoplay policy了,而是声音,它会检测页面是否有video或audio标签,如果有的话,就会直接在上图显示,选择允许,就可以实现和上面一样的效果。如果上面没有声音选项,你也可以点击上图的 网站设置,里面有所有的浏览器的主要权限设置。

点进去,找到声音选项,一样可以设定允许自动播放。

通过WebSocket的长连接实现语音搜索功能(整理中。。)

注意:这里的设定只能生效于当前的页面,无法生效所有页面。

以上就是语音识别器部分

接下来是封装的webSocket 接收语音指令部分,直接上代码

class Socket {
  /**
     * @description: 初始化实例属性,保存参数
     *
     */
  constructor (options) {
    this.url = options.url // 语音连接url
    this.callback = options.received // 返回函数
    this.name = options.name || 'default'
    this.ws = null
    this.status = null
    // 心跳定时器
    this.pingInterval = null
    // 心跳检测频率
    this.timeout = options.time
    this.isHeart = options.isHeart
    this.isReconnection = options.isReconnection
  }

  connect (data) {
    this.ws = new WebSocket(this.url)
    // 建立连接
    this.ws.onopen = (e) => {
      this.status = e.type
      console.log('success', e)
      if (this.isHeart) {
        // 心跳
        this.heartCheck()
      }
      // 给后台发送数据
      if (data !== undefined) {
        return this.ws.send(JSON.stringify({ type: data.type }))
      }
    }
    // 接受服务器返回的信息
    this.ws.onmessage = (e) => {
      if (typeof this.callback === 'function') {
        return this.callback(e.data)
      } else {
        console.log('参数的类型必须为函数')
      }
    }
    // 关闭连接
    this.ws.onclose = (e) => {
      console.log('onclose', e)
    }
    // 报错
    this.onerror = (e) => {
      console.log('onerror', e)
      this.closeSocket(e)
    }
  }

  sendMsg (data) {
    const msg = JSON.stringify(data)
    return this.ws.send(msg)
  }

  resetHeart () {
    clearInterval(this.pingInterval)
    return this
  }

  heartCheck () {
    this.pingInterval = setInterval(() => {
      if (this.ws.readyState === 1) {
        console.log('Im alive')
        this.ws.send(JSON.stringify({ type: 'ping' }))
      }
    }, this.timeout * 8)
  }

  closeSocket (e) {
    this.resetHeart()
    if (this.status !== 'close') {
      console.log('disconnect and reconnect', e)
      //   if (this.isReconnection) {
      // 重连
      this.connect()
    //   }
    } else {
      console.log('close manually', e)
    }
  }

  close () {
    this.status = 'close'
    this.resetHeart()
    console.log('998899')
    return this.ws.close()
  }
}
export default Socket

订阅

    window.ws = new Socket({
      url: `${this.socketUrl}${id}`,// url和参数
      name: '', 
      isHeart: true, // 是否心跳
      time: 60000,
      received: (data) => {
        if (typeof this.callbackMsg === 'function') {
          return this.callbackMsg(data)
        } else {
          console.log('参数的类型必须为函数')
        }
      }
    })
    // this.ws = ws
    const data = {
      type: 'init'
    }
    window.ws.connect(data)

这里的socket只是做接收指令,发送指令是通过接入的收音设备,发送语音流到数据中控