Skip to Content

Events

事件载荷何时触发
connection_established—已加入会话。
video_play_started—数字人的画面开始在元素里播放。
message{ id, role, content, final, typed? }一条字幕(角色会话),或用户打的字(typed: true)。
session_ended{ reason?, startWait? }会话结束了:你离开了、角色结束了通话、到了时长上限或沉默上限,或者连接断了。只触发一次。streamToVideoElement reject 时不触发:那个 reject 就是回答。startWait 表示它是在等渲染器时结束的:"cancelled"(用户选了「稍后再打」)或 "timed_out"。
call_ending{ secondsLeft, reason }通话将在 secondsLeft 秒后结束:到了最长时长(reason: "max_duration"),或你账户的余额用完("quota_exceeded");以后可能有更多原因。倒计时开始时触发一次。见 The call’s last seconds。
start_waiting{ waitedSeconds, final }数字人还没出现,通话在等渲染器:第一次提示时触发,之后每次询问用户时再触发。final: true——到了最长等待时间,SDK 挂断(随后触发 session_ended)。见 Waiting for a renderer。
tool_call_started{ toolCallId, toolName, toolType, toolSubtype?, arguments, timestamp }模型调用了一个工具——任何类型,见下文。
tool_call_completed{ toolCallId, toolName, toolType, toolSubtype?, result, executionTime, documentsAccessed?, timestamp }调用完成。executionTime 单位为毫秒。
tool_call_failed{ toolCallId, toolName, toolType, toolSubtype?, errorMessage, executionTime, timestamp }调用失败。

字幕。 role 是 "user"(用户说的)或 "persona"(角色说的)。用户的话边识别边到:同一个 id 反复出现, content 越来越长,final: true 表示最后一版——按 id 替换,不要追加。一个 id 是用户的一轮话:中间的停顿不会另起一行, 用户说完、轮到角色时才出现 final: true。角色的话也一样,随数字人说出而到——绝不会比声音早:每次回答一个 id, content 越来越长,回答说完时 final: true(如果用户插话打断,就是到那时为止说出的内容)。角色的 content 是纯粹的口语: 它的模型知道自己在语音通话里,所以不会写「(微笑)」之类的舞台说明,也没有 Markdown 和 emoji。

const lines = new Map(); client.on("message", (m) => { lines.set(m.id, m); render([...lines.values()]); });

工具调用。 角色调用的每个工具都会触发这三个 tool_call_* 事件:toolType 是 "client" 时,是你的页面执行的 客户端工具;是 "server" 时,是 AvatarGo 替你执行的工具,toolSubtype 为 "webhook"、 "knowledge" 或 "system"(end_call 之类)。toolCallId 把一次调用的 started 和它的 completed 或 failed 对应起来。 知识库检索的 arguments 是 { query },用的是你的文档的语言和措辞,不一定是用户的;它的 completed 会说明检索到的段落来自哪些文档 (documentsAccessed)。记一份日志:

client.on("tool_call_started", (e) => console.log("▸", e.toolName, e.toolSubtype ?? e.toolType, e.arguments)); client.on("tool_call_completed", (e) => console.log("✓", e.toolName, `${e.executionTime} ms`, e.result)); client.on("tool_call_failed", (e) => console.log("✗", e.toolName, e.errorMessage));

设为不等回复的 webhook,请求一发出就算完成(result: "Request sent.");之后请求结果如何不会告知。webhook 返回的内容会出现在 result 里,到达页面,所以用户的浏览器看得到。让你的接口只返回用户可以看的内容。

会话为什么结束。 session_ended 的 reason 是 LiveKit 的 DisconnectReason(连接给出了原因时才有)——足以分辨是网络断了还是正常结束。 要知道完整原因(end_call、idle_timeout、max_duration 等),由你的服务器从 GET /v1/sessions/{id} 读 endReason。