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 <cursoragent@cursor.com>
This commit is contained in:
Xin Wang
2026-05-22 15:10:15 +08:00
parent f73fadcc77
commit 7267c06552

147
docs/product-ws.md Normal file
View File

@@ -0,0 +1,147 @@
# Product WebSocket 使用说明
Product WebSocket`/ws-product`)面向浏览器、移动端等产品客户端,使用稳定的 JSON/base64 协议 `va.ws.v1`
## 连接地址
```
ws://<host>:<port>/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": "<base64 编码的 pcm_s16le 数据>",
"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": "<base64>",
"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/`