uniapp,h5,讯飞语音平台链接后端WebSocket,实现语音转写

127 阅读1分钟

先去下载这个插件

npm i js-audio-recorder

js-audio-recorder 官网文档地址

<template>
  <view style="height: 600rpx; margin-top: 300rpx">
    <my-navBar backIconMode="dark"></my-navBar>
    <button @click="startRecording">开始录音</button>
    <button @click="stopRecording">停止录音</button>
    <p>识别结果: {{ recognitionResult }}</p>
  </view>
</template>

<script setup>
import Recorder from 'js-audio-recorder'
console.log('Recorder', Recorder)
let recorder = new Recorder({
  sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
  sampleRate: 16000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
  numChannels: 1, // 声道,支持 1 或 2, 默认是1
})
console.log('recorder', recorder)
const socketTask = ref(null)
const isConnected = ref(false)
const recognitionResult = ref('')
// 移除页面加载时连接WebSocket的逻辑
// onMounted(() => {
//   handleInitWebSocket()
// })

// 页面卸载时清理资源
onUnmounted(() => {
  if (socketTask.value) {
    socketTask.value.close()
  }
})
// 初始话WebSocket
const handleInitWebSocket = async () => {
  if (isConnected.value) {
    console.log('WebSocket已经连接')
    return
  }
  try {
    const agentToken =
      '你的token'
    socketTask.value = await uni.connectSocket({
      url: '你的wss链接' + '?agent-token=' + agentToken,
      header: {
        'agent-token': agentToken,
      },
      success: () => {
        console.log('WebSocket连接已建立')
      },
      fail: (err) => {
        console.log('WebSocket连接失败', err)
        isConnected.value = false
      },
      complete: () => {
        console.log('WebSocket连接完成')
      },
    })
    await new Promise((resolve, reject) => {
      socketTask.value.onOpen(() => {
        console.log('WebSocket连接已打开')
        isConnected.value = true
        resolve()
      })
      socketTask.value.onError((err) => {
        console.log('WebSocket错误:', err)
        isConnected.value = false
        reject(err)
      })
    })
    socketTask.value.onMessage((res) => {
      console.log('收到服务器内容:', JSON.parse(res.data).message)
      recognitionResult.value = JSON.parse(res.data).message
    })
    socketTask.value.onClose(() => {
      console.log('WebSocket已关闭')
      isConnected.value = false
    })
  } catch (error) {
    console.error('WebSocket初始化失败:', error)
    isConnected.value = false
    uni.showToast({
      title: '连接失败,请重试',
      icon: 'none',
    })
  }
}

const startRecording = async () => {
  await handleInitWebSocket()
  recorder.start()
}

const stopRecording = async () => {
  recorder.stop()
  const pcmArrayBuffer = recorder.getPCM().buffer
  // 定义切片大小,例如 1024 字节
  const chunkSize = 1024
  let offset = 0
  while (offset < pcmArrayBuffer.byteLength) {
    const end = Math.min(offset + chunkSize, pcmArrayBuffer.byteLength)
    const chunk = pcmArrayBuffer.slice(offset, end)
    // 假设 socket 是你的 WebSocket 实例
    // 发送音频二进制数据(ArrayBuffer)
    await new Promise((resolve, reject) => {
      socketTask.value.send({
        data: chunk,
        success: () => {
          console.log('音频 ArrayBuffer 发送成功', chunk)
          resolve()
        },
        fail: (err) => {
          console.error('音频 ArrayBuffer 发送失败', err)
          reject(err)
        },
      })
    })
    offset += chunkSize
  }

  // 发送结束标志
  setTimeout(async () => {
    const endObj = '{"end": true}'
    await new Promise((resolve, reject) => {
      socketTask.value.send({
        data: endObj,
        success: () => {
          console.log('结束标志发送成功', endObj)
          resolve()
        },
        fail: (err) => {
          console.error('结束标志发送失败', err)
          reject(err)
        },
      })
    })
  }, 500)
}
</script>

<style lang="scss" scoped></style>


20250528_113702.gif