Owner 语音桌宠
这是一个 Python 语音桌宠运行程序。当前第一版先提供无 GUI 的真实实时语音循环:
小杰小杰 唤醒 -> 麦克风录音 -> VAD 切分 -> ASR 转文字 -> 携带本次进程内临时历史调用 LLM -> TTS 生成语音 -> 本机扬声器播放 -> 回到待机继续监听。
当前能力
owner_voice_pet run-live:真实常驻语音循环。owner_voice_pet run-live --once:只跑一轮,便于验收。.env直接读取配置,不要求导出 shell 环境变量。- 唤醒词检测使用本地
sherpa-onnxKWS 模型,不走云端 ASR。 OWNER_SPEECH_PROVIDER=cloud|local:选择云端语音模型或本地语音模型。- 默认云端语音模型:
mimo-v2.5-asr、mimo-v2.5-tts。 - 本地设备:
sounddevice读取麦克风,扬声器或afplay播放。 - 本地模型:
models/存放sherpa-onnxwake/VAD/STT 模型,目录不提交 Git。 - 临时上下文:同一次
run-live进程内携带最近 user/assistant 历史,退出即清空。
首次准备
python3.11 -m venv .venv
.venv/bin/python -m pip install --upgrade pip
.venv/bin/python -m pip install -e '.[speech]'
cp .env.example .env
然后编辑 .env,填写本地密钥和模型配置。当前默认示例:
OWNER_LLM_BASE_URL=https://token-plan-cn.xiaomimimo.com/v1
OWNER_LLM_API_KEY=
OWNER_LLM_MODEL=mimo-v2.5
OWNER_LLM_API_STYLE=chat_completions
OWNER_WAKE_PROVIDER=local_kws
OWNER_WAKE_KEYWORDS_FILE=
OWNER_WAKE_KWS_THRESHOLD=0.15
OWNER_WAKE_KWS_SCORE=1.0
OWNER_WAKE_ACK_TEXT=我在
OWNER_POST_PLAYBACK_DRAIN_MS=50
OWNER_VAD_PROVIDER=hybrid
OWNER_VAD_THRESHOLD=0.5
OWNER_VAD_MIN_DURATION_MS=250
OWNER_VAD_END_SILENCE_MS=350
OWNER_VAD_NO_SPEECH_TIMEOUT_MS=5000
OWNER_VAD_MAX_RECORDING_MS=12000
OWNER_SPEECH_PROVIDER=cloud
OWNER_ASR_MODEL=mimo-v2.5-asr
OWNER_TTS_MODEL=mimo-v2.5-tts
OWNER_TTS_VOICE=mimo_default
OWNER_WAKE_PROVIDER=local_kws 表示唤醒词“小杰小杰”由本地模型检测。唤醒命中后会先本地播报 OWNER_WAKE_ACK_TEXT=我在,再开始听取问题。OWNER_SPEECH_PROVIDER=cloud 只影响唤醒后的正式问题 ASR/TTS:它会把 VAD 切出来的用户问题片段发送到云端 ASR,不会上传连续麦克风流,也不会用云端判断唤醒。改成 local 时使用项目 models/ 下的本地语音模型路径。
本地模型
即使默认走云端 ASR/TTS,也必须准备本地唤醒模型;同一脚本会下载 wake、VAD、STT 模型,便于切换到 OWNER_SPEECH_PROVIDER=local:
python3.11 scripts/download_speech_models.py --dir models
.venv/bin/python -m owner_voice_pet model-check --models-dir models
models/ 已在 .gitignore 中,不会提交大模型文件。
本地唤醒关键词文件位于 models/wake/keywords.txt。默认 OWNER_WAKE_KWS_THRESHOLD=0.15 已偏向灵敏;如果真人唤醒仍不灵敏,可以继续降到 0.10,若误唤醒变多再回调到 0.20。
默认 OWNER_VAD_PROVIDER=hybrid 会同时使用本地 sherpa-onnx VAD 和能量阈值兜底,避免本地 VAD 对麦克风音量过保守导致 VAD_TIMEOUT_NO_SPEECH。如果唤醒后你已经停说但还长时间显示“录音中”,优先调小 OWNER_VAD_END_SILENCE_MS,例如 250;如果房间噪声较大,再略调高 OWNER_VAD_THRESHOLD,例如 0.6。
设备检查
.venv/bin/python -m owner_voice_pet device-check
输出里 ok=true 表示已检测到可用麦克风和扬声器。
运行
单轮验收:
.venv/bin/python -m owner_voice_pet run-live --once
常驻重复对话:
.venv/bin/python -m owner_voice_pet run-live
运行后终端会显示待机、唤醒命中、应答中、请说出问题、录音中、转写中、转写结果、思考中、播放中、恢复待机等状态。说“小杰小杰”,听到“我在”且看到“请说出问题”后再提问;听到回复后可以再次说“小杰小杰”继续下一轮。本次进程内会携带临时历史,程序退出后不保存。
验证
.venv/bin/python -m compileall src tests scripts
.venv/bin/python -m unittest discover -s tests
.venv/bin/python -m owner_voice_pet acceptance
.venv/bin/python -m owner_voice_pet validate-assets
.venv/bin/python -m owner_voice_pet security-check
.venv/bin/python -m owner_voice_pet model-check --models-dir models
.venv/bin/python -m owner_voice_pet device-check
openspec validate --all --strict
LLM smoke:
.venv/bin/python -m owner_voice_pet llm-smoke --no-stream --message '用一句中文回复:小杰在线。'
安全约束
- API key 只写入本地
.env,.env不提交 Git。 models/、.venv/和临时音频文件不提交 Git。- 默认不持久化麦克风原始音频。
- 云端 ASR 只接收 VAD 切分后的语音片段。
security-check会扫描已跟踪文本文件中的sk-...和tp-...形式密钥。