在 React 产品里接入数字人,并不只是多挂载一个组件。真正有用的实现,应当让数字人承担清晰的职责;即使这块视觉界面暂时不可用,产品主流程也仍可继续;同时,原有的 Agent 和数据边界不会被改变。
在这套架构中,Spatius 是展示层:Spatius 开发者文档总览明确说明,它将数字人语音音频转换为实时动作数据,AvatarKit 再在客户端本地渲染数字人。Spatius 不会返回一段成品视频,也不会接管 ASR、LLM、TTS、产品数据、权限、工具调用、工作流决策、轮次管理或人工交接。这些职责仍由你的 SaaS 应用、Agent 框架或后端负责。在选 React 组件或传输方式之前,先确认这个边界。
核心结论
- 先选集成路径,再选 React 组件。AvatarKit UI 与 Direct Mode 对应的是不同的集成形态。
- 当你的体验采用其 LiveKit 会话接线方式时,可使用 AvatarKit UI;不要把它描述成 Direct Mode 的封装。
- 使用 Direct Mode 时,后端只需保留一个小型 Token 接口。客户端通过 AvatarKit 连接 Motion Server,发送数字人语音音频、接收动作数据,并在本地渲染。
- 将数字人放进边界清晰的 React 功能模块,明确展示加载、出错、重连和退出状态。没有数字人时,产品其他部分也应照常可用。
- 对话、权限、工具和产品操作的事实来源,始终应在你的应用中,而不是在数字人播放状态中。
先做集成决策,而不是先挑组件
React 是用户看到数字人的地方,但它本身并不能决定数字人该如何连接。首先要弄清楚:你的应用现在在哪里生成数字人要说的语音,以及谁拥有实时运行时。
| 你的产品已经具备… | 建议从…开始 | React 主要负责什么 | 不要误以为 |
|---|---|---|---|
| 基于 LiveKit Agents 的语音体验 | 已文档化的 LiveKit Agents 集成和 AvatarKit UI | 渲染数字人界面及其周边会话 UI | AvatarKit UI 不等于 Direct Mode;它封装的是 AvatarKit RTC 初始化和 LiveKit 会话接线。 |
| TTS 或其他数字人语音来源,并且希望采用较轻的客户端接入 | Direct Mode和 AvatarKit Web SDK 参考 | 本地渲染数字人,并使用 Session Token 建立连接 | Token 接口不是 Agent 运行时,也不是音频或动作数据的中转服务。 |
| 必须由后端掌握音频链路和向客户端的下游传输 | Backend Mode | 渲染后端传给客户端的内容 | 控制力更高,也意味着团队需自己负责传输、恢复和可观测性。 |
这一区分很重要,因为配置、凭证和故障处理都不同。Spatius 将 AvatarKit UI 文档定义为一个 React 组件包,它封装 AvatarKit RTC 设置和 LiveKit 会话接线。当你的产品确实使用这一会话模型时,它会很合适。Direct Mode 则是另一条独立路径:客户端的 AvatarKit 使用 Session Token 直接连接 Motion Server。
如果产品已经有语音音频,但数字人体验并不需要 LiveKit Room,不要只因某个 React 包看起来更方便,就额外加入一层运行时。反过来,如果产品已经在使用 LiveKit Agents,就应沿用那条已文档化的集成路径,而不是再并行搭建一条新的客户端到服务端链路。以 集成路径选择指南 的当前内容为准。
关于类似的实时 React 设计决策,Daily 关于自定义视频聊天应用、实时会话 React Hooks,以及在 app-message 与独立 WebSocket 间选择的文章,都是有价值的外部阅读材料。它们讲的是通用媒体应用模式,不是 Spatius 的集成契约。
将数字人放在 React 功能边界里,而不是全局应用外壳中
数字人通常服务于一个具体的产品时刻:引导完成入门任务、解释配置步骤、培训流程,或支持会话。因此应把它放在拥有这个用户时刻的路由或功能模块中,而不是让整个应用外壳永久依赖它。这也符合 React 关于将共享产品状态放在最近共同所有者、而非藏进展示型子组件的建议,可参考 Sharing State Between Components。
一个比较稳妥的组件层级可以是:
产品页面或工作流路由
├── 产品控制项与任务状态
├── 对话或 Agent 面板
│ ├── 对话记录 / 文字兜底
│ └── 用户操作与确认控件
└── 数字人体验边界
├── 连接与生命周期状态
├── 数字人画布或 AvatarKit UI 界面
├── 加载与连接状态
├── 重试 / 退出 / 切换交互方式的控件
└── 局部错误兜底
外层页面应拥有产品事实:用户处于哪个流程、某个操作是否允许、回复是否还在生成,以及用户是否选择关闭视觉化体验。数字人边界只负责客户端展示会话及其局部状态。
这种拆分能避免一个常见错误:把数字人的连接状态当成业务工作流状态。即使数字人还在加载或断开,用户依然应能阅读说明、确认变更,或进入支持流程。
同样的组件边界思路,也可参考 LogRocket 对 React Error Boundary 和 useEffect cleanup的说明,以及 Daily 对实时会话 React Hooks的介绍。它们适合帮助团队设计“视觉会话局部失败,而不是整页失败”的结构。
为画布建立明确的布局契约
AvatarKit UI 的画布必须位于一个宽度和高度都非零的容器中;Provider 会等到该容器可以被测量后,才开始加载数字人。AvatarKit UI 参考文档记录了这一尺寸要求。因此要在布局中明确预留空间,不要依赖可能塌陷的 flex 子项、隐藏 Tab,或没有最小高度的容器。
如果 React 应用带有服务端渲染路由,应把数字人视为浏览器端运行的功能,并在真实的客户端构建中验证 Web SDK 的配置。AvatarKit Web 使用 WebAssembly,因此构建工具必须正确提供 .wasm 资源,而不是将其内联到 JavaScript 中。当前的 Vite 与 Next.js 配置要求,请参阅 Toolchain Setup;Web SDK Quickstart则是先验证浏览器链路的最小官方路径。
MDN 的 WebAssembly 概览可作为浏览器运行时层面的外部参考;AvatarKit 的具体配置仍应以 Spatius Toolchain 文档为准。
更广义的浏览器渲染背景,可阅读 web.dev 关于渲染性能、客户端渲染与交互性,以及把工作移出主线程的文章。这些资料帮助团队思考响应式 React 界面,但不意味着它们会改变 AvatarKit 已文档化的安装要求。
将产品和 Agent 的职责留在数字人之外
数字人可以呈现语音,但不应在无形中获得对产品的控制权。
| 职责 | 建议的所有者 | 为什么应留在那里 |
|---|---|---|
| 用户登录和租户访问 | 你的 SaaS 应用 | 这是产品身份和授权模型的一部分。 |
| 知识、检索和 Agent 上下文 | Agent 或后端 | 这些规则决定回复可以使用什么信息。 |
| 工具调用和有实际后果的操作 | 应用或 Agent 工作流 | 应用应校验权限,并始终让用户保持控制。 |
| TTS 以及是否要说出某段话的决定 | Agent 技术栈或音频来源 | 由产品决定哪些已批准的文本变成数字人语音。 |
| 动作生成与本地数字人渲染 | Spatius 与 AvatarKit | Motion Server 接收数字人语音并返回动作数据;AvatarKit 在本地渲染。 |
| 人工交接、兜底和产品分析 | SaaS 应用 | 这些是产品决策,而不是动画行为。 |
对正在构建“AI Copilot”界面的 React 团队来说,这个边界尤其关键。不要让组件的 connected 状态等同于 Agent 可用、工具调用成功,或账号变更已经完成。请继续在你信任的状态管理和后端契约中维护这些事实。React 的状态管理指南在这里很有帮助:数字人可以视觉化地呈现产品事实,但不应成为它们的事实来源。
更多产品层面的边界说明,可阅读 如何把 AI 数字人接入现有的 SaaS AI Agent。
关于相邻的前端问题,Snyk 的 React 与 TypeScript 安全实践、Rollbar 的前端错误处理指南以及 Smashing Magazine 关于 React Error Boundary 与错误上报的文章,都是有用的第三方参考。它们共同强调:权限、敏感数据和产品结果应留在呈现组件之外。
按你实际选择的路径建立连接流
更稳妥的 React 实现,会在代码库中清晰地呈现连接路径,并确保服务端凭证始终留在服务端。
如果使用 AvatarKit UI 和 LiveKit 会话
AvatarKit UI 是面向 AvatarKit RTC 和 LiveKit 会话驱动的数字人界面的 React 包。它的 Provider 接收数字人标识和 LiveKit 连接信息,再向组件树提供数字人会话与生命周期状态。React UI 参考文档记录了可组合的画布、加载、错误和状态组件,因此产品可以构建一个受控的数字人面板,而不必从头实现这些展示层接线。
但这并不代表 React UI 变成了 Agent。你的 LiveKit Agents Worker 或其他已文档化的平台运行时,仍然负责实时 Agent 流程中属于它的部分。应用应通过适用于该运行时的方式签发或取得连接信息,再只将数字人界面所需的值传进去。不要把产品权限和 Agent 业务逻辑塞进 UI props。
当现有架构本来就在使用对应的 LiveKit 集成时,再选这条路径。LiveKit Agents 集成指南区分了这一平台路径与独立集成路径,而 AvatarKit UI 参考文档 说明了 Provider、状态、加载、错误和 Context 的当前行为。
在设计周边 React 界面时,Daily 对React 媒体组件的概览、其React Hooks 介绍以及自定义视频聊天示例都提供了有用的参考模式:把会话 UI 与产品其余部分分开。
如果在 React SaaS 应用中使用 Direct Mode
正如 Direct Mode 概览所述,Direct Mode 的后端要求很小,而且职责明确:
- React 客户端向你的后端请求 Session Token。
- 后端使用服务端保存的
SPATIUS_API_KEY调用 Console API,获得该 Token。 - 客户端使用 Session Token,通过 AvatarKit 直接连接 Motion Server。
- 你的应用提供数字人语音音频;AvatarKit 将其发送给 Motion Server,接收动作数据,并在本地渲染数字人。
API Key 不应该出现在浏览器打包产物、浏览器存储或客户端环境变量中。Credentials 指南区分了服务端 API Key 和面向客户端连接的 Session Token。Direct Mode 中,Token 接口不代理 Motion Server 连接、不发送语音音频、不接收动作数据,也不运行 ASR、LLM 或 TTS;它只负责签发客户端凭证。当前要求请以 Direct Mode 概览、Session Token API 和 Session Token 认证流程 为准。
这样 React 的职责就很清晰:当用户进入相关体验时请求凭证,初始化客户端数字人会话,并在用户退出时清理它。原有服务继续产生语音音频并运行 Agent。
关于这类模式中浏览器安全与清理的通用部分,可参考 Auth0 对 Backend for Frontend的介绍、LogRocket 的 useEffect cleanup说明,以及 Snyk 的 React 安全实践。这些只是背景资料,Direct Mode 的凭证行为仍由 Spatius 文档定义。
将“开口说话”视为应用事件
关键的交接点,不是“用户点击了数字人”,而是产品决定某一段回复应该被说出来的时刻。Spatius 音频指南提供了一个重要背景:输入是“数字人要说的语音音频”,它不是产品麦克风、ASR 或对话策略的替代品。
在将语音交给数字人展示层之前,应用应已完成以下判断:
- 这段回复是否适合在当前产品情境中被朗读;
- 当前用户是否有权获得其中的信息;
- 回复中是否包含需要明确确认的请求、产品操作或人工交接;
- 如果视觉界面不可用,应该提供什么文本与非数字人兜底。
在 Direct Mode 流程中,客户端 AvatarKit 连接将最终的数字人语音发送给 Motion Server,Direct Mode Web 指南是对应的客户端路径。在 LiveKit Agents 流程中,应使用已文档化的 LiveKit Agents 客户端集成,而不是尝试在 UI 里模拟 Direct Mode。无论使用哪条路径,Spatius 都位于“决定是否说话”之后:它不会决定 Agent 说什么,也不会决定用户可以做什么。
这也是为什么重要说明或确认不能只存在于动画语音中。对话记录、操作控件和任务结果仍应保留在正常的 React UI 中。这样即使用户静音、数字人仍在加载,或更偏好另一种交互方式,流程也依然清晰。
关于更通用的实时 UI 取舍,可以对照 Daily 关于 data channel 与独立 WebSocket的讨论、其媒体应用浏览器性能建议,以及 web.dev 的主线程外工作指南。它们可帮助规划周边应用,而不是 Spatius 传输功能的证明。
将生命周期、加载和错误设计为产品状态
数字人界面是异步的客户端功能。在设计第一帧视觉效果之前,先规划状态转移。Spatius 的客户端生命周期记录了底层阶段;React 仍需要让用户能理解每个阶段对应的产品状态。
| 状态 | 用户应看到什么 | React 功能应做什么 |
|---|---|---|
| 尚未请求 | 正常任务 UI;若数字人是可选功能,提供明确的启动入口 | 不要无必要地创建数字人会话。 |
| 初始化或连接中 | 简洁的加载提示,说明正在准备什么;对话记录和产品控件仍可使用 | 预留画布空间,并防止重复连接。 |
| 已连接 | 数字人、简单的连接状态提示,以及清晰的用户控制项 | 业务操作仍放在周边的产品 UI 中。 |
| 数字人出错 | 局部错误面板,提供重试和替代路径,例如文字或常规支持 UI | 记录不敏感的诊断事件;不要让页面崩溃或阻断工作流。 |
| 已断开或用户退出 | 平稳回到正常产品状态 | 断开或清理客户端会话,再让下一次进入成为明确选择。 |
使用 AvatarKit UI 时,可使用其提供的加载、错误和状态组件,或其当前文档中的状态与回调,让这些转换对用户可见。React Error Boundary 可以保护页面不被数字人子树的渲染失败拖垮,但它不能替代运行时连接处理。用户退出或组件卸载时清理客户端会话,可参考 React 的 Effect 生命周期指南。初始化、连接、重连和麦克风发布失败,都属于异步状态,应在数字人边界内被明确处理。
Client Lifecycle 指南、Client State & Events 参考 与 AvatarKit UI 参考文档 说明了当前已文档化的生命周期、状态回调和可用 UI 行为。对于任何导致视觉体验无法启动的情况,产品还应准备独立的兜底。
对应的通用前端实践,可参考 LogRocket 的 Error Boundary 指南、Smashing Magazine 的错误上报模式、Rollbar 的前端错误处理文章以及 Daily 关于实时媒体性能的建议。用它们来塑造数字人周围的可观测性与兜底,而不要把所有失败都归为同一个泛化错误。
在排查对话前,先验证浏览器构建
数字人没有显示时,团队常常先检查 Prompt、Agent 或 TTS。但对 React Web 集成而言,应先检查浏览器端界面与所选路径。Web SDK Quickstart可以先提供一个较小、已知可用的 Direct Mode 基线,再去排查更大的应用。
| 检查项 | 为什么重要 |
|---|---|
| 是否使用了正确的集成路径 | LiveKit 驱动的 UI 设置与 Direct Mode 的连接模型不同。 |
| 数字人容器是否有可测量的宽度和高度 | AvatarKit UI 会等待可测量的画布容器后才加载。 |
| WebAssembly 请求是否成功 | AvatarKit Web 要求 .wasm 作为外部资源,以正确的 MIME 类型提供。 |
| 只有 Direct Mode 所需的客户端在使用 Session Token | 服务端 API Key 必须留在后端。 |
| 应用是否有清晰的非数字人兜底 | 不能因为展示层不可用,就让产品任务消失。 |
| 日志是否区分了产品失败与数字人会话失败 | 工具调用失败、对话记录缺失和数字人断开,需要不同的所有者和修复方式。 |
应在接近生产的构建中完成这些验证,而不只是在本地热更新会话中测试。Web SDK Toolchain Setup 明确指出,.wasm 请求失败或 MIME 类型错误,是初始化失败的常见原因。如果 SDK 报告客户端问题,应先按照已文档化的客户端错误与恢复指南定位,再判断它是否真的是产品或 Agent 层的故障。
若要从浏览器运行时角度做更广泛的检查,可参考 web.dev 的 Rendering on the Web、其关于客户端渲染取舍的文章,以及 Daily 的 React 实时应用实战。它们能帮助团队围绕真实浏览器界面测试,而不仅盯着服务端 Agent。
一份聚焦的实现清单
- 先选路径。 确认该功能应使用 Direct Mode、已文档化的 LiveKit Agents 集成,还是 Backend Mode。
- 定义功能边界。 将数字人放在拥有该用户时刻的路由或产品模块中。
- 将密钥留在服务端。 对 Direct Mode,创建由后端签发 Session Token 的接口;不要向客户端暴露
SPATIUS_API_KEY。 - 预留真实画布区域。 在初始化前,为数字人容器提供可测量的宽度和高度。
- 等用户时刻就绪后再连接。 不要只因全局应用外壳挂载就初始化会话。
- 让对话记录和任务控件独立存在。 即使没有数字人,用户也应能理解、继续、退出或获得帮助。
- 在局部处理加载与错误。 使用可见状态、重试和替代交互方式,不要留下空白画布或整页报错。
- 验证生产构建。 在真实环境中检查 WebAssembly 资源、凭证、生命周期行为和产品兜底。
作为最后一次交叉检查,web.dev 关于主线程渲染性能的指导、Daily 的实时浏览器性能建议以及 LogRocket 关于Effect cleanup的文章,都提醒我们应将此功能测试为一个长期运行的客户端会话,而不是静态组件。
常见问题
可以把 AvatarKit UI 用在 Direct Mode 吗?
不要将它当作 Direct Mode 的封装。AvatarKit UI 的文档说明它是一个封装 AvatarKit RTC 设置和 LiveKit 会话接线的 React 包。Direct Mode 则是另一条路径:客户端 AvatarKit 使用 Session Token 直接连接 Motion Server。应先选择符合运行时的路径,再遵循其当前文档。
在 React 中加入数字人,就等于给产品加入了一个 AI Agent 吗?
不是。开发者文档总览说明,Spatius 将数字人语音转换为动作数据,AvatarKit 在客户端本地渲染数字人。ASR、LLM、TTS、上下文、检索、权限、工具调用、工作流、轮次管理和人工交接,仍由你的应用、Agent 框架或后端负责。
Direct Mode 的 Session Token 应该在哪里生成?
应由你的后端使用服务端 API Key,通过已文档化的 Session Token API 流程获取。React 客户端向后端请求 Session Token,再用它建立与 Motion Server 的连接。不要将 API Key 打包进浏览器。
为什么页面能正常使用,但数字人是空白或一直加载?
数字人是独立的客户端界面,拥有自己的画布、WebAssembly 资源、连接状态和运行时错误路径。先检查画布尺寸、浏览器中 .wasm 的响应,以及当前选择的集成路径,再去改动 Agent 逻辑。周边产品 UI 应在这块界面恢复期间保持可用。
让数字人成为有用的产品界面,而不是产品控制平面
好的 React 集成,会让数字人在一个明确的任务中显得自然,同时保持原有产品架构不变:选对路径,把展示会话隔离在清晰的组件边界中,并让应用继续拥有智能、数据和工作流决策权。
如果团队正在优化更广泛的 UI 架构,Daily 的 React 媒体组件模式、Rollbar 的前端错误处理指导和 Snyk 的 React 安全实践都可以作为本文产品专属资料之外的相关阅读。
如果需要进一步规划试点与恢复路径,可继续阅读如何在 SaaS 产品中试点 AI 数字人和如何处理 AI 数字人体验中的等待、错误与人工交接。
如果你正在评估如何把实时数字人接入现有 SaaS 体验,预约演示。
参考资料
- Spatius 开发者文档总览
- 选择集成路径
- Direct Mode 集成
- 面向 React 的 AvatarKit UI
- AvatarKit Web Toolchain Setup
- Session Token 认证流程
- Client Lifecycle
- MDN WebAssembly 概览
- React Error Boundary 参考