# 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/`。