# 语音助手会话方案 v1(服务端 + 机端对齐) 本文档描述 **「唤醒 → 问候 → 滴声开录 → 断句上云 → 提示音 → 云端理解与 TTS → 分支循环/待机」** 的端到端方案,供 **服务端(voicellmcloud)** 与 **机端(本仓库 voice_drone_assistant)** 分工落地。 **v1 明确不做**:播报中途 **抢话 / 打断 TTS(barge-in)**;播放 TTS 时机端 **关麦或不处理用户语音**。 **关联协议**: - 音频上行与 Fun-ASR:[CLOUD_VOICE_PROTOCOL_pcm_asr_uplink_v1.md](./CLOUD_VOICE_PROTOCOL_pcm_asr_uplink_v1.md) - 未唤醒不上云:由服务端/产品文档 `CLOUD_VOICE_CLIENT_WAKE_GATE_v1` 约定(机端须本地门禁后再建联上云) - 总接口:以 voicellmcloud 仓库 `API_SPECIFICATION` 为准 - 飞控确认窗:[CLOUD_VOICE_FLIGHT_CONFIRM_v1.md](./CLOUD_VOICE_FLIGHT_CONFIRM_v1.md) --- ## 1. 产品流程(用户视角) 1. 用户说唤醒词(如「无人机」,由机端配置),**仅本地处理,不上云 ASR**。 2. 机端播放问候语(如「你好,有什么事儿吗」)— 可用本地 TTS 或 `tts.synthesize`。 3. 机端 **滴一声**,表示 **开始收音**;同时启动 **5 秒静默超时** 计时(见 §4)。 4. 用户说话;机端 **VAD/端点检测** 得到 **一整句** 后: - 播放 **极短断句提示音**(表示「已截句、将上云」); - **提示音播放期间闭麦或做回声隔离**,提示音结束后 **短消抖**(建议 **150~300 ms**)再恢复采集逻辑,避免把提示音当成用户语音。 5. 将该句 **PCM** 以 `turn.audio.*` 发云端;云端 **Fun-ASR → LLM → `dialog_result` → TTS**;机端播完 **全部** `tts_audio_chunk` 及收到 **`turn.complete`** 后,视为本轮播报结束(见 §3 服务端)。 6. **分支**: - **`routing === flight_intent`**:进入 **飞控子状态机**(口头确认/取消/超时),**不使用** §4 的「闲聊滴声后 5s」规则覆盖确认窗;超时以 **`dialog_result.confirm.timeout_sec`** 及 [CLOUD_VOICE_FLIGHT_CONFIRM_v1.md](./CLOUD_VOICE_FLIGHT_CONFIRM_v1.md) 为准。 - **`routing === chitchat`**:本轮结束后 **再滴一声**,进入下一轮 **步骤 4**(同一 WebSocket 会话内 **新 `turn_id`** 再起一轮 `turn.audio.*`)。 7. 若在 **步骤 3 的滴声之后** 连续 **5 s** 内未检测到有效语音(见 §4),机端播 **超时提示音**,**不再收音**,回到 **待机**(仅唤醒)。 --- ## 2. 机端状态机(规范性) | 状态 | 含义 | 开麦 | 上云 ASR | 备注 | |------|------|------|----------|------| | `STANDBY` | 仅监听唤醒 | 按现网 VAD | **禁止** `turn.audio.*` | 本地 STT + 唤醒词 | | `GREETING` | 播问候 | 可关麦或忽略输入 | 否 | 避免问候进识别 | | `PROMPT_LISTEN` | 已滴「开始录」,等用户一句 | 开 | 否 | **5s 超时**在此状态监控 | | `SEGMENT_END` | 已断句,播短提示音 | **闭麦/屏蔽** | 否 | 消抖后再转 `UPLOADING` | | `UPLOADING` | 发送 `turn.audio.*` | 否 | **是** | 一轮一个 `turn_id` | | `PLAYING_CLOUD_TTS` | 播云端 TTS | **关麦**(v1 无抢话) | 否 | 至 `turn.complete` + PCM 播完 | | `FLIGHT_CONFIRM` | 飞控确认窗 | 按飞控文档 | **可** `turn.text` 或按产品另定 | **独立超时**,不共用 5s | | `CHITCHAT_TAIL` | 闲聊结束,将再滴一声 | — | 否 | 回到 `PROMPT_LISTEN` | **并发**:同一时刻仅允许 **一路** `turn.audio.start`~`end`;须等 `turn.complete` 后再开下一轮(与现有 `pipeline_lock` 一致)。 **唤醒前**:须满足未唤醒不上云的产品/协议约定。 --- ## 3. 服务端(voicellmcloud)职责 — v1 **无新消息类型** ### 3.1 单轮行为(不变) 对每个完整 `turn.audio.*` 或 `turn.text`: 1. Fun-ASR(仅 `pcm_asr_uplink` + 音频轮)→ 文本 2. LLM 流式 → `dialog_result`(`routing` / `flight_intent` / `chat_reply` 等) 3. `tts_audio_chunk*` → `turn.complete` 服务端 **不** 下发「请再滴一声」「进入待机」类机端 UX 信令;这些由机端根据 **`routing` + `turn.complete`** **固定规则** 驱动。 ### 3.2 机端判定「播报完成」 须同时满足: - 收到该轮 **`turn.complete`** - 已按序播完该轮关联的 **binary PCM**(`tts_audio_chunk` 与现实现一致) 然后机端再执行 §1 步骤 6 的分支。 ### 3.3 可选下行 - **`asr.partial`**:机端 **不得** 用于驱动状态跳转;仅可 UI 展示。 - **错误**:`error` / `ASR_FAILED` 等 → 机端播简短失败提示后,建议 **回 `STANDBY` 或回到 `PROMPT_LISTEN`**(产品定)。 --- ## 4. 5 秒静默超时(闲聊路径) | 项 | 约定 | |----|------| | **起算点** | 「**开始收音**」的 **滴声播放结束** 时刻(或滴声后固定 **50~100 ms** 偏移,避免与滴声能量重叠)。 | | **「无说话」** | 麦克 **RMS / VAD** 低于阈值,持续累计 ≥ **5 s**(建议可配置,默认 5)。 | | **期间若开始说话** | 清零超时;**断句上云**后本超时在下一轮「滴声」后重新起算。 | | **触发动作** | 播 **超时提示音** → 进入 **`STANDBY`**(不再滴声、不上云)。 | | **不适用** | **`FLIGHT_CONFIRM`** 整段;确认窗用 **服务端给的 `timeout_sec`**。 | **机端配置**(`system.yaml` `cloud_voice`):`listen_silence_timeout_sec`、`post_cue_mic_mute_ms`、`segment_cue_duration_ms`;环境变量见 `main_app.py` 头部说明。 --- ## 5. 断句后提示音(工程) | 项 | 约定 | |----|------| | 目的 | 用户感知「已截句,可等待播报」 | | 实现 | 机端本地短 WAV / 蜂鸣;时长建议 **≤ 200 ms** | | 回声 | **SEGMENT_END** 阶段闭麦或硬件 AEC;结束后 **≥ 150 ms** 再进入 `UPLOADING` | | 与云端 | **无需** 上传该提示音 | --- ## 6. 时序简图(闲聊多轮) ```mermaid sequenceDiagram participant U as 用户 participant D as 机端 participant S as 服务端 U->>D: 唤醒词(本地) D->>D: GREETING 播问候 D->>D: 滴声 → PROMPT_LISTEN(起 5s 定时) U->>D: 一句语音 D->>D: VAD 断句 → 短提示音 → UPLOADING D->>S: turn.audio.start/chunk/end S->>D: asr.partial(可选) S->>D: dialog_result + TTS + turn.complete D->>D: PLAYING_CLOUD_TTS(关麦) alt chitchat D->>D: 再滴声 → PROMPT_LISTEN else flight_intent D->>D: FLIGHT_CONFIRM(独立超时) end ``` --- ## 7. 配置建议(机端) | 键 | 默认值 | 说明 | |----|--------|------| | `listen_silence_timeout_sec` | `5` | 滴声后起算 | | `post_cue_mic_mute_ms` | `150`~`300` | 断句提示音后再采集 | | `cue_tone_duration_ms` / `segment_cue_duration_ms` | `≤200` | 断句提示 | | `flight_confirm_handling` | 遵循飞控文档 | 禁用闲聊 5s 覆盖 | --- ## 8. 机端开发自检 - [ ] `STANDBY` 下无 `turn.audio.start`。 - [ ] `PLAYING_CLOUD_TTS` 与 `SEGMENT_END` 提示音阶段 **不开麦**(v1)。 - [ ] 每轮新 `turn_id`;不并行两轮音频上行。 - [ ] `flight_intent` 后进入 `FLIGHT_CONFIRM`,**不**误用 5s 闲聊超时。 - [ ] `chitchat` 在 TTS 完成后 **再滴** 再 `PROMPT_LISTEN`。 --- ## 9. 非目标(v1) - 播报中抢话、打断 TTS、实时 re-prompt。 - 服务端驱动「滴声/待机」(均由机端规则实现)。 - 连续免唤醒「直接说指令」跨多轮(若需另开 v2)。 --- ## 10. 修订记录 | 版本 | 日期 | 说明 | |------|------|------| | v1 | 2026-04-07 | 首版:小爱类会话 + 双端分工;不含 barge-in |