科大讯飞在线语音播报vue模块

本文详细描述了如何通过JavaScript利用WebSocket与TTS服务进行安全通信,涉及加密技术和音频数据处理过程。
摘要由CSDN通过智能技术生成

<template>

  <div class="home">

      <!-- <button @click="getWebsocketUrl">获取WSS地址</button> -->

      <!-- <button @click="connectWebSocket">连接WSS地址</button>

       <button @click="audioPlay">播放</button> -->

  </div>

</template>

<script>

// @ is an alias to /src

import CryptoJS from 'crypto-js'

import {Base64} from "js-base64";


 

export default {

name: 'Home',

data() {

  return {

    webSocketUrl: '',

    ttsWS: null,

    audioContent: null,

    audioDataOffset: 0,

    transWorker: null,

    audioData: [],

   

  }

},

created(){

  this.getWebsocketUrl()

},

methods: {

  getWebsocketUrl() {

    return new Promise((resolve, reject) => {

      var apiKey = "自己的key"

      var apiSecret = "自己的api"

      var url = 'wss://tts-api.xfyun.cn/v2/tts'

      var host = location.host

      var date = new Date().toGMTString()

      var algorithm = 'hmac-sha256'

      var headers = 'host date request-line'

      var signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v2/tts HTTP/1.1`

      var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret)

      var signature = CryptoJS.enc.Base64.stringify(signatureSha)

      var authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`

      var authorization = btoa(authorizationOrigin)

      url = `${url}?authorization=${authorization}&date=${date}&host=${host}`

      this.$data.webSocketUrl = url

      resolve(url)

    })

  },

  // 建立连接

  connectWebSocket(value) {

    // alert(value)

    this.$data.ttsWS=null

    this.$data.audioContent=null

    this.$data.audioDataOffset=0

    this.$data.transWorker=null

    this.$data.audioData=[]

    this.$data.audioContext=null

    if ('WebSocket' in window) {

      this.$data.ttsWS = new WebSocket(this.$data.webSocketUrl)

    } else if ('MozWebSocket' in window) {

      this.$data.ttsWS = new MozWebSocket(this.$data.webSocketUrl)

    } else {

      alert('浏览器不支持WebSocket')

      return

    }

    this.$data.ttsWS.onopen = e => {

      this.webSocketSend(value)

      this.playTimeout = setTimeout(() => {

        this.audioPlay()

      }, 1000)

    }

    this.$data.ttsWS.onmessage = e => {

      this.result(e.data)

    }

    this.$data.ttsWS.onerror = e => {

      clearTimeout(this.playTimeout)

      alert('WebSocket报错,请f12查看详情')

      console.error(`详情查看:${encodeURI(url.replace('wss:', 'https:'))}`)

    }

    this.$data.ttsWS.onclose = e => {

      console.log(e)

    }

   

  },

  webSocketSend(value) {

    var params = {

      common: {

        app_id: "自己的id", // APPID

      },

      business: {

        aue: 'raw',

        auf: 'audio/L16;rate=16000',

        vcn: 'xiaoyan',

        speed: 50,

        pitch: 50,

        bgs: 0,

        tte: 'UTF8',

      },

      data: {

        status: 2,

        text: this.encodeText(value,'')

      },

     

    }    

    this.$data.ttsWS.send(JSON.stringify(params))  //向wedbsocket发送数据

  },

  encodeText(text, encoding) {

    switch (encoding) {

      case 'utf16le' : {

        let buf = new ArrayBuffer(text.length * 4)

        let bufView = new Uint16Array(buf)

        for (let i = 0, strlen = text.length; i < strlen; i++) {

          bufView[i] = text.charCodeAt(i)

        }

        return buf

      }

      case 'buffer2Base64': {

        let binary = ''

        let bytes = new Uint8Array(text)

        let len = bytes.byteLength

        for (let i = 0; i < len; i++) {

          binary += String.fromCharCode(bytes[i])

        }

        return window.btoa(binary)

      }

      case 'base64&utf16le' : {

        return this.encodeText(this.encodeText(text, 'utf16le'), 'buffer2Base64')

      }

      default : {

        return Base64.encode(text)

      }

    }

  },

  result(resultData) {

    // console.log(resultData,"resumePlayDurationresumePlayDurationresumePlayDuration")

    let jsonData = JSON.parse(resultData)

    // 合成失败

    if (jsonData.code !== 0) {

      alert(`合成失败: ${jsonData.code}:${jsonData.message}`)

      console.error(`${jsonData.code}:${jsonData.message}`)

      this.resetAudio()

      return

    }

    let output1 = this.transToAudioData(jsonData.data.audio)

    // console.log(output1)

      this.audioData.push(output1)


 

    if (jsonData.code === 0 && jsonData.data.status === 2) {

      this.ttsWS.close()

    }

  },

  // 播放

  audioPlay() {

    // alert("播放")

    let audioData=[]

    let res = this.audioData.slice(this.audioDataOffset)

      // console.log(audioData)

      res.forEach((item)=>{

        item.forEach((itemone)=>{

          audioData.push(itemone)

        })

      })

    this.audioDataOffset += audioData.length

      // console.log(audioData.length)

    let audioBuffer = this.audioContext.createBuffer(1, audioData.length, 22050)

    let nowBuffering = audioBuffer.getChannelData(0)

    if (audioBuffer.copyToChannel) {

      audioBuffer.copyToChannel(new Float32Array(audioData), 0, 0)

    } else {

      for (let i = 0; i < audioData.length; i++) {

        nowBuffering[i] = audioData[i]

      }

    }

      // let bufferSource = this.bufferSource = this.audioContext.createBufferSource()

      let bufferSource = this.audioContext.createBufferSource()

    bufferSource.buffer = audioBuffer

    bufferSource.connect(this.audioContext.destination)

    bufferSource.start()

    // bufferSource.onended = event => {

    //   if (this.audioDataOffset < this.audioData.length) {

    //     this.audioPlay()

    //   } else {

    //     // this.audioStop()

    //   }

    // }

  },

  transToAudioData: function (audioDataStr, fromRate = 16000, toRate = 22505) {

    let outputS16 = this.base64ToS16(audioDataStr)

    let output = this.transS16ToF32(outputS16)

    output = this.transSamplingRate(output, fromRate, toRate)

    output = Array.from(output)

    return output

  },

  base64ToS16: function (base64AudioData) {

    base64AudioData = atob(base64AudioData)

    const outputArray = new Uint8Array(base64AudioData.length)

    for (let i = 0; i < base64AudioData.length; ++i) {

      outputArray[i] = base64AudioData.charCodeAt(i)

    }

    return new Int16Array(new DataView(outputArray.buffer).buffer)

  },

  transS16ToF32: function (input) {

    var tmpData = []

    for (let i = 0; i < input.length; i++) {

      var d = input[i] < 0 ? input[i] / 0x8000 : input[i] / 0x7fff

      tmpData.push(d)

    }

    return new Float32Array(tmpData)

  },

  transSamplingRate: function (data, fromRate = 44100, toRate = 16000) {

    var fitCount = Math.round(data.length * (toRate / fromRate))

    var newData = new Float32Array(fitCount)

    var springFactor = (data.length - 1) / (fitCount - 1)

    newData[0] = data[0]

    for (let i = 1; i < fitCount - 1; i++) {

      var tmp = i * springFactor

      var before = Math.floor(tmp).toFixed()

      var after = Math.ceil(tmp).toFixed()

      var atPoint = tmp - before

      newData[i] = data[before] + (data[after] - data[before]) * atPoint

    }

    newData[fitCount - 1] = data[data.length - 1]

    return newData

  },

},

mounted() {

  let AudioContext = window.AudioContext || window.webkitAudioContext

  if (AudioContext) {

    console.log('Audio Context初始化')

    this.audioContext = new AudioContext()

    this.audioContext.resume()

    this.audioDataOffset = 0

  }

},

components: {}

}

</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值