Files
engine-v5-pipecat-core/docs/product-ws.md
2026-05-26 14:37:21 +08:00

5.1 KiB
Raw Blame History

Product WebSocket 使用说明

Product WebSocket/ws-product)面向浏览器、移动端等产品客户端,使用稳定的 JSON/base64 协议 va.ws.v1

连接地址

ws://<host>:<port>/ws-product

生产环境请使用 wss://。可通过 GET /health 查看当前支持的协议与能力。

音频参数

参数 默认值
编码 PCM signed 16-bit little-endianpcm_s16le
采样率 16000 Hz
声道 1单声道

基本流程

  1. 建立 WebSocket 连接
  2. 发送 session.start 握手
  3. 持续发送音频或文本输入
  4. 接收服务端事件转写、回复文本、TTS 音频等)
  5. 结束时发送 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 字节,延迟和带宽更优。字段 audiodata 均可作为 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/jpegimage/pngimage/webp
widthheight 必填,图片像素尺寸,必须为正整数
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包含 typeprotocolva.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.finalinterrupted

每轮助手回复结束时都会发送一条 response.text.final

{
  "type": "response.text.final",
  "text": "今天北京天气晴朗,",
  "interrupted": true
}
  • interrupted: false — 助手正常说完本轮内容(文本流与 TTS 自然结束)。
  • interrupted: true — 本轮被打断,text 只包含已流式输出、尚未说完的部分,不是完整原定回复。

以下情况会置 interruptedtrue,并停止当前 TTS

  1. 文本打断 — 发送 input.textinterrupttrue(默认值)。
  2. 主动取消 — 发送 response.cancel
  3. 语音插话barge-in — 助手正在说话时,用户开口且满足打断条件:转写文本达到最短字数门槛,或命中常见短答词(如「是的」「行」「可以」)。过短的背景噪声通常不会触发打断。

客户端可用 interrupted 区分「完整回复」与「说到一半被截断」,例如在 UI 上对未说完的气泡做标记。

浏览器示例

引擎可在 config.json 中开启内置演示页:

"server": {
  "serve_webpage": true,
  "webpage_mount": "/voice-demo"
}

启动服务后访问 http://localhost:8000/voice-demo/,默认连接同源的 /ws-product。参考实现见 examples/webpage/