DroneMind/voicellmcloud/docs/CLOUD_VOICE_ASSISTANT_SESSION_v1.md
2026-04-14 10:08:41 +08:00

179 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 语音助手会话方案 v1服务端 + 机端对齐)
本文档描述 **「唤醒 → 问候 → 滴声开录 → 断句上云 → 提示音 → 云端理解与 TTS → 分支循环/待机」** 的端到端方案,供 **服务端voicellmcloud****机端** 分工落地。
**v1 明确不做**:播报中途 **抢话 / 打断 TTSbarge-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.md`](./CLOUD_VOICE_CLIENT_WAKE_GATE_v1.md)
- 总接口:[`API_SPECIFICATION.md`](./API_SPECIFICATION.md)
- 飞控确认窗:[`CLOUD_VOICE_FLIGHT_CONFIRM_v1.md`](./CLOUD_VOICE_FLIGHT_CONFIRM_v1.md)
---
## 1. 产品流程(用户视角)
1. 用户说唤醒词(如「无人机」,由机端配置),**仅本地处理,不上云 ASR**。
2. 机端播放问候语(如「你好,有什么事儿吗」)— 可用本地 TTS 或 `tts.synthesize`
3. 机端 **滴一声**,表示 **开始收音**;同时启动 **5 秒静默超时** 计时(见 §4
4. 用户说话;机端 **VAD/端点检测** 得到 **一整句** 后:
- 播放 **极短断句提示音**(表示「已截句、将上云」);
- **提示音播放期间闭麦或做回声隔离**,提示音结束后 **短消抖**(建议 **150300 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` 一致)。
**唤醒前**:必须满足 [`CLOUD_VOICE_CLIENT_WAKE_GATE_v1.md`](./CLOUD_VOICE_CLIENT_WAKE_GATE_v1.md)。
---
## 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`**(产品定)。
### 3.4 服务端开发自检
- [x] `pcm_asr_uplink` 下单轮 ASR+LLM+TTS 与 `text_uplink` 下行形态一致(除 `asr.partial`)。 — 已实现:`app/websocket/handler.py``turn.audio.*` → Fun-ASR → `_run_turn_text_locked`)。
- [x] `flight_intent` 仍带 `confirm`dialog v1 客户端声明 protocol 时)。 — 已实现:`create_dialog_result_cloud_v1` 与既有 dialog v1 流水线。
- [x] 文档无需为新 UX 增加强制字段。 — v1 不新增 WS 帧类型。
### 3.5 与本仓库voicellmcloud的对应关系
| 文档 § | 代码 / 配置 |
|--------|-------------|
| Fun-ASR + 单轮 LLM + TTS | `app/providers/dashscope_fun_asr_turn.py``handler._handle_turn_audio_*``handler._run_turn_text_locked` |
| `asr.partial` 下行 | `models.create_asr_partial`Fun-ASR 回调中经 `session_manager.send_json` 下发 |
| `pcm_asr_uplink` / `session.ready` | `handler._handle_session_start``validators.validate_session_start` |
| 飞控确认 JSON | [`CLOUD_VOICE_FLIGHT_CONFIRM_v1.md`](./CLOUD_VOICE_FLIGHT_CONFIRM_v1.md) + `handler``dialog_result` v1 |
**结论**:服务端按本文 **§3** 交付时,**无需再为「小爱类会话」单独开发新协议**;机端按 §1§2、§4§8 实现状态机与定时即可联调。
---
## 4. 5 秒静默超时(闲聊路径)
| 项 | 约定 |
|----|------|
| **起算点** | 「**开始收音**」的 **滴声播放结束** 时刻(或滴声后固定 **50100 ms** 偏移,避免与滴声能量重叠)。 |
| **「无说话」** | 麦克 **RMS / VAD** 低于阈值,持续累计 ≥ **5 s**(建议可配置,默认 5。 |
| **期间若开始说话** | 清零超时;**断句上云**后本超时在下一轮「滴声」后重新起算。 |
| **触发动作** | 播 **超时提示音** → 进入 **`STANDBY`**(不再滴声、不上云)。 |
| **不适用** | **`FLIGHT_CONFIRM`** 整段;确认窗用 **服务端给的 `timeout_sec`**。 |
---
## 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` | `≤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 |