From 7267c065529e61b3bd0326fa171d7bc87187a689 Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Fri, 22 May 2026 15:10:15 +0800 Subject: [PATCH] Add Chinese docs for product WebSocket usage. Document va.ws.v1 protocol, client messages, server events, and interrupted flag behavior for product clients. Co-authored-by: Cursor --- docs/product-ws.md | 147 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 docs/product-ws.md diff --git a/docs/product-ws.md b/docs/product-ws.md new file mode 100644 index 0000000..fd0fd1e --- /dev/null +++ b/docs/product-ws.md @@ -0,0 +1,147 @@ +# Product WebSocket 使用说明 + +Product WebSocket(`/ws-product`)面向浏览器、移动端等产品客户端,使用稳定的 JSON/base64 协议 `va.ws.v1`。 + +## 连接地址 + +``` +ws://:/ws-product +``` + +生产环境请使用 `wss://`。可通过 `GET /health` 查看当前支持的协议与能力。 + +## 音频参数 + +| 参数 | 默认值 | +|------|--------| +| 编码 | PCM signed 16-bit little-endian(`pcm_s16le`) | +| 采样率 | 16000 Hz | +| 声道 | 1(单声道) | + +## 基本流程 + +1. 建立 WebSocket 连接 +2. 发送 `session.start` 握手 +3. 持续发送音频或文本输入 +4. 接收服务端事件(转写、回复文本、TTS 音频等) +5. 结束时发送 `session.stop` + +### 1. 启动会话 + +```json +{ + "type": "session.start", + "protocol": "va.ws.v1", + "audio": { + "encoding": "pcm_s16le", + "sample_rate": 16000, + "channels": 1 + } +} +``` + +### 2. 发送音频 + +**JSON + base64**(便于调试): + +```json +{ + "type": "input.audio", + "audio": "", + "sample_rate": 16000, + "channels": 1 +} +``` + +**二进制帧**:也可直接发送原始 PCM16 字节,延迟和带宽更优。字段 `audio` 与 `data` 均可作为 base64 字段名。 + +建议按约 20 ms 一帧分片发送(16 kHz 单声道下每帧约 640 字节)。 + +### 3. 发送文本(可选) + +```json +{ + "type": "input.text", + "text": "你好", + "interrupt": true +} +``` + +`interrupt` 默认为 `true`,会打断当前正在播放的 bot 语音。 + +### 4. 取消当前回复 + +```json +{"type": "response.cancel"} +``` + +### 5. 结束会话 + +```json +{"type": "session.stop", "reason": "done"} +``` + +## 服务端事件 + +所有出站消息均为 JSON,包含 `type`、`protocol`(`va.ws.v1`)和递增的 `seq` 字段。 + +| 事件类型 | 说明 | +|----------|------| +| `input.transcript.interim` | 用户语音中间转写(流式 ASR 时) | +| `input.transcript.final` | 用户语音最终转写 | +| `response.text.started` | 助手开始回复 | +| `response.text.delta` | 助手文本流式片段(通常早于 TTS 音频) | +| `response.text.final` | 助手本轮回复结束,见下方 `interrupted` 说明 | +| `response.audio.started` | 开始播放 TTS | +| `response.audio.delta` | TTS 音频片段(base64 PCM16) | +| `response.audio.stopped` | TTS 播放结束 | + +音频事件示例: + +```json +{ + "type": "response.audio.delta", + "protocol": "va.ws.v1", + "seq": 1, + "audio": "", + "bytes": 6400, + "sample_rate": 16000, + "channels": 1 +} +``` + +### `response.text.final` 与 `interrupted` + +每轮助手回复结束时都会发送一条 `response.text.final`: + +```json +{ + "type": "response.text.final", + "text": "今天北京天气晴朗,", + "interrupted": true +} +``` + +- **`interrupted: false`** — 助手正常说完本轮内容(文本流与 TTS 自然结束)。 +- **`interrupted: true`** — 本轮被打断,`text` 只包含**已流式输出、尚未说完**的部分,不是完整原定回复。 + +以下情况会置 `interrupted` 为 `true`,并停止当前 TTS: + +1. **文本打断** — 发送 `input.text` 且 `interrupt` 为 `true`(默认值)。 +2. **主动取消** — 发送 `response.cancel`。 +3. **语音插话(barge-in)** — 助手正在说话时,用户开口且满足打断条件:转写文本达到最短字数门槛,或命中常见短答词(如「是的」「行」「可以」)。过短的背景噪声通常不会触发打断。 + +客户端可用 `interrupted` 区分「完整回复」与「说到一半被截断」,例如在 UI 上对未说完的气泡做标记。 + +## 浏览器示例 + +引擎可在 `config.json` 中开启内置演示页: + +```json +"server": { + "serve_webpage": true, + "webpage_mount": "/demo" +} +``` + +启动服务后访问 `http://localhost:8000/demo/`,默认连接同源的 `/ws-product`。参考实现见 `examples/webpage/`。