事件协议
TiRTC AI 对讲在命令通道上传输控制事件。所有事件均使用 JSON-RPC 2.0,payload 为 UTF-8 JSON,TiRTC 命令字为:
#define TIRTC_AI_SIGNALING 0x2100提示
此命令字 0x2100 属于 TiRTC 开发者应用层保留范围(0x2000 ~ 0xffff),并非 SDK 内部预留。你可以根据自己项目的实际情况更改该值,只需确保设备端和业务服务端协商一致,且不与 TiRTC 内部保留命令(小于 0x2000)冲突即可。
协议基础
JSON-RPC 消息分为两类:
| 类型 | 特征 | 说明 |
|---|---|---|
| Request | 带 id 字段 | 发送方需要接收方返回成功或失败响应,例如 start_session。 |
| Notification | 不带 id 字段 | 单向通知,不要求响应,例如 caption 或 interrupt。 |
id 使用字符串。平台返回的 JSON-RPC 响应不带 method,设备端应使用响应中的 id 匹配原始请求。
通用 Request 结构:
{
"jsonrpc": "2.0",
"id": "req-001",
"method": "start_session",
"params": {}
}通用成功响应:
{
"jsonrpc": "2.0",
"id": "req-001",
"result": {}
}通用失败响应:
{
"jsonrpc": "2.0",
"id": "req-001",
"error": {
"code": -32602,
"message": "Invalid params"
}
}事件总览
| method | 方向 | 类型 | 说明 |
|---|---|---|---|
start_session | 设备 -> 平台 | Request | 建连后启动 AI 对讲会话。 |
caption | 平台 -> 设备 | Notification | 下发 ASR / TTS 字幕。 |
round_start | 平台 -> 设备 | Notification | 一轮回复音频开始。 |
round_end | 平台 -> 设备 | Notification | 一轮回复音频结束。 |
interrupt | 设备 -> 平台 | Notification | 主动打断当前回复。 |
submit_speech | 设备 -> 平台 | Notification | 手动提交当前上行语音。 |
update_config | 设备 -> 平台 | Request | 运行时更新会话配置,目前仅支持 extra_params。 |
device_action | 平台 -> 设备 | Request | 平台请求设备执行声明过的设备能力。 |
end_session | 双向 | Notification | 结束当前会话。 |
start_session
方向:设备 -> 探鸽平台
TiRTC 连接建立后,设备端必须先发送 start_session,用于创建本次 AI 对讲会话。探鸽平台收到后会加载设备和角色配置,并返回会话 ID 与实际使用的音频格式。
请求示例:
{
"jsonrpc": "2.0",
"id": "start-session-001",
"method": "start_session",
"params": {
"device_id": "DEMO_DEVICE_01",
"role_id": "role_xxx",
"input_audio": {
"codec": "opus",
"sample_rate": 16000,
"channels": 1
},
"output_audio": {
"codec": "opus",
"sample_rate": 16000,
"channels": 1
}
}
}params 字段:
| 字段 | 必填 | 说明 |
|---|---|---|
device_id | 是 | 设备 ID。 |
role_id | 是 | 角色 ID,来自探鸽平台角色配置或设备角色绑定查询。 |
input_audio | 否 | 设备上行音频格式;不传时使用平台默认值(通常为 pcm)。推荐显式传入,以确保两端理解一致,避免兼容性风险。 |
output_audio | 否 | 平台下行音频格式;不传时使用平台默认值(通常为 pcm)。推荐显式传入,以确保两端理解一致,避免兼容性风险。 |
input_audio 与 output_audio 均包含以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
codec | string | 音频编码格式。 |
sample_rate | int | 采样率(Hz)。 |
channels | int | 声道数。 |
支持的音频格式
| codec | 支持的采样率(Hz) | 支持的声道 |
|---|---|---|
opus | 16000 | 1 |
pcm | 16000、8000 | 1 |
g711a | 16000、8000 | 1 |
amr | 8000(NB)、16000(WB) | 1 |
说明:
- 平台内部 ASR / LLM / TTS Pipeline 固定为 16 kHz 单声道;与内部格式不一致的上行音频会在平台侧重采样。
- 会话实际使用的格式以
start_session成功响应中的input_audio和output_audio为准;设备端发送音频与解码下行音频时必须与响应一致。 - 传入不支持的 codec、采样率或声道组合时,平台返回 JSON-RPC error,
message为Invalid audio format。
成功响应:
{
"jsonrpc": "2.0",
"id": "start-session-001",
"result": {
"session_id": "aivoice-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"input_audio": {
"codec": "opus",
"sample_rate": 16000,
"channels": 1
},
"output_audio": {
"codec": "opus",
"sample_rate": 16000,
"channels": 1
}
}
}失败响应示例:
{
"jsonrpc": "2.0",
"id": "start-session-001",
"error": {
"code": -32602,
"message": "Invalid audio format"
}
}设备收到失败响应后,应停止本次会话启动流程,并释放采集、播放等本地资源。
caption
方向:探鸽平台 -> 设备
caption 用于下发字幕。字幕可能来自用户语音识别,也可能来自平台回复内容。
示例:
{
"jsonrpc": "2.0",
"method": "caption",
"params": {
"text": "你好,有什么可以帮您?",
"caption_type": 1,
"is_final": true,
"mode": 0,
"utterance_id": 1001,
"seq_num": 3,
"begin_time_ms": 120,
"end_time_ms": 1680
}
}params 字段:
| 字段 | 必有 | 说明 |
|---|---|---|
text | 是 | 字幕文本。 |
caption_type | 是 | 字幕来源:0 表示 ASR 用户字幕,1 表示 TTS 回复字幕。 |
is_final | 是 | 是否为该段话的最终字幕。 |
mode | 是 | 传输模式:0 表示全量文本,1 表示增量文本。 |
utterance_id | 是 | 话语 ID,同一段话的字幕共享同一个 ID。 |
seq_num | 是 | 序列号,用于同一段话内排序。 |
begin_time_ms | 否 | 字幕片段开始时间,单位毫秒;可能为空或为 0。 |
end_time_ms | 否 | 字幕片段结束时间,单位毫秒;可能为空或为 0。 |
合并建议:
- 使用
caption_type + utterance_id作为字幕分组键。 mode=1时,将text追加到当前分组。mode=0时,用text替换当前分组内容。is_final=true时,将当前分组标记为最终文本。
ASR 增量示例:
{
"jsonrpc": "2.0",
"method": "caption",
"params": {
"text": "帮我",
"caption_type": 0,
"is_final": false,
"mode": 1,
"utterance_id": 2001,
"seq_num": 1
}
}{
"jsonrpc": "2.0",
"method": "caption",
"params": {
"text": "帮我打开灯。",
"caption_type": 0,
"is_final": true,
"mode": 0,
"utterance_id": 2001,
"seq_num": 3
}
}round_start
方向:探鸽平台 -> 设备
round_start 表示一轮平台回复音频开始。设备端可用它切换 UI 状态,例如点亮“正在说话”灯效、打开播放状态、启用回声抑制策略等。
示例:
{
"jsonrpc": "2.0",
"method": "round_start"
}处理建议:
round_start与round_end通常成对出现。- 设备端不要仅依赖该事件决定是否播放音频,实际播放仍以音频流为准。
- 收到
round_start后,如果用户再次说话或按键打断,可发送interrupt。
round_end
方向:探鸽平台 -> 设备
round_end 表示一轮平台回复音频结束。设备端可用它恢复到等待用户输入状态,或清理本轮播放状态。
示例:
{
"jsonrpc": "2.0",
"method": "round_end"
}处理建议:
- 收到
round_end后,设备端可以恢复拾音提示、关闭“正在说话”灯效。 - 打断场景下,平台也会尽快下发
round_end,设备端应停止播放旧轮次缓冲。
interrupt
方向:设备 -> 探鸽平台
interrupt 用于主动打断当前回复。典型场景包括用户按键打断、唤醒词打断、业务逻辑要求立即停止当前播报等。
示例:
{
"jsonrpc": "2.0",
"method": "interrupt"
}处理建议:
- 发送后设备端应立即停止播放本地缓存中的旧回复音频。
- 平台收到后会停止当前输出,并通过后续事件和音频流进入新状态。
- 如果打断由用户语音触发,设备端也可以继续上行用户新一轮语音。
submit_speech
方向:设备 -> 探鸽平台
submit_speech 用于手动提交当前上行语音。典型场景包括按键松开发送、半双工对讲、UI 控件确认发送,或设备端本地 VAD 已判断用户说完一句话。
示例:
{
"jsonrpc": "2.0",
"method": "submit_speech"
}处理建议:
- 发送
submit_speech后,平台会把当前已收到的上行语音视为已提交,并推动后续 ASR / LLM / TTS 流程。 submit_speech不用于打断平台当前回复;如需停止正在播放或生成的回复,应发送interrupt。- 如果设备端只依赖平台云端 VAD 自动判断语音结束,通常不需要发送该事件。
update_config
方向:设备 -> 探鸽平台
update_config 用于在会话运行中更新少量动态上下文。当前仅支持 extra_params,常用于位置、业务状态等会随会话变化的信息。平台会把新的 extra_params 合并到当前会话,不会改写欢迎语、音色、系统提示词等静态配置。
请求示例:
{
"jsonrpc": "2.0",
"id": "update-config-001",
"method": "update_config",
"params": {
"extra_params": {
"latitude": 39.9800718,
"longitude": 116.309314
}
}
}成功响应:
{
"jsonrpc": "2.0",
"id": "update-config-001",
"result": {
"success": true,
"message": "更新配置成功"
}
}失败响应示例:
{
"jsonrpc": "2.0",
"id": "update-config-001",
"error": {
"code": -32602,
"message": "update_config only supports extra_params, got \"voice\""
}
}注意事项:
- 响应是 JSON-RPC response,不会返回
method: "config_updated"。 - 设备端应通过响应里的
id匹配update_config请求。 - 除
extra_params外的字段会被拒绝。
device_action
方向:探鸽平台 -> 设备
当角色配置中声明了设备能力,平台可能通过 device_action 请求设备执行动作。该消息是 JSON-RPC Request,设备必须保留 id 并在执行完成后返回同一个 id 的 response。
平台下发示例:
{
"jsonrpc": "2.0",
"id": "device-action-001",
"method": "device_action",
"params": {
"action": "set_light",
"data": {
"power": "on"
}
}
}设备执行成功响应:
{
"jsonrpc": "2.0",
"id": "device-action-001",
"result": {
"ok": true,
"data": {
"power": "on"
}
}
}设备执行失败响应:
{
"jsonrpc": "2.0",
"id": "device-action-001",
"error": {
"code": -32000,
"message": "device is busy"
}
}end_session
方向:双向
end_session 用于结束当前 AI 对讲会话。设备端主动结束、平台策略结束、用户语义触发结束时都可以使用该事件。
设备到平台示例:
{
"jsonrpc": "2.0",
"method": "end_session"
}平台到设备示例:
{
"jsonrpc": "2.0",
"method": "end_session"
}处理建议:
- 设备端收到或发送
end_session后,应停止采集、停止播放,并释放本地会话状态。 - 结束流程需要可幂等执行,避免重复事件导致崩溃或资源泄漏。
- 如果需要关闭 TiRTC 连接,可在本地资源释放后断开连接。
设备端接收示例
#include <stdint.h>
#include <string.h>
#include "tiRTC.h"
#define TIRTC_AI_SIGNALING 0x2100
static void on_command(tirtc_conn_t hconn, uint32_t cmdw,
const void *data, uint32_t len)
{
(void)hconn;
if (cmdw != TIRTC_AI_SIGNALING || data == NULL || len == 0) {
return;
}
/* data 是 UTF-8 JSON-RPC 字符串。
* 生产代码中请使用 JSON 库解析 method / params,
* 然后分发到 caption、round_start、round_end、interrupt、submit_speech、device_action、end_session 等处理函数。 */
}自检清单
- 命令字使用
0x2100。 - 所有 payload 均为合法 UTF-8 JSON。
start_session带id,并处理成功/失败响应。role_id必传且有效。- 已处理
caption的增量和全量模式。 - 已处理
round_start/round_end状态切换。 - 已实现
interrupt的本地立即停止播放逻辑。 - 如需手动提交语音,已实现
submit_speech的发送逻辑。 - 如需运行时更新配置,已按
id处理update_config的 JSON-RPC response。 - 如需设备能力调用,已按
id处理device_action请求和响应。 - 已实现
end_session的幂等清理逻辑。