需求描述
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,不会有这个报错。
点击打开报错的js文件,发现是
ev.data?.message的写法导致的,再结合报错提示,需要添加loader。
安装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()
查看官方文档,需要使用webpack插件复制文件到dist打包目录下。
You will also need to
- serve the
silero_vad.onnxfile that comes distributed with@ricky0123/vad-web - serve the
vad.worklet.bundle.min.jsfile that comes distributed with@ricky0123/vad-web - serve the wasm files that come distributed with the package
onnxruntime-web
官网的路径需要根据实际项目去修改,需要保证复制的文件和项目打包的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]"
},
],
]
}
到这里就可以正常使用了