在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 asym
playback.pcm "hw:0,0"
capture.pcm "hw:1,0"
}
ctl.!default {
type hw
card 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 = False
def signal_handler(sig, frame):
global running
print("正在退出...")
running = False
sys.exit(0)
# 注册信号处理函数
signal.signal(signal.SIGINT, signal_handler)
# 回调函数,执行唤醒后的操作
def on_wakeup():
print("\n系统已唤醒,等待命令...")
# 这里可以添加唤醒后的操作,如播放提示音、启动命令识别等
os.system("aplay -q wake_tone.wav") # 播放提示音(需准备此文件)
# 示例:唤醒后进入交互模式,可执行命令等
global is_wakeup
is_wakeup = True
# 设置唤醒超时
def reset_wakeup():
global is_wakeup
time.sleep(10) # 10秒后自动重置唤醒状态
if is_wakeup:
print("唤醒超时,重新进入监听模式...")
is_wakeup = False
threading.Thread(target=reset_wakeup, daemon=True).start()
def main():
# 初始化PyAudio
p = pyaudio.PyAudio()
# 打开音频流
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("开始监听唤醒词 '你好小智'...")
print("按Ctrl+C退出")
global running, is_wakeup
buffer = []
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强大的算力足以处理语音识别任务
这个方案适合用于智能家居控制中心、智能音箱、交互机器人等多种应用场景。
如需进一步帮助或具体某一部分的详细说明,请随时告知!