5.1 KiB
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(单声道) |
基本流程
- 建立 WebSocket 连接
- 发送
session.start握手 - 持续发送音频或文本输入
- 接收服务端事件(转写、回复文本、TTS 音频等)
- 结束时发送
session.stop
1. 启动会话
{
"type": "session.start",
"protocol": "va.ws.v1",
"audio": {
"encoding": "pcm_s16le",
"sample_rate": 16000,
"channels": 1
}
}
2. 发送音频
JSON + base64(便于调试):
{
"type": "input.audio",
"audio": "<base64 编码的 pcm_s16le 数据>",
"sample_rate": 16000,
"channels": 1
}
二进制帧:也可直接发送原始 PCM16 字节,延迟和带宽更优。字段 audio 与 data 均可作为 base64 字段名。
建议按约 20 ms 一帧分片发送(16 kHz 单声道下每帧约 640 字节)。
3. 发送文本(可选)
{
"type": "input.text",
"text": "你好",
"interrupt": true
}
interrupt 默认为 true,会打断当前正在播放的 bot 语音。
4. 发送摄像头图片(可选)
客户端可发送一帧摄像头截图,让 LLM 基于图片内容回复。服务端会把图片追加到 Pipecat LLM context,并立即触发一次 LLM 推理;后续回复仍通过现有的 response.text.* 与 response.audio.* 事件返回。
{
"type": "input.image",
"image": "<base64 编码的 JPEG/PNG/WebP 图片字节>",
"mime_type": "image/jpeg",
"width": 640,
"height": 360,
"text": "请根据这张摄像头画面回答用户的问题。",
"user_id": "product-user",
"append_to_context": true
}
字段说明:
| 字段 | 说明 |
|---|---|
image / data |
必填,图片字节的 base64;也兼容 data:image/...;base64,... data URL |
mime_type / media_type |
可选,默认 image/jpeg;支持 image/jpeg、image/png、image/webp |
width、height |
必填,图片像素尺寸,必须为正整数 |
text |
可选,随图片一起进入 LLM 的问题/提示词 |
user_id |
可选,默认 product-user |
append_to_context |
可选,默认 true;为 true 时图片会进入 LLM context 并触发回复 |
建议发送压缩后的截图而不是持续视频流,例如 640px 宽、JPEG quality 0.75 左右。单张图片最大 8 MB。
5. 取消当前回复
{"type": "response.cancel"}
6. 结束会话
{"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 播放结束 |
音频事件示例:
{
"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:
{
"type": "response.text.final",
"text": "今天北京天气晴朗,",
"interrupted": true
}
interrupted: false— 助手正常说完本轮内容(文本流与 TTS 自然结束)。interrupted: true— 本轮被打断,text只包含已流式输出、尚未说完的部分,不是完整原定回复。
以下情况会置 interrupted 为 true,并停止当前 TTS:
- 文本打断 — 发送
input.text且interrupt为true(默认值)。 - 主动取消 — 发送
response.cancel。 - 语音插话(barge-in) — 助手正在说话时,用户开口且满足打断条件:转写文本达到最短字数门槛,或命中常见短答词(如「是的」「行」「可以」)。过短的背景噪声通常不会触发打断。
客户端可用 interrupted 区分「完整回复」与「说到一半被截断」,例如在 UI 上对未说完的气泡做标记。
浏览器示例
引擎可在 config.json 中开启内置演示页:
"server": {
"serve_webpage": true,
"webpage_mount": "/voice-demo"
}
启动服务后访问 http://localhost:8000/voice-demo/,默认连接同源的 /ws-product。参考实现见 examples/webpage/。