整合Live2D数字人和VAD模型,实现自动唤醒及交互

前一段时间利用开源软件,整合Live2D数字人、Dify和Ollama部署了一个本地的2D数字人,具体参考:

北方的郎:2G显卡就能跑的数字人系统:Win10上Dify智能体+live2d数字人

添加图片注释,不超过 140 字(可选)

玩了一阵子,感觉还是有些遗憾就是不能自动语音唤醒,每次交互都要点击按钮才行。

于是就自己试了一下,一开始只用音量,但是对噪音太敏感。后来加入频域,过零点检测等,有提升不过还是不够好,后来找到VAD技术,发现效果不错,具体参考:

北方的郎:应用前端语音唤醒机制简单研究、测试:音量、VAD等

1 VAD前端控件简介

找了一个基于JavaScript的VAD开源项目:

https://github.com/ricky0123/vad

添加图片注释,不超过 140 字(可选)

项目说明如下:此软件包旨在提供一个准确、用户友好的声音活动检测器(VAD),可在浏览器中运行。通过使用此软件包,您可以提示用户授予麦克风权限,开始录制音频,将包含语音的音频片段发送到您的服务器进行处理,或者在用户说话时显示特定的动画或指示器。

调用说明:

Voice Activity Detection for Javascript

Voice Activity Detection for Javascript

运行它提供的Demo,发现效果不错,能很准确的区分噪音和语音。而且录制的语音很完整。运行Demo的步骤如下:

npm i@ricky0123/vad-react
git clone https://github.com/ricky0123/vad
cd ./vad/examples/react-bundler
npm run build && npm run start

添加图片注释,不超过 140 字(可选)

2 整合Live2D数字人前端及VAD控件

本人前端开发经验很少,所以一些方法可能不够优雅,请见谅。

VAD控件的调用,参考的是它自己提供的react例子:

vad/examples/react-bundler at master · ricky0123/vad

修改的代码是开源的Live2d数字人:

GitHub - wan-h/awesome-digital-human-live2d: Awesome Digital Human

步骤如下

1,修改web\package.json

加入

    "@ricky0123/vad-react": "^0.0.25",

添加图片注释,不超过 140 字(可选)

2,修改\web\app\lib\comm.ts

加入asrFromBase64的定义

	public async asrFromBase64(
	  base64str: string,
	  settings: { [key: string]: string } = {},
	  engine: string = "default",
	  format: string = "wav",
	  sampleRate: Number = 16000,
	  sampleWidth: Number = 2
	): Promise {
	  if (!base64str) {
		return "";
	  }

	  try {
		const response = await API.asr_infer_api(
		  base64str,
		  engine,
		  format,
		  sampleRate,
		  sampleWidth,
		  settings
		);
		return response.data;
	  } catch (error) {
		console.error(error);
		return "";
	  }
	}

3,修改\web\app\ui\home\chatbot.tsx

加入引用及函数定义

import { useMicVAD, utils } from "@ricky0123/vad-react";  // 引入VAD控件

let micRecorder: Recorder | null = null;
let isRecording: boolean = false;

function UserSpeaking() {
  return user is speaking
}

function UserNotSpeaking() {
  return user is not speaking
}

function arrayBufferToWavBlob(arrayBuffer) {
    // 将 ArrayBuffer 转换为 Blob,设置 MIME 类型为 audio/wav
    return new Blob([arrayBuffer], { type: 'audio/wav' });
}
 

修改function Chatbot,加入


    // VAD相关状态
	const [audioList, setAudioList] = useState([])
	const vad = useMicVAD({
		startOnLoad: true,
		onSpeechEnd: (audio) => {
			if (isProcessing) return;
			console.log("VAD SpeechEnd", "");
			const wavBuffer = utils.encodeWAV(audio, 1, 16000, 1, 16);
			const base64 = utils.arrayBufferToBase64(wavBuffer);
			const url = `data:audio/wav;base64,${base64}`
			setAudioList((old) => [url, ...old])
			setIsProcessing(true);
			Comm.getInstance().asrFromBase64(base64, settings).then(
				(res) => {
					console.log("asr: ", res);
					if (res) {
						chatWithAI(res);
					} else {
						setIsProcessing(false);
					}
				}
			).catch(
				(error) => {
					setIsProcessing(false);
				}
			)
		},
		})

如果为了方便调试,显示VAD获取的音频,可以在Return后的({micRecordAlert ?:null})位置后加入:


			
			{vad.listening && 
VAD is running
} {!vad.listening &&
VAD is NOT running
} {vad.userSpeaking && } {!vad.userSpeaking && }
    {audioList.map((audioURL) => { return (
  1. ) })}

4,其他

然后就可以执行npm run build进行编译了。

把编译后的VAD项目(
https://github.com/ricky0123/vad)的例子react-bundler下的dist目录:vad\examples\react-bundler\dist下的这几个文件

添加图片注释,不超过 140 字(可选)

拷贝到编译后的数字人的这两个目录下

web\.next\static\chunks\
web\.next\static\chunks\app\

这么做主要是我在把这几个文件的拷贝命令加入到next.config.mjs的时候,一直报错,所以干脆直接拷贝了。

然后执行npm run start就可以看到效果了

添加图片注释,不超过 140 字(可选)

还有就是调试的时候可以执行 npm run dev进行调试。

原文链接:,转发请注明来源!