web vad实践

2,003 阅读3分钟

需求描述

pc浏览器实现语音控制交互

业务流程

graph TD
pc端调用麦克风获取语音媒体流 --> 获取语音blob文件上传给后端接口-->后端解析语音文件,返回指令-->根据指令进行浏览器交互

实现

MediaDevices.getUserMedia()

MediaDevices.getUserMedia()  会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D 转换器等等),也可能是其他轨道类型。

通过 MediaDevices.getUserMedia() 获取用户多媒体权限时,有以下三种情况:

  • HTTPS
  • localhost 域
  • 本地文件以file 形式打开时

其他情况下调用该API返回undefined

juejin.cn/post/699030… 修改chrome参数可以实现HTTP 环境下也能使用和调试该API。

const stream = await navigator.mediaDevices.getUserMedia({
      audio: true,
    })
//stream-本地麦克风的音频媒体流

vad-web

Voice Activity Detection (VAD)作用是从一段语音(纯净或带噪)信号中标识出语音片段与非语音片段。可选择余地并不多,最后决定使用@ricky0123/vad-web,可以在浏览器运行,说明文档如下www.vad.ricky0123.com/docs/browse…

难点在于如何在已有项目中正常运行,有很多需要注意的地方。

1.兼容问题
npm i @ricky0123/vad-web

安装到现有项目中使用,所以是通过npm方式安装。项目的webpack版本是4.37.0,安装到项目后引入会报错。 如果项目的webpack版本是5.X,不会有这个报错。

1683600459932.png 点击打开报错的js文件,发现是ev.data?.message的写法导致的,再结合报错提示,需要添加loader。

1683600715358.png 安装babel,然后在webpack.config(或者vue.config)配置文件添加

npm i @babel/preset-env babel-core babel-loader@8.1 -D 
module.exports={
...
module: {
    rules: [
      /**
       * 定义打包规则:其中所需的插件有 babel-loader @babel/preset-env @babel/core
       */

      {
          test: /\.js$/,
          // exclude: /node_modules/,
          exclude: {
            and: [/node_modules/], // Exclude libraries in node_modules ...
            not: [
              // Except for a few of them that needs to be transpiled because they use modern syntax
              /@ricky0123/,
            ]
          },
          loader: 'babel-loader',
          options: {
              //  预设babel做怎样的兼容性处理
              presets: ['@babel/preset-env']
          }
      }
  ]
  }
}

重启项目,该报错消失,兼容问题解决。

2.wasm等文件处理

引入MicVAD,调用start,这里会发现报错

import { MicVAD } from "@ricky0123/vad-web"
const myvad = await MicVAD.new({
  onSpeechEnd: (audio) => {
    // do something with `audio` (Float32Array of audio samples at sample rate 16000)...
  },
})
myvad.start()

1683601939510.png 查看官方文档,需要使用webpack插件复制文件到dist打包目录下。

You will also need to

  1. serve the silero_vad.onnx file that comes distributed with @ricky0123/vad-web
  2. serve the vad.worklet.bundle.min.js file that comes distributed with @ricky0123/vad-web
  3. serve the wasm files that come distributed with the package onnxruntime-web

1683602111864.png 官网的路径需要根据实际项目去修改,需要保证复制的文件和项目打包的js文件在同一个文件夹下,否则还会报错。

copy-webpack-plugin在dev本地调试的环境不起作用,参考webpack官方文档,需要使用write-file-webpack-plugin插件

npm i copy-webpack-plugin write-file-webpack-plugin -D

const CopyPlugin = require("copy-webpack-plugin")
module.exports={
  plugins:[
     new WriteFilePlugin(),
     new CopyPlugin({
      patterns: [{
          from: "node_modules/@ricky0123/vad-web/dist/vad.worklet.bundle.min.js",
          to: "static/js/[name].[ext]",
        },
        {
          from: "node_modules/@ricky0123/vad-web/dist/*.onnx",
          to: "static/js/[name].[ext]",
        },
        {
          from: "node_modules/onnxruntime-web/dist/*.wasm",
          to: "static/js/[name].[ext]"
        },
      ],
  ]
}

到这里就可以正常使用了