使用已有 Conversation 建立 WebSocket 连接,进行实时语音、文本交互和后台任务事件传输。
Realtime 目前为 Beta 功能,接口定义、事件结构和行为可能发生变化。请关注文档更新,并在生产环境使用前完成兼容性验证。
GET /api/v1/forward/realtime
单个 Realtime 连接的最长持续时间为 60 分钟。
请求头
| Header | 是否必填 | 说明 |
|---|---|---|
| Authorization | 是 | Bearer <PAT 或 SAT> |
| Upgrade | 是 | websocket,由 WebSocket 客户端生成。 |
| Connection | 是 | Upgrade,由 WebSocket 客户端生成。 |
查询参数
| 参数 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
| conversation_id | string | 是 | 当前凭据可访问、状态为 ready 的 Conversation ID。 |
示例请求
wss://api.qoder.com.cn/api/v1/forward/realtime?conversation_id=conv_xxx
示例响应
HTTP 101 Switching Protocols
WebSocket 连接就绪后,服务端发送 voice.ready:
voice.ready.payload 字段
事件公共字段见实时事件。
| 字段 | 类型 | 说明 |
|---|---|---|
| config | object | 当前连接生效的 Conversation 配置。 |
| config.audio.output.voice | string | 当前连接生效的音色标识。 |
| provider | string | 服务提供方,公开环境固定为 qoder。 |
| input_audio | object | audio.append 使用的音频格式。 |
| input_audio.format | string | 固定为 pcm16:裸 PCM、小端有符号 16 位,不含 WAV 文件头。 |
| input_audio.sample_rate | integer | 固定为 16000,单位 Hz。 |
| input_audio.channels | integer | 固定为 1,单声道。 |
| output_audio | object | audio.delta 使用的音频格式。 |
| output_audio.format | string | 固定为 pcm16,编码与输入音频相同。 |
| output_audio.sample_rate | integer | 固定为 24000,单位 Hz。 |
| output_audio.channels | integer | 固定为 1,单声道。 |
| capabilities | object | 当前连接支持的协议能力。 |
| capabilities.graceful_close | boolean | 是否支持正常关闭协议,当前为 true。 |
错误
握手完成前返回 HTTP 错误:
| HTTP | Code | 触发条件 |
|---|---|---|
| 400 | conversation_id_required、unsupported_query_parameter | WSS Query 参数缺失或不受支持。 |
| 401 | authentication_required、入口层 TOKEN_INVALID | PAT 或 SAT 无效、已过期,或直接使用了 Service Account Key。 |
| 403 | permission_error | SAT 未绑定可用的 Workspace。 |
| 404 | conversation_not_found | Conversation 不存在,或当前凭据无权访问其所属用户、Workspace 或 Identity。 |
| 409 | conversation_not_ready | 会话未就绪。 |
| 500 | conversation_persistence_error | 服务内部错误。 |
| 502 | forward_unavailable、forward_protocol_error | 依赖服务异常。 |
| 503 | gateway_unavailable | 服务暂不可用。 |
error 事件返回,见 WebSocket 错误。
实时事件
事件通过 UTF-8 JSON 文本消息传输,不接受二进制消息。客户端单条消息上限为 256 KiB(含 JSON 和 Base64);收到 voice.ready 后才能发送音频或文本。
公共字段
| 字段 | 类型 | 说明 |
|---|---|---|
| version | string | 双向必填,固定为 voice.realtime.v1。 |
| type | string | 双向必填,事件类型。 |
| payload | object | 双向必填,事件数据;无业务字段时为 {}。 |
| event_id | string | 服务端必返,本次 WSS 投递 ID,不是历史事件 ID。客户端不传该字段。 |
| sequence | integer | 服务端必返,当前连接内递增,重连后重置,不作为续传游标。 |
| conversation_id | string | 服务端必返,所属 Conversation。 |
| timestamp | string | 服务端必返,RFC 3339 时间,可含纳秒精度小数。 |
| work_id | string | 服务端可选,所属任务。 |
| announcement_id | string | 服务端可选,所属播报。 |
客户端事件
| type | payload 字段 | 说明 |
|---|---|---|
audio.append | audio: string | 分块发送非空 Base64 PCM16,编码见 voice.ready.payload.input_audio。服务端检测语音活动,无需提交事件。 |
text.message | text: string | 去除首尾空白后非空,UTF-8 最多 16 KiB。 |
interrupt | 无 | 打断当前响应;客户端停止播放并清空队列。 |
playback.started | work_id: string、announcement_id: string;对应音频事件携带时必填。 | 实际开始播放。原样回传对应音频事件顶层标识;无标识时传 {}。 |
playback.ended | work_id: string、announcement_id: string;对应音频事件携带时必填。 | 当前音频段播放完毕、队列排空。 |
playback.cancelled | work_id: string、announcement_id: string;对应音频事件携带时必填。 | 无法播放或取消播放。打断时停止播放、清空队列,并按原音频标识发送此回执。 |
ping | 无 | 探活,响应为 pong。 |
connection.close | request_id: string | 停止采集与播放后发送,等待同一 request_id 的 connection.closed。标识非空、最多 128 字节,无首尾空白、换行或空字符。 |
服务端事件
事件结构示例见示例响应。
| type | payload 字段 | 说明 |
|---|---|---|
voice.state | state: string | connecting、ready、idle、interrupted。 |
voice.ready | config: object、provider: string、input_audio: object、output_audio: object、capabilities: object | 连接就绪,返回最终生效的 Conversation 配置和音频传输格式。 |
voice.replaced | reason: string | 连接被替换。 |
transcript.delta | role: string、text: string;可选 item_id: string、response_id: string | 用户识别文本更新或助手字幕增量。 |
transcript.final | 同上 | 最终字幕,覆盖临时字幕。 |
audio.delta | audio: string | Base64 PCM16 音频,编码见 voice.ready.payload.output_audio。 |
audio.done | 无 | 当前音频段输出结束,不代表客户端播放完毕。 |
playback.interrupt | reason: string | 停止播放并清空队列。 |
work.accepted | status: "accepted"、objective: string | 任务已接受。 |
work.running | status: "running" | 任务执行中。 |
work.progress | kind: string、detail: string;可选 title: string、is_error: boolean、event_id: string | 任务进度。payload 中的 event_id 是 Forward 持久化事件 ID。 |
work.milestone | announcement_id: string、milestone_type: string、summary: string | 任务阶段信息。 |
work.completed | status: "completed"、result: string;可选 event_id: string | 任务完成,播报可能尚未结束。payload 中的 event_id 是 Forward 持久化事件 ID。 |
work.failed | status: "failed"、error.code: string;可选 event_id: string | 任务失败或取消,与连接状态独立。payload 中的 event_id 是 Forward 持久化事件 ID。 |
pong | 无 | ping 的响应。 |
connection.closed | request_id: string、outcome: string | 关闭确认,返回原 request_id。outcome 为 no_active_response、no_content、saved 或 saved_interrupted。 |
error | code: string、message: string;可选 retryable: boolean、retry_after_ms: integer | 协议或服务错误。 |
WebSocket 错误
| Code | 是否结束连接 | 触发条件 |
|---|---|---|
invalid_event、text_too_long | 否 | 事件无效或文本超限。 |
voice_not_ready | 否 | 实时连接尚未就绪。 |
invalid_playback_receipt | 否 | 播放回执无效。 |
connection_closing | 否 | 正在关闭,不再接受业务事件。 |
invalid_work_request、work_busy、work_unavailable、work_persistence_error、forward_request_failed、forward_cancel_failed、forward_protocol_error | 否 | 任务请求或执行异常。 |
provider_initialization_failed、voice_configuration_failed、context_restore_failed | 是 | 实时模型初始化、音色确认或上下文恢复失败。 |
provider_unavailable、service_restarting | 是 | 服务不可用;重连间隔见 retry_after_ms(如有)。 |
event_persistence_failed | 是 | 事件保存失败,最后一条历史可能缺失。 |
HTTP 错误响应
响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
| type | string | 固定为 error。 |
| request_id | string | 请求追踪 ID。 |
| error.type | string | 错误大类,例如 invalid_request_error、authentication_error、permission_error、not_found_error、conflict_error、api_error。 |
| error.code | string | 稳定的业务错误码。 |
| error.message | string | 错误描述。 |

