Files
engine-v5-pipecat-core/docs/product-ws.md
2026-05-28 09:36:44 +08:00

5.2 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.state 可选;当 agent.response_state.enabled 开启且 LLM 回复以 <state>...</state> 开头时发送
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/