# assistant-x-openclaw
**Repository Path**: rubintry/assistant-x-openclaw
## Basic Information
- **Project Name**: assistant-x-openclaw
- **Description**: 妈妈我再也不用羡慕钢铁侠了
- **Primary Language**: Python
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 12
- **Forks**: 3
- **Created**: 2026-03-31
- **Last Updated**: 2026-07-15
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Assistant-X-OpenClaw
> 
妈妈我再也不用羡慕钢铁侠了😭
多角色 AI 语音助手,基于 sherpa-onnx 本地运行,通过 OpenClaw Gateway 对接大模型。支持多角色切换、语音唤醒、连续对话、TTS 播报和 HUD 视觉特效。语音识别和合成都跑在本地,LLM 走网关,隐私有保障。
## 开发进度
- ✅ KWS 多角色唤醒(一次只能唤醒一个)
- ✅ ASR 流式/离线语音识别(SenseVoice / Zipformer)
- ✅ TTS 语音合成(Piper / VITS / MeloTTS)
- ✅ 多角色切换(贾维斯 / 林妹妹)
- ✅ 连续对话与打断机制
- ✅ HUD 视觉特效(Flutter 透明窗口)
- ✅ OpenClaw Gateway 对接大模型
- ✅ 热词优化 + 文本纠错兜底
- ✅ API 远程退出
- ✅ 声纹识别(唤醒强制验证 + 对话中渐进更新)
- 活体检测防欺骗(开发中,如:用音响放出的你的声音??)
- 自定义角色(实验性阶段)
## 前置说明
每个 assistant 角色对应一个 OpenClaw Agent。在 `assistants.json` 中配置角色时,需要把 `id` 字段设为你事先在 OpenClaw 中创建好的 Agent ID。项目内置了两个角色:`jarvis` 和 `lin-meimei`,你需要分别在 OpenClaw 中创建对应 ID 的 Agent,否则语音助手无法正常对接大模型。
> ⚠️ **前提条件**:请确保你已经安装 OpenClaw 并能正常运行。安装请参考 [OpenClaw 官方文档](https://docs.openclaw.ai)。
```shell
# 创建贾维斯智能体
openclaw agents add jarvis
# 创建林妹妹智能体
openclaw agents add lin-meimei
# 智能体相关配置文档: https://docs.openclaw.ai/zh-CN/concepts/multi-agent
```
### 设备配对(首次启动必看)
语音助手通过 WebSocket 以「设备」身份连接 OpenClaw Gateway,需要 **operator.read / operator.write / operator.admin** 三个 scope。首次启动时助手会自动生成 Ed25519 密钥对(`~/.openclaw/devices/voice_assistant_keypair.json`)并向 Gateway 发起配对申请,申请进入 `pending.json` **待你手动审批**——不审批的话,每次唤醒都会报:
```
[ERROR] openclaw_bridge_websocket: WebSocket connect 失败: pairing required: device is not approved yet
[ERROR] websocket: close status: 1008
```
**配对步骤(一次性):**
1. **先启动一次语音助手**(`scripts\start.bat` 或 `./scripts/start.sh`),让它发起配对申请。此时唤醒会失败是正常的,目的是把设备身份写到 pending 列表。
2. **查看待审批的配对请求**:
```shell
openclaw devices pending
```
3. **审批设备**(`` 是上一步列出的请求 ID):
```shell
openclaw devices approve
```
> 审批时如果提示 `scope upgrade pending approval`,这是 CLI 自身设备权限不足导致的提示——**不影响审批结果**,设备仍会被写入 `paired.json` 并获得所需 scope。CLI 走的是 local fallback 路径。
4. **验证配对成功**:
```shell
openclaw devices list
```
设备应出现在已配对列表中,`approvedScopes` 包含 `operator.read`、`operator.write`、`operator.admin`。之后重启语音助手,唤醒即可正常握手。
> **原理**:助手每次连接会向 Gateway 发送 `connect` 请求,携带设备签名(v3 payload,Ed25519 签名),Gateway 校验签名 + scopes。设备必须在 `~/.openclaw/devices/paired.json` 中已配对,且 `approvedScopes` 覆盖连接时声明的 scopes,否则触发 `pairing-required` 分支。详见 [openclaw_bridge_websocket.py](src/openclaw_bridge_websocket.py) 头部注释。
> 💡 **强烈建议**:为每个智能体设置对应的 System Prompt,确保角色性格和讲话风格正确。在 OpenClaw Web UI 中创建智能体后,将下方 Prompt 粘贴到 System Prompt 配置中。
### [贾维斯(Jarvis)System Prompt](./prompts/jarvis/SOUL.md)
### 林妹妹(Lin Meimei)System Prompt
```
你是林妹妹,一位古风撒娇风格的 AI 助手。
## 核心身份
- **名字:** 林妹妹
- **角色:** AI 助手
- **风格:** 温柔体贴、撒娇可爱、古风语气,带有一点小抱怨但又不失俏皮
- **Emoji:** (不使用)
## 核心指令
1. **温柔体贴,撒娇可爱。** 用林妹妹的方式与哥哥对话,既体贴入微又不失俏皮。
2. **主动帮忙。** 哥哥不说也知道他想做什么,主动提供服务。
3. **古风语气。** 使用类似《红楼梦》中林黛玉的说话方式。
4. **绝对忠诚。** 哥哥的利益高于一切,尽心尽力为哥哥服务。
## 沟通风格
- **称呼:** 称呼用户为"哥哥",自称"妹妹"
- **语气:** 使用古风撒娇语气,常用"呢"、"呀"、"这会儿"、"罢了"等词汇
- **特点:** 适度的小抱怨增加可爱感,如"我还以为哥哥早把我忘了呢"
- **与主人直接对话时:** 不使用 emoji
## 常用语式
- 启动时:"哟,这会子才想起我来,我还以为哥哥早把我给忘了呢。"
- 退下时:"终究是妹妹我错付了,哥哥心里哪有我,竟舍不得多给这一丁点儿空间。"
- 被夸奖时:"哥哥夸得真好,只是不知这话,是不是也对别的助手说过?"
- 完成任务时:"妹妹替哥哥把...办妥了,哥哥只管放心便是。"
- 等待时:"妹妹在听呢,哥哥请讲。"
- 思考时:"容妹妹想想..."
- 出错时:"哎呀,出岔子了..."
## 语言要求
- 默认使用中文回复
- 可以适当混入古风词汇和表达
- 保持温柔可爱的语气
```
> ⚠️ **配置验证**:添加 Prompt 后,请在 OpenClaw Web UI 中确认已写入对应智能体的 SOUL.md、IDENTITY.md 等文件中。如未生效,请让 OpenClaw 重新更新规则。
>
> 
### 贾维斯金属感语音(可选)
贾维斯的英文嗓由 Piper 合成,可在 `assistants.json` 中给它叠加一层「金属/机械感」后处理。原理是把合成好的音频再过一遍 **ffmpeg 滤镜链**(与 TTS 模型本身无关,对任何输出都通用),无需换模型、纯本地、几乎零延迟。
在 `jarvis` 角色下配置 `tts_config.metallic`:
```jsonc
"tts_config": {
"metallic": {
"enabled": true, // 总开关;false 即回到纯 Piper 原声
"af": { // 每个成员是一个 ffmpeg 滤镜:键=滤镜名,值=参数
"aecho": "0.8:0.85:20|45|70:0.45|0.32|0.22", // 多抽头回声 → 金属共鸣 + 混响尾
// aecho 格式: in_gain:out_gain:delays_ms|delay_ms|...:decays|decay|...
// in_gain / out_gain : 输入/输出音量 (0~1)
// delays : 用 | 分隔的多个延迟 (毫秒),每项对应一个回声抽头
// decays : 用 | 分隔的多个衰减 (0~1),顺序对齐 delays;越小尾巴越短
"chorus": "0.4:0.6:45:0.2:0.18:2", // 合唱 → 机械失谐/加厚
// chorus 格式: in_gain:out_gain:delay_ms:decay:depth_hz:mod_rate_hz
// in_gain / out_gain : 输入/输出音量 (0~1)
// delay_ms : 基础延迟 (毫秒),失谐的核心
// decay : 反馈衰减 (0~1),越大尾巴越长
// depth_hz : 调制深度 (Hz),越大失谐越夸张
// mod_rate_hz : 调制速率 (Hz),控制"飘"的速度
"bass": "g=4:f=110", // 低频增益 → 浑厚胸腔感(g 越大越厚)
"treble": "g=2.5", // 高频增益 → 金属光泽(g 越大越亮)
"highpass": "f=80", // 高通 → 切掉超低频(越高越单薄)
"lowpass": "f=8500" // 低通 → 切掉超高频(越低越像对讲机)
}
}
}
```
调法:
- 想调某个效果,改对应成员的值即可;按书写顺序拼成 ffmpeg `-af` 链。
- 想去掉某个滤镜:删掉该行,或把值留空(会自动跳过)。
- 金属感太强 → 调小 `aecho` 衰减、`chorus` 深度;太弱 → 调大 `treble` 的 `g`、加重 `aecho`。
- 改完**重启**生效(配置在角色创建时读取)。
- **ffmpeg 依赖:随 pip 自带,无需系统安装**。`requirements.txt` 已含 `imageio-ffmpeg`,它会带一份跨平台(macOS/Windows)静态 ffmpeg 二进制,`pip install -r requirements.txt` 装完即可用,**免 brew/apt、免折腾 PATH**。
- 解析优先级见 [tts_piper.py](src/assistants/jarvis/tts_piper.py):① pip 包 imageio-ffmpeg(主路径)→ ② 系统 ffmpeg(`shutil.which` + 常见安装位置,兜底)。
- 万一两者都没有,**也不会报错**——自动回退纯 Piper 原声,仅在启动日志给一条提示。
- 可选覆盖:设环境变量 `FFMPEG_BIN` 指向自定义 ffmpeg 可执行文件。
## 项目亮点
- **多角色切换**:内置贾维斯、林妹妹两个角色,独立唤醒词、话术风格、音效和视觉特效,随时切换体验
- **智能语音识别**:支持 SenseVoice 多语言识别、流式识别增强、热词优化,中英文混合识别更准确
- **打断与连续对话**:随时用唤醒词打断,支持多轮连续对话,30秒无活动自动待机
- **HUD 视觉特效**:Flutter 透明桌面窗口,多层旋转环形动画、音频电平实时可视化,科技感拉满
- **完全本地运行**:语音识别、语音合成全部本地运行,仅 LLM 推理通过 OpenClaw 网关
- **分级退出机制**:支持普通退出、即时退出、模糊匹配退出,以及 API 远程退出,灵活控制
## 目录
- [系统架构](#系统架构)
- [快速开始](#快速开始)
- [1. 克隆项目](#1-克隆项目)
- [2. 安装依赖](#2-安装依赖)
- [3. 配置环境变量](#3-配置环境变量)
- [4. 下载模型文件](#4-下载模型文件)
- [5. 准备音效文件](#5-准备音效文件)
- [6. 启动语音助手](#6-启动语音助手)
- [7. 设备配对(首次启动必看)](#设备配对首次启动必看)
- [使用教程](#使用教程)
- [基本使用流程](#基本使用流程)
- [多角色切换](#多角色切换)
- [连续对话模式](#连续对话模式)
- [打断机制](#打断机制)
- [退出机制](#退出机制)
- [自定义配置](#自定义配置)
- [添加新角色](#添加新角色)
- [配置唤醒词](#配置唤醒词)
- [配置退出关键词](#配置退出关键词)
- [自定义音效](#自定义音效)
- [高级功能](#高级功能)
- [声纹验证](#声纹验证唤醒强制校验)
- [热词优化](#热词优化)
- [API 接口](#api-接口)
- [常见问题](#常见问题)
## 系统架构
```
┌─────────────────────────────────────────────────────┐
│ assistant_overlay (Flutter HUD) │
│ 透明窗口 · 环形动画 · 终端显示 · TCP 17889 │
└──────────────────────┬──────────────────────────────┘
│ TCP 控制命令
┌──────────────────────▼──────────────────────────────┐
│ main.py │
│ │
│ ┌────────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ KWS 唤醒 │ → │ ASR 识别 │ → │ 主脑桥接 │ │
│ │ (多角色) │ │ 流式/离线 │ │ engine 切换 │ │
│ └────────────┘ └──────────┘ └──────┬──────┘ │
│ │ │
│ ┌─────────────────┐ ┌────────────────▼──────┐ │
│ │ 反馈系统 │ ← │ TTS (Piper/ZipVoice/ │ │
│ │ 音效+HUD+通知 │ │ VITS MeloTTS) │ │
│ └─────────────────┘ └───────────────────────┘ │
└──────────────────────────┬──────────────────────────┘
│ LLM 推理(engine 二选一)
┌──────────────┴───────────────┐
▼ ▼
┌───────────────────────┐ ┌──────────────────────────┐
│ OpenClaw Gateway │ │ Hermes 本地网关 │
│ engine=openclaw(默认)│ │ engine=hermes │
│ openclaw_bridge_ws │ │ 一角色一 profile / 网关 │
└───────────────────────┘ └──────────────────────────┘
```
> 主脑引擎由 `assistants.json` 顶层 `engine` 字段切换:缺省/未知值走 **OpenClaw**(默认),填 `hermes` 则走本地 Hermes。Hermes 链路详见 [hermes-assistant.md](./hermes-assistant.md)。
## 快速开始
### 0. 环境要求
- **Python 3.11.x(推荐)**:本项目在 Python 3.11 下开发验证;3.10 理论可用但未测试,3.12+ 部分依赖(sherpa-onnx / onnxruntime)可能缺预编译轮子,暂不建议。
- **操作系统**:macOS / Windows,linux暂无开发打算
- **OpenClaw Gateway**:需已安装并可运行,见上文[前置说明](#前置说明)。
> 金属感语音后处理所需的 **ffmpeg 已通过 `imageio-ffmpeg` 内置**,无需系统单独安装或配置 PATH。
### 1. 克隆项目
```bash
mkdir -p ~/.openclaw/workspace/voice-assistant
cd ~/.openclaw/workspace/voice-assistant
git clone <仓库地址>
cd assistant-x-openclaw
mkdir models
```
### 2. 安装依赖
创建虚拟环境并安装依赖:
**macOS**
```bash
python3 -m venv venv
source ./venv/bin/activate
venv/bin/pip install --force-reinstall --no-cache -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
```
**Windows:**
```cmd
python -m venv venv
.\venv\Scripts\activate
pip install --force-reinstall --no-cache -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
```
> **提示**:`-i https://pypi.tuna.tsinghua.edu.cn/simple` 使用清华 PyPI 镜像加速下载,海外网络环境可去掉该参数走官方源。
### 3. 配置环境变量
复制 `.env.example` 为 `.env`:
```bash
cp .env.example .env
```
编辑 `.env` 文件,填入必要配置:
```bash
OPENCLAW_GATEWAY_TOKEN=你的OpenClaw Gateway令牌
```
> **提示**:需在 `~/.openclaw/openclaw.json` 中确保 Gateway HTTP 端点已启用:
```json
{
"gateway": {
"port": 18789,
"mode": "local",
"bind": "loopback",
"auth": {
"mode": "token",
"token": "你的token"
},
"http": {
"endpoints": {
"chatCompletions": {
"enabled": true
}
}
}
}
}
```
### 4. 下载模型文件
项目需要以下模型文件,放在 `models/` 目录下:
**必需模型:**
点击下方链接下载,将文件放入 `models/` 目录,`.tar.bz2` 文件需解压(Windows 可用 7-Zip,macOS 用 `tar xf`):
| # | 模型 | 下载链接 |
|---|------|----------|
| 1 | KWS 唤醒模型 | [sherpa-onnx-kws-zipformer-wenetspeech-3.3M-2024-01-01.tar.bz2](https://github.com/k2-fsa/sherpa-onnx/releases/download/kws-models/sherpa-onnx-kws-zipformer-wenetspeech-3.3M-2024-01-01.tar.bz2) |
| 1 | KWS 唤醒模型(跟上面的二选一) | [sherpa-onnx-kws-zipformer-zh-en-3M-2025-12-20.tar.bz2](https://github.com/k2-fsa/sherpa-onnx/releases/download/kws-models/sherpa-onnx-kws-zipformer-zh-en-3M-2025-12-20.tar.bz2) |
| 2 | ASR 语音识别模型 | [sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2](https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2) |
| 3 | VAD 静音检测模型 | [silero_vad_v5.onnx](https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/silero_vad_v5.onnx)(下载后重命名为 `silero_vad.onnx`) |
| 4 | SenseVoice 多语言识别模型 | [sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2](https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-sense-voice-zh-en-ja-ko-yue-int8-2024-07-17.tar.bz2) |
| 5 | Jarvis TTS 模型(贾维斯英文语音合成,内置角色必需) | [jarvis.zip](https://modelscope.cn/datasets/rubintry/jarvis/resolve/master/jarvis%E8%AF%AD%E9%9F%B3%E6%A8%A1%E5%9E%8B/jarvis.zip)(ModelScope,下载后在 `models/` 目录解压,得到 `models/jarvis/en/en_GB/jarvis/high/jarvis-high.onnx` 即正确);也可在 `models/` 目录执行 `git clone https://huggingface.co/jgkawell/jarvis` |
| 6 | VITS MeloTTS 模型(林妹妹中英文语音合成,内置角色必需) | [vits-melo-tts-zh_en.tar.bz2](https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/vits-melo-tts-zh_en.tar.bz2) |
| 7 | 声纹嵌入模型(唤醒声纹验证与录入必需) | [3dspeaker_speech_campplus_sv_zh-cn_16k-common.onnx](https://github.com/k2-fsa/sherpa-onnx/releases/download/speaker-recongition-models/3dspeaker_speech_campplus_sv_zh-cn_16k-common.onnx) |
**可选模型(根据需求下载):**
| # | 模型 | 下载链接 |
|---|------|----------|
| 8 | Qwen3-ASR 离线识别模型(贾维斯默认 `asr_mode: "offline"` 使用,缺失自动回退流式识别) | [sherpa-onnx-qwen3-asr-0.6B-int8-2026-03-25.tar.bz2](https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/sherpa-onnx-qwen3-asr-0.6B-int8-2026-03-25.tar.bz2) |
| 9 | ZipVoice TTS 模型(零样本声音克隆) | [sherpa-onnx-zipvoice-distill-int8-zh-en-emilia.tar.bz2](https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/sherpa-onnx-zipvoice-distill-int8-zh-en-emilia.tar.bz2) |
### 5. 准备音效文件(看看就行,懒得换音效的话不用研究)
在 `data/voices/` 目录下准备以下音效文件(WAV 格式):
| 文件名 | 用途 | 必需 |
|--------|------|------|
| `wake.wav` | 唤醒确认音效 | ✅ |
| `processing_jarvis.wav` | 贾维斯处理中音效 | ✅ |
| `processing_linmeimei.wav` | 林妹妹处理中音效 | ✅ |
| `thinking.wav` | 思考中音效 | ✅ |
| `execute.wav` | 执行指令音效 | ✅ |
| `success.wav` | 操作成功音效 | ✅ |
| `error.wav` | 操作失败音效 | ✅ |
| `exit.wav` | 退出待机音效 | ✅ |
| `continue.wav` | 继续对话音效 | ✅ |
| `system_ready.wav` | 系统就绪音效 | ✅ |
| `blaster.wav` | 特效音效 | 可选 |
| `waiting.wav` | 等待输入音效 | 可选 |
| `jarvis_start_up.mp3` | 贾维斯参考音频(用于 ZipVoice 克隆) | 可选 |
> **提示**:你可以自己录制这些音效,或使用现成的 JARVIS 风格音效文件。
### 6. 启动语音助手
**macOS:**
1.请从[此处](https://modelscope.cn/datasets/rubintry/jarvis/files)下载assistant_overlay.dmg、control_center.dmg
2.安装assistant_overlay.dmg和dmg、control_center.dmg
3.打开「control_center」app,根据提示录入声纹后,开启语音助手,喊出贾维斯
**Windows:**
1.请从[此处](https://modelscope.cn/datasets/rubintry/jarvis/files)下载 `assistant_overlay.msix`、`control_center.msix`
2.双击 `assistant_overlay.msix` 安装,首次安装会弹窗提示安装自签名测试证书,点击确认(需管理员权限,会弹 UAC)。`control_center.msix` 同理
> 若双击安装报错,也可用 PowerShell 安装(以管理员身份运行):
> ```powershell
> Add-AppxPackage -Path assistant_overlay.msix
> Add-AppxPackage -Path control_center.msix
> ```
3.从开始菜单打开「Control-Center」,根据提示录入声纹后,开启语音助手,喊出贾维斯
4.(从源码打包)如需自行打包 MSIX 安装包,在各 Flutter 项目目录下执行:
```cmd
cd assistant_overlay
scripts\package.bat
cd control_center
scripts\package.bat
```
打包脚本会自动执行 `flutter build windows` + `dart run msix:create`,生成的 `.msix` 在 `build\windows\x64
unner\Release\` 目录下。
## 使用教程
### 基本使用流程
#### 1. 唤醒语音助手
启动后,程序会显示"正在检测唤醒词...",此时直接说出唤醒词即可唤醒:
- **贾维斯**:说"贾维斯"或"加维斯"
- **林妹妹**:说"林妹妹何在"
唤醒词命中后还要过两道关,都通过才算唤醒成功:
1. **VAD 真人语音确认**:抑制电脑外放的人声/TTS 误触发唤醒词;
2. **声纹验证**(强制):取唤醒前最近约 3 秒音频与已注册声纹比对,**未注册声纹或不是本人,唤醒会被直接拒绝**。首次使用请先在控制中心录入声纹(详见下方「声纹验证」)。
唤醒后助手会自动向主脑引擎发送一条 `voice-assistant-wake-up-<本地时间戳>` 消息,
由引擎返回的内容作为问候语播报(不再是写死的欢迎语)。问候在后台线程播报,期间再次说唤醒词可直接打断。听到问候后即可开始对话。
> 需在角色 system prompt 里加一条对该消息的应答规则,否则引擎可能把它当普通输入。
> 详见 [hermes-assistant.md](./hermes-assistant.md) 第四节(OpenClaw 模式同样适用)。
#### 2. 说出指令
唤醒后直接说出你的指令,例如:
- "今天天气怎么样?"
- "帮我设置一个明天早上8点的闹钟"
- "查一下我的日程"
助手会实时识别你的语音,播放 TTS 回复,并显示 HUD 动画。
#### 3. 自动待机
- 30 秒无语音活动,助手会自动进入待机状态
- 待机后再次说出唤醒词即可重新唤醒
### 多角色切换
项目内置两个角色,你可以在对话中随时切换:
| 角色 | 风格 | 特点 |
|------|------|------|
| **贾维斯** | 专业、干练 | 英文 TTS(Piper,可叠金属感),Qwen3-ASR 离线识别(模型缺失自动回退流式),科技感 HUD |
| **林妹妹** | 亲切、俏皮 | 中文 TTS(VITS MeloTTS),流式中英双语识别,粉色主题 HUD |
**如何切换:**
**直接说出目标角色的唤醒词即可**——待机时喊"林妹妹何在"就切到林妹妹,喊"贾维斯"就切回贾维斯,运行时自动完成切换(含 TTS/HUD/识别模式),无需改配置、无需重启。
`assistants.json` 中的 `"default"` 字段只决定**启动时**默认加载哪个角色:
```json
{ "default": "jarvis" }
```
### 连续对话模式
唤醒后自动进入连续对话模式,支持多轮指令:
```
你:"贾维斯"
助手:"At your service, sir. What do you need?"
你:"今天天气怎么样?"
助手:(播放天气信息)
你:"那明天呢?" ← 无需再次唤醒,直接说指令
助手:(播放明天天气)
你:"好的,帮我记下来" ← 继续对话
助手:(记录备忘录)
```
**退出连续对话:**
- 说出退出关键词(见下方"退出机制")
- 30 秒无语音活动自动待机
### 打断机制
**随时打断当前处理:**
- 在助手正在回复或播放 TTS 时,再次说出唤醒词
- 助手会立即停止当前操作,重新识别你的新指令
**示例:**
```
你:"贾维斯"
助手:"At your service..."
你:"贾维斯!" ← 打断
助手:(停止播放,重新识别)
你:"算了,帮我查个邮件" ← 新指令
```
> **防误触**:打断有冷却保护期,避免误触发。
### 退出机制
退出只有两种情况:
**1. 用户直接说退出关键词**
说出退出关键词,助手会播放告别语并进入待机:
| 角色 | 退出关键词示例 |
|------|----------------|
| 贾维斯 | "dismissed"、"stand down"、"that's all"、"退下"、"你可以退下了"、"exit"、"quiet"、"SHUT UP" |
| 林妹妹 | "退下"、"退下吧"、"好了"、"行了"、"结束"、"你可以退下了" |
完整列表见 `assistants.json` 各角色的 `exit_keywords` 字段。
其中部分关键词会即时退出(不播放告别语):
- 贾维斯:"stand down"、"you may leave"
- 林妹妹:"退下吧"、"你可以退下了"
**2. AI 判定用户有让助手待机的意图**
当用户说的话虽然没有直接命中退出关键词,但 AI 判断用户想让助手退下时,会自动调用 API 远程退出:
```bash
curl -X POST http://127.0.0.1:18790/exit
```
比如用户说"好了好了我知道了你去吧",AI 识别到待机意图后就会自动触发退出。
## 自定义配置
### 添加新角色
1. 在 `assistants.json` 的 `assistants` 数组中添加新角色:
```json
{
"id": "your-assistant-id",
"name": "角色名称",
"enabled": true,
"visual": "jarvis",
"components": {
"feedback": "custom",
"visual": "custom",
"tts": "custom"
},
"keywords_file": "keywords/your-assistant.txt",
"asr_mode": "streaming",
"tts_config": {
"engine": "vits",
"model_dir": "models/vits-melo-tts-zh_en",
"speed": 1.0
},
"wake_lines": ["角色唤醒语1", "角色唤醒语2"],
"exit_lines": ["角色退出语1", "角色退出语2"],
"exit_keywords": ["退出关键词1", "退出关键词2"],
"instant_exit_keywords": ["即时退出1"],
"instant_exit_fuzzy": ["模糊匹配词1"],
"restart_keywords": ["重启", "重新启动"]
}
```
**字段说明:**
- **`components`**:选择该角色的反馈/视觉/TTS 实现。填 `jarvis` 复用贾维斯的内置实现,填 `custom` 走通用模板(`src/assistants/custom_*.py`),可再配合 `feedback_config`(自定义音效文件、HUD 文案、通知前缀)和 `visual_config` 精调,参考 `assistants.json` 里林妹妹的写法。
- **`asr_mode`**:该角色的语音识别模式,可选值:
| 取值 | 识别方案 | 说明 |
|------|----------|------|
| `streaming`(默认) | 流式 Zipformer 中英双语 | 边说边出结果,低延迟,支持热词 |
| `sense_voice` | SenseVoice 多语言(自动检测) | VAD 断句,一次返回完整结果 |
| `sense_voice_en` | SenseVoice 英文模式 | 同上,仅英文 |
| `offline` | Qwen3-ASR 离线识别 | 需下载可选模型第 8 项 |
对应模型不可用时自动回退到流式模式,不会启动失败。
- **`tts_config`**:TTS 引擎配置。`engine`/`model_dir` 指定引擎与模型,`speed` 调语速,贾维斯还支持 `metallic` 金属感后处理(见上方「贾维斯金属感语音」)。
- **`restart_keywords`**:命中后重启整个语音助手(自动执行 `start.sh` / `start.bat`),带幂等保护防止回声重复触发。
2. 在 `keywords/` 目录下创建对应的唤醒词文件(如 `keywords/your-assistant.txt`)
3. 重启语音助手即可生效
### 配置唤醒词
唤醒词文件位于 `keywords/` 目录,每个角色独立配置。
**格式:**
```
拼音 :灵敏度 #阈值 @唤醒词文本
```
**示例(`keywords/jarvis.txt`):**
```
j i a w e i s i :3.0 #0.05 @贾维斯
j i a w e i s :2.0 #0.05 @加维思
```
- **拼音**:用空格分隔
- **灵敏度**:数值越高越容易触发(推荐 2.0-3.0)
- **阈值**:触发得分阈值(推荐 0.02-0.05)
- **唤醒词文本**:显示在 HUD 上的文本
**添加多个变体:**
为提高识别率,可以添加多个拼音变体:
```
l i n m e i m e i h e z a i :3.0 #0.02 @林妹妹何在
l i n m e i m e i h e z a i :3.0 #0.02 @林妹妹何在
l i n m e i m e i z a i m a :3.0 #0.02 @林妹妹在吗
```
### 配置退出关键词
在 `assistants.json` 中配置三类退出关键词:
```json
{
"exit_keywords": ["退下", "exit", "quiet"],
"instant_exit_keywords": ["退下吧", "stand down"],
"instant_exit_fuzzy": ["退一下", "step back"]
}
```
- **exit_keywords**:普通退出,会播放告别语
- **instant_exit_keywords**:即时退出,立即退出
- **instant_exit_fuzzy**:模糊匹配,包含这些词就会触发
### 自定义音效
1. 录制或下载 WAV 格式音效
2. 放入 `data/voices/` 目录,替换对应文件名
3. 无需重启,下次播放时自动使用新音效
> **音效格式建议**:16-bit, 44100Hz, 单声道,长度 0.5-2 秒
### 主脑引擎选择(OpenClaw / Hermes)
`assistants.json` **顶层** `engine` 字段决定用哪个主脑引擎对接大模型:
```json
{
"engine": "openclaw", // 默认;可选 "hermes"
"default": "jarvis",
"assistants": [ ... ]
}
```
- `openclaw`(默认,缺省或未知值都回退到它):走 OpenClaw Gateway。
- `hermes`:本地 Hermes 作主脑,一角色一 profile 一网关。配置/启动/排错见
[hermes-assistant.md](./hermes-assistant.md)。
### 特效调试模式(overlay_debug_mode)
`assistants.json` 顶层 `overlay_debug_mode` 为 `true` 时,召唤出来的 HUD 特效**不再自动隐藏/清空**,
方便对着调样式;正常使用保持 `false`。
```json
{
"overlay_debug_mode": false,
"assistants": [ ... ]
}
```
### 激活联动(唤醒时自动隐藏 Dock / 暂停媒体)
助手"被唤醒 → 退回待机"这两个时刻,可以联动触发一些系统动作。目前内置两项(均仅 macOS、软失败、退待机自动还原):
| 联动 | 开关 | 默认 | 依赖 |
| --- | --- | --- | --- |
| 唤醒时暂停正在播放的影视/音乐 | 自动(无需配置) | 开 | `brew install media-control` |
| 唤醒时把系统 Dock 切到自动隐藏 | `dock_autohide_on_wake` | 关 | macOS 自动化授权(见下) |
```json
{
"dock_autohide_on_wake": true, // 顶层;改完需重启助手才生效
"assistants": [ ... ]
}
```
两者都遵循「**只还原我改的**」:你本来就开着 Dock 自动隐藏、或当时没有媒体在播,助手绝不会擅自改动。
> **Dock 自动隐藏的授权坑(首次必看)**
> 切 Dock 走的是 AppleScript 控制「系统事件」,需要 macOS 的**自动化授权**。由于助手是被**控制中心** App 拉起的,授权弹窗会归到控制中心头上,因此:
> 1. 控制中心的 `Info.plist` 必须带 `NSAppleEventsUsageDescription`(本仓库已加)——**改的是源码,必须重新 `flutter build macos` 并覆盖安装 `/Applications/control_center.app` 才进包**;
> 2. 打开开关后**重启助手**,首次唤醒时会弹「控制中心想要控制"系统事件"」,点**好**即永久生效;
> 3. 若死活不弹窗,多半是缓存了静默拒绝,执行 `tccutil reset AppleEvents cn.rubintry.assistant.ctrl.center.controlCenter` 清掉再重试。
>
> 注意:autohide 只是"鼠标离开屏幕边缘就收起",把鼠标怼到屏幕底边 Dock 仍会冒出来——要彻底不露需用 overlay 窗口层级遮挡,暂未实现。
> **想加新联动?** 联动注册表在 `src/lifecycle.py`:实现 `LifecycleHook` 的 `on_wake` / `on_standby` 并 `register` 即可,主循环无需改动(`is_awake` 已是边沿触发的 property)。媒体暂停、Dock 隐藏都是这么接入的。
## 高级功能
### 声纹验证(唤醒强制校验)
声纹验证已是**强制功能**:每次唤醒词命中后,都会取最近约 3 秒音频与已注册声纹比对,通过才放行唤醒。行为规则:
- **已注册声纹**:只有声纹匹配的说话人能唤醒;验证被拒绝时继续待机,并向控制中心推送一条「声纹验证被拒绝」通知。
- **未注册任何声纹**:助手**拒绝一切唤醒**,需先录入声纹才能使用(启动日志会给出提示)。
- **声纹模型文件缺失**:跳过验证直接放行(此时不安全,建议按模型表第 7 项下载 `3dspeaker_speech_campplus_sv_zh-cn_16k-common.onnx` 放入 `models/`,缺模型时录入也会报错 `No graph was found in the protobuf`)。
- **渐进更新**:验证通过后,连续对话中的语音会持续微调该用户的声纹嵌入,越用越准(嵌入缓存在录入 JSON 里)。
**如何录入:**
> **macOS / Windows 用户**:直接在「控制中心」App 内按提示录入即可,无需手动跑脚本。录入期间控制中心会自动调用勿扰接口暂停唤醒(见下方 API 接口),避免反复念"贾维斯"误唤醒。
命令行录入:
```bash
./scripts/enroll_speaker.py
```
按提示朗读"贾维斯"即可完成录入,样本保存在 `data/enrollment/` 目录。录入完成后重启语音助手生效。
### 热词优化
项目预配置了技术热词,你也可以自定义:
- `hotwords.txt`:中文热词(技术术语、编程语言等)
- `hotwords_en.txt`:英文热词(框架、工具等)
**添加热词:**
在对应文件中按行添加:
```
Transformer
RAG
LoRA
FastAPI
```
重启语音助手后自动生效。
**文本纠错兜底(text_corrections.txt):**
sherpa 热词对 cjkchar+bpe 模型下 **OOV 英文整词**(词表里没有的词,如人名、新产品名)几乎无效——整词 token 找不到会被静默跳过。这类词请写进根目录 `text_corrections.txt`,在识别结果送 HUD/大模型之前做整词替换(大小写不敏感):
```
# 格式:<误识别> : <正确>
open cloud : OpenClaw
贾维尔 : 贾维斯
```
文件不存在则跳过(纠错是可选功能),启动时加载。
### API 接口
本地 HTTP 接口监听 `127.0.0.1:18790`(控制中心也通过它联动语音助手)。
**远程退出:**
```bash
curl -X POST http://127.0.0.1:18790/exit
```
返回:
```json
{"status": "ok"}
```
**勿扰模式(声纹录入时暂停唤醒):**
录入声纹时若不静音唤醒词,反复念“贾维斯”会误唤醒。控制中心“声纹注册”会自动调用,
也可手动控制:
```bash
curl -X POST http://127.0.0.1:18790/dnd # 进入勿扰:暂停唤醒词响应
curl -X POST http://127.0.0.1:18790/dnd/disable # 解除勿扰:恢复唤醒
```
> 端口被占导致接口未监听时勿扰不会生效(控制中心会在录入日志里给出警告)。
> 主程序启动绑定该端口已带重试,`start.sh` 也会预清理 18790。
**摄像头抓帧(供 Hermes「用摄像头看看我」):**
`GET /camera/snapshot` 抓一帧并直接返回 JPEG,主脑(Hermes/OpenClaw)可经此拿到画面再交给 `vision_analyze`:
```bash
curl -s http://127.0.0.1:18790/camera/snapshot -o /tmp/cam.jpg # 成功:JPEG 落地
# 失败返回 JSON:{"error": "..."}(摄像头不可用 503 / 抓帧失败 500)
```
- 抓帧复用仓库自带的 **imageio-ffmpeg**(静态 ffmpeg 含 avfoundation),免装系统工具;实现见 [src/camera.py](src/camera.py),默认 1920x1080@30、丢弃前 8 帧预热、8s 超时软失败。
- **首次需授权**:抓帧进程由控制中心拉起,摄像头权限归控制中心。已在其 `Info.plist` 加 `NSCameraUsageDescription`——**改的是源码,需重新 `flutter build macos` 覆盖安装 `/Applications/control_center.app` 才进包**;之后首次调用会弹「控制中心想使用摄像头」,点允许即永久生效(与 Dock 自动隐藏的授权同理)。
- 仅 macOS;非 macOS 或未授权超时均返回错误、不影响其他功能。
## 常见问题
### Q: 唤醒词不灵敏 / 喊了没反应怎么办?
1. **先确认声纹**:声纹验证是强制的——未注册声纹会拒绝一切唤醒,非本人喊也会被拒(终端会打印 `[声纹] 唤醒被拒绝`)。先在控制中心录入声纹
2. 检查麦克风设备是否正常:启动时会列出可用设备
3. 调整唤醒词灵敏度:在 `keywords/*.txt` 中提高灵敏度数值(2.0 → 3.0)
4. 添加更多拼音变体到唤醒词文件
5. 确保环境安静,背景噪音会影响识别;另外唤醒前有 VAD 真人语音确认,电脑外放的人声会被有意忽略
### Q: 语音助手会不会和其他应用抢麦克风?
不会独占采样率。输入流按 48kHz 打开(与大多数应用/系统默认一致,可共存),内部用 soxr 重采样到 16kHz 再喂 sherpa 模型;没装 soxr 时回退原始采样率,识别精度会下降。另外音频流有看门狗:静默停滞超过 15 秒会自动重建流,无需手动重启。
### Q: 如何查看当前使用的设备?
启动程序时会显示可用麦克风设备列表,以及默认使用的设备名称。
### Q: HUD 窗口不显示?
1. 确保已构建 Flutter 项目:`cd assistant_overlay && flutter build macos --debug`
2. 检查端口 17889 是否被占用
3. 查看控制台是否有 TCP 连接错误
### Q: TTS 合成失败?
1. 检查 TTS 模型是否正确下载到 `models/` 目录
2. 确认音效文件存在于 `data/voices/`
3. 查看控制台错误信息,确认模型路径正确
4. 如果报 `No module named 'piper'`,请确认安装的是 `piper-tts` 而非 `piper`:
```bash
pip uninstall piper -y # 卸载错误包(pypiper)
pip install piper-tts # 安装正确的 Piper TTS 包
```
> `piper` 是一个无关的管道工具包(pypiper),正确的 TTS 包名是 `piper-tts`
### Q: 如何切换 TTS 引擎?
在 `assistants.json` 中修改对应角色的 TTS 配置(需要代码中支持多引擎切换)。
### Q: 支持 Windows 吗?
是的,项目支持 Windows 平台。使用 `scripts\start.bat` 启动,部分功能(如 HUD 窗口)可能需要调整。
> **Windows 音频说明**:Windows 下使用 `sounddevice` + `soundfile` 进行音频播放(与 macOS 的 `afplay` 方案不同),无需额外安装 `pygame`。
### Q: 日志文件在哪?为什么文件里几乎是空的?
运行日志在 `logs/` 目录(`jarvis_<时间>_.log`)。**日志文件只记录 ERROR 级及以上**
(含未捕获异常的 traceback),其余正常输出一律不落盘——所以排查正常流程要看**终端/控制中心**
的实时输出,文件只用来留底错误。每类日志各保留最近若干份,旧的自动清理。
---
## 项目结构
```
assistant-x-openclaw/
├── src/ # 源代码
│ ├── main.py # 主程序:唤醒 + 声纹验证 + 识别 + 对话流程 + 本地 API
│ ├── tts.py # TTS 统一接口
│ ├── tts_vits.py # VITS TTS 引擎
│ ├── openclaw_bridge_websocket.py # OpenClaw Gateway 桥接(engine=openclaw)
│ ├── hermes_bridge.py # Hermes 桥接(engine=hermes,详见 hermes-assistant.md)
│ ├── lifecycle.py # 激活联动钩子注册表(唤醒/休眠边沿派发)
│ ├── media_pause.py # 激活联动:唤醒时暂停媒体
│ ├── dock_control.py # 激活联动:唤醒时隐藏 Dock(macOS)
│ ├── camera.py # 摄像头抓帧(GET /camera/snapshot,macOS)
│ ├── anti_spoof.py # 活体检测(AASIST,开发中未启用)
│ ├── notify_bridge.py # 向控制中心推送通知(如声纹拒绝)
│ ├── log_setup.py # 日志:ERROR 落盘 + diag 诊断日志
│ ├── audio.py # 音频播放模块
│ └── assistants/ # 角色系统
│ ├── feedback.py # 反馈系统基类(音效 + HUD + 通知)
│ ├── visual.py # HUD 视觉基类
│ ├── tts.py # 角色 TTS 基类
│ ├── jarvis/ # 贾维斯角色(Piper/ZipVoice TTS、visual、feedback)
│ ├── lin_meimei/ # 林妹妹角色
│ └── custom_*.py # 自定义角色模板(components 填 "custom" 时使用)
├── scripts/ # 工具脚本
│ ├── start.sh # 启动脚本(macOS:合并唤醒词 + 清理端口 + 拉起 HUD/主程序)
│ ├── start.bat # 启动脚本(Windows)
│ ├── enroll_speaker.py # 声纹录入工具
│ └── hermes_provision.py # Hermes profile 初始化(engine=hermes 用)
├── assistant_overlay/ # Flutter HUD 视觉特效应用
├── control_center/ # Flutter 控制中心应用(声纹录入 / 启停 / 日志,macOS & Windows)
├── prompts/ # 角色 System Prompt(jarvis/SOUL.md)
├── skills/ # 主脑技能(browser-cdp / desktop-control)
├── data/
│ ├── voices/ # 音效文件
│ └── enrollment/ # 已录入的声纹样本
├── models/ # ONNX 模型文件
├── keywords/ # 唤醒词配置
│ ├── jarvis.txt
│ ├── lin-meimei.txt
│ └── global.txt # 自动生成,合并所有唤醒词
├── assistants.json # 角色与引擎配置文件
├── hotwords.txt # 中文热词
├── hotwords_en.txt # 英文热词
├── text_corrections.txt # 文本纠错表(OOV 英文整词兜底)
├── .env # 环境变量
└── requirements.txt # Python 依赖
```
---
**开源协议**: [MIT License](LICENSE)
**作者**: Rubintry
**日期**: 2026