在RK3588 Ubuntu主板上实现FunASR离线语音唤醒系统
RK3588是一款性能强大的SoC,搭配FunASR可以很好地实现离线语音唤醒功能。以下是完整的实施方案:
1. 硬件准备
音频输入设备选择
由于您的主板针脚图未显示专用音频接口,您需要添加以下硬件之一:
-
USB麦克风/USB声卡(推荐)
- 最简单的解决方案
- 即插即用,无需额外配置
- 推荐型号:USB全向麦克风或带麦克风的USB声卡
-
I2S麦克风模块
- 如INMP441或MSM261S4030H0
- 需要配置GPIO引脚以支持I2S功能
- 需要在设备树中添加I2S配置
-
WM8960等音频编解码器模块
- 提供麦克风输入和音频输出
- 通过I2C控制,需要相应驱动
2. 环境配置
安装依赖
# 更新系统
sudo apt update && sudo apt upgrade -y# 安装基本工具
sudo apt install -y build-essential git cmake python3-pip python3-dev# 安装音频相关库
sudo apt install -y alsa-utils pulseaudio portaudio19-dev# 安装科学计算和AI相关库
sudo apt install -y python3-numpy python3-scipy# 检查音频设备
arecord -l
配置ALSA音频
# 创建或编辑.asoundrc文件
nano ~/.asoundrc# 添加以下内容(假设USB麦克风是card 1)
pcm.!default {type asymplayback.pcm "hw:0,0"capture.pcm "hw:1,0"
}ctl.!default {type hwcard 0
}
3. 安装FunASR
FunASR是达摩院开源的语音识别工具箱,支持离线唤醒。
安装FunASR Python包
# 创建虚拟环境(推荐)
python3 -m pip install virtualenv
virtualenv funasr_env
source funasr_env/bin/activate# 安装FunASR
pip install -U funasr
pip install funasr-onnx # 如果想使用ONNX模型加速
下载唤醒模型
mkdir -p models
cd models# 下载唤醒模型(以"你好小智"为例)
wget https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/models/wekws_wenetspeech_xiaoyu.tar.gz
tar -xzf wekws_wenetspeech_xiaoyu.tar.gz
4. 实现离线唤醒程序
创建唤醒程序
# wakeup.py
import os
import time
import wave
import pyaudio
import funasr
import threading
import signal
import sys# 配置参数
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 16000
RECORD_SECONDS = 0.5 # 每次处理的音频长度
THRESHOLD = 0.6 # 唤醒阈值# 初始化FunASR唤醒模型
model_dir = "models/wekws_wenetspeech_xiaoyu"
wakeup_model = funasr.AutoModel(model=model_dir,model_type="wekws",device_id=0 # 使用CPU,设置为>=0使用GPU
)# 全局变量
running = True
is_wakeup = Falsedef signal_handler(sig, frame):global runningprint("正在退出...")running = Falsesys.exit(0)# 注册信号处理函数
signal.signal(signal.SIGINT, signal_handler)# 回调函数,执行唤醒后的操作
def on_wakeup():print("\n系统已唤醒,等待命令...")# 这里可以添加唤醒后的操作,如播放提示音、启动命令识别等os.system("aplay -q wake_tone.wav") # 播放提示音(需准备此文件)# 示例:唤醒后进入交互模式,可执行命令等global is_wakeupis_wakeup = True# 设置唤醒超时def reset_wakeup():global is_wakeuptime.sleep(10) # 10秒后自动重置唤醒状态if is_wakeup:print("唤醒超时,重新进入监听模式...")is_wakeup = Falsethreading.Thread(target=reset_wakeup, daemon=True).start()def main():# 初始化PyAudiop = pyaudio.PyAudio()# 打开音频流stream = p.open(format=FORMAT,channels=CHANNELS,rate=RATE,input=True,frames_per_buffer=CHUNK)print("开始监听唤醒词 '你好小智'...")print("按Ctrl+C退出")global running, is_wakeupbuffer = []while running:# 读取音频数据data = stream.read(CHUNK, exception_on_overflow=False)buffer.append(data)# 保持buffer大小为固定长度(约RECORD_SECONDS秒)if len(buffer) > int(RATE / CHUNK * RECORD_SECONDS):buffer.pop(0)# 非唤醒状态下检测唤醒词if not is_wakeup:# 每1秒处理一次(可调整为更频繁)if len(buffer) >= int(RATE / CHUNK * RECORD_SECONDS):# 将buffer中的数据保存为临时wav文件with wave.open("temp.wav", 'wb') as wf:wf.setnchannels(CHANNELS)wf.setsampwidth(p.get_sample_size(FORMAT))wf.setframerate(RATE)wf.writeframes(b''.join(buffer))# 使用FunASR检测唤醒词result = wakeup_model.generate("temp.wav")# 检查结果if "keyword" in result and result["keyword"] == "你好小智" and result["score"] > THRESHOLD:print(f"检测到唤醒词!得分: {result['score']:.2f}")on_wakeup()else:# 唤醒状态下的处理逻辑(可添加命令识别等)pass# 短暂休眠,降低CPU占用time.sleep(0.01)# 清理资源stream.stop_stream()stream.close()p.terminate()os.remove("temp.wav")if __name__ == "__main__":main()
制作启动服务
# 创建systemd服务文件
sudo nano /etc/systemd/system/voice-wakeup.service
添加以下内容:
[Unit]
Description=Voice Wakeup Service
After=network.target[Service]
ExecStart=/bin/bash -c 'source /home/your_username/funasr_env/bin/activate && python3 /home/your_username/wakeup.py'
WorkingDirectory=/home/your_username
StandardOutput=inherit
StandardError=inherit
Restart=always
User=your_username[Install]
WantedBy=multi-user.target
启用服务:
sudo systemctl daemon-reload
sudo systemctl enable voice-wakeup
sudo systemctl start voice-wakeup
5. 优化与扩展
性能优化
RK3588有NPU加速能力,可以利用它提高识别速度:
# 安装NPU加速库(需要根据具体RK3588开发板调整)
sudo apt install librga-dev# 尝试使用TNN或ONNX运行时优化模型推理
pip install funasr-onnx onnxruntime
添加命令识别功能
唤醒后可以添加命令识别功能:
# 在on_wakeup函数中添加命令识别
def on_wakeup():print("系统已唤醒,等待命令...")os.system("aplay wake_tone.wav")# 录制5秒钟的命令p_cmd = pyaudio.PyAudio()stream_cmd = p_cmd.open(format=FORMAT,channels=CHANNELS,rate=RATE,input=True,frames_per_buffer=CHUNK)print("请说出您的命令...")frames = []for i in range(0, int(RATE / CHUNK * 5)):data = stream_cmd.read(CHUNK)frames.append(data)# 保存命令音频with wave.open("command.wav", 'wb') as wf:wf.setnchannels(CHANNELS)wf.setsampwidth(p_cmd.get_sample_size(FORMAT))wf.setframerate(RATE)wf.writeframes(b''.join(frames))# 识别命令asr_model = funasr.AutoModel(model="models/speech_paraformer-large_asr_nat-zh-cn",model_type="paraformer",device_id=0)result = asr_model.generate("command.wav")command_text = result["text"]print(f"识别到命令: {command_text}")# 执行命令逻辑execute_command(command_text)
总结
基于RK3588的Ubuntu系统,使用FunASR实现离线语音唤醒是完全可行的。该方案具有以下优势:
- 完全离线: 无需联网,保护隐私
- 低延迟: 本地处理,响应速度快
- 可定制: 可以根据需要自定义唤醒词和后续行为
- 资源高效: RK3588强大的算力足以处理语音识别任务
这个方案适合用于智能家居控制中心、智能音箱、交互机器人等多种应用场景。
如需进一步帮助或具体某一部分的详细说明,请随时告知!