Skip to content

perf: Prewarm LiveAvatar browser sessions - #16

Merged
lanyue-llk merged 22 commits into
lex-mainfrom
perf/liveavatar-session-prewarm-20260713
Jul 29, 2026
Merged

perf: Prewarm LiveAvatar browser sessions#16
lanyue-llk merged 22 commits into
lex-mainfrom
perf/liveavatar-session-prewarm-20260713

Conversation

@jiejuncai-ly

@jiejuncai-ly jiejuncai-ly commented Jul 14, 2026

Copy link
Copy Markdown

Goal

在 Sandbox 用户点击 Start 前完成 LiveKit Room、Agent session、room_audio_inputroom_video_input 预热,并让 Start 复用已建立的 Session,缩短首屏视频与人脸检测等待。

本 PR 与 lex-voice#226 配套。

Design

Server prewarm

  • 新增 POST /api/session/prewarm,使用 Gateway 注入的单 Sandbox、一次性 secret 授权。
  • readiness 必须同时满足 agentSessionReadyroom_audio_inputroom_video_input;不要求浏览器视频首帧已发布。
  • prewarm 在执行中或成功后不可重复消费;失败释放 guard,Gateway 对失败或不确定响应执行 fail-closed 回收。
  • 端点只在 LIVEAVATAR_RUNTIME_MODE=sandbox 下存在,非 Sandbox 返回 404。

Browser Start

  • 只有存在 sandboxId 时,本地媒体与 dispatch 并行启动并复用 prewarm Session。
  • 本地 browser/xunfei 场景保留原串行行为,不受 prewarm 优化影响。
  • 只有浏览器获得有效视频帧后,后端才发布 room_video,避免绿色或无效首帧。

Paths and timeout

  • 同一 build 支持本地根路径、Gateway /s/<slug> 和 CubeSandbox /proxy/4003/ 前缀。
  • Next.js 直接监听 0.0.0.0:4003,同时提供 UI 和 prewarm API;不依赖 ui_proxy4103
  • prewarm 总预算 45s,Agent worker readiness 上限 30s;Gateway 外层默认预算必须大于该总预算并保留网络余量。
  • 失败响应只返回安全的 phase/timings,不泄露 secret 或内部错误对象。

Validation

GitHub Actions 的 tests、lint、format check 和 Next production build 均通过;测试覆盖 Sandbox/非 Sandbox 分支、一次性授权、readiness、超时取消、路径前缀和失败清理。

Internal Gateway 的基础 create、claim、RTC、release 和 Room cleanup 链路已经完成 HIL。本 PR 的 prewarm 延迟目标仍需在前后端合并、正式 Internal template 重建后,按 prewarm -> Start -> 首帧 -> 人脸检测 -> release -> 再次分配 完成最终 HIL;CI 通过不替代该验收。

Rollout

本次只构建和验证 Internal Sandbox template。Online 继续作为后续客户目标,但原 HK Sandbox 已撤下;新的非 HK Online Sandbox 接入并通过 HIL 后,再把本 PR 的前端产物纳入 Online template。

  1. 合并本 PR 与 lex-voice chore(deps): update dependency eslint-plugin-prettier to v5.5.4 livekit-examples/agent-starter-react#226
  2. 构建 Internal template,暴露 499994003
  3. 更新 Internal Gateway template ID。
  4. 验证 prewarm、Start、首帧、人脸检测、释放和再次分配。

@jiejuncai-ly
jiejuncai-ly marked this pull request as ready for review July 14, 2026 03:47
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@jiejuncai-ly

Copy link
Copy Markdown
Author

本轮 review 已逐项核对:

  • prewarmRoomSession 等待 room_audio_input / room_video_input 不改。browser 模式仍通过 lex-voice 的 browser profile 启动这两个 Room Input 服务参与者;它们先入房并等待浏览器原始轨道。usesServerRoomInputDevice() 只决定用户启动阶段是否再次要求 video readiness,不能据此推断 browser 模式没有这两个参与者。
  • 本地媒体快速失败仍等待 dispatch 的问题已在 d813831 修复:失败时立即 cancelAgentSessionStart(sessionId),中止 dispatch fetch,再复用原有统一远端清理路径。
  • session identity 的隐式漂移已在 9d160e4 修复:LIVEAVATAR_VOICE_SESSION_ID 进入 appConfig.voiceSessionId,且远端 UI config 不能覆盖。AGENT_NAME 由同一进程 env 同源读取,LiveKit room name 则由 canonical session id 推导,因此不再增加另一套配置入口。

验证:129 tests passed,lint passed,production build passed(仅保留已有 ONNX dynamic-require warning)。真实 cloud template 的 /api/session/prewarm HIL 仍按部署 gate 执行。

@jiejuncai-ly

jiejuncai-ly commented Jul 16, 2026

Copy link
Copy Markdown
Author

更新:routing 已合入,本 PR 已基于最新 lex-main 恢复并完成重新移植与测试;当前分支是正式候选,不再是撤下状态。

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown

Claude finished @jiejuncai-ly's task in 5m 13s —— View job


Review 结论

有条件通过

(说明:本次沙箱环境无 node_modules 且无法访问网络安装依赖,未能实际执行 pnpm test / lint / build,以下结论基于对全部变更文件源码的静读审查。核心链路 session-dispatch-service.tsprewarm/route.tsprewarm-use-guard.tssession-registry.tsuseRoom.tsuseBrowserSourceClient.ts 均已通读,前几轮 review 中指出的三个问题——本地媒体快速失败未取消 dispatch、session identity 隐式漂移、room_audio_input/room_video_input 参与者语义——均已在当前代码中正确落地。)

问题及建议

  • [P2] app/api/session/session-dispatch-service.ts:595-631runWithinPrewarmDeadline 中,若 operationPromise 恰好在 deadline 边界前完成但 Date.now() >= deadline 判断为真时,会丢弃已经成功的结果并按超时处理(额外产生一次未被感知的后台 room/dispatch 副作用)。属于极端时序场景,非阻塞项,可考虑放宽为“结果已到手优先返回”。
  • [P2] lib/frontend-vad-observer.ts:48-63 + hooks/useBrowserSourceClient.ts:157-159resolveVadAssetBasePaths 直接把整个 window.location.pathname 当作 session 前缀拼接 /vad-web/。当前应用是单路由页面,行为正确;但如果未来在同一入口下增加客户端子路由,该路径会被误拼成 <pathname>/vad-web/ 导致 404。建议在实现里加注释或改为只截取到 sandboxId/slug 段,避免后续路由变化时静默失效。
  • [P2] app/api/session/prewarm/prewarm-use-guard.ts:12-14prewarmUseStatesglobalThis 级 Map,completed 状态的 key 永不清理。设计注释已说明这是有意为之(Gateway 每 sandbox 一个新 UUID,进程生命周期短),在当前部署模型下可接受,仅在未来若单进程长期承载大量 sandbox 会话时需要重新评估。

残余风险:未能在本地跑通 142 项前端测试与 production build,建议在 CI 结果(View job run)通过后再合并;上述三条均为非阻塞的健壮性/可维护性建议。

Copy link
Copy Markdown
Author

针对本轮 review 的三条 P2,逐项确认如下:

  1. runWithinPrewarmDeadline 的 deadline 边界行为是有意的硬超时语义。恢复执行时若已达到 deadline,就 fail closed 并触发 Gateway allocation 回滚;延迟 operation 的 settle 也由 PrewarmDeadlineError.settled / retryReady 跟踪,不会留下无人处理的 room/dispatch。当前不改为“结果优先”。
  2. VAD 资源路径当前按 Gateway 的单入口 /s/<slug> 设计,整个 pathname 就是 session proxy prefix,现有行为正确。若未来增加 /s/<slug>/... 客户端子路由,再改为显式 base path。
  3. prewarmUseStates 保留 completed key 是一次性授权设计的一部分。当前每个 sandbox 对应一个短生命周期 Next.js 进程和独立 session UUID,sandbox 释放后进程一并结束,不构成长生命周期 Map 泄漏;若未来改成单进程承载大量 sandbox,再重新评估。

补充:当前 test CI 已通过,workflow 已执行 lint、format check、142 项测试和 production build。以上三项均不阻塞合并。

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown

Claude finished @jiejuncai-ly's task in 3m 26s —— View job


任务清单

  • 读取 PR 背景与自定义审查要求
  • 获取当前 diff (git diff origin/lex-main HEAD,因浅克隆无法用三点 diff)
  • 审查核心变更文件(重点核对本轮新增的 85acae5 fix: isolate prewarm startup to sandbox sessions
  • 输出 review 结论

(说明:沙箱环境无 node_modules 且无法访问网络,未能本地执行 pnpm test/lint/build;已通过 CI 状态确认最新提交的 test job 已成功 — job run。)

Review 结论

通过

本轮新增提交 85acae5(isolate prewarm startup to sandbox sessions)核对如下:

  • app/api/session/prewarm/route.ts:27-32:新增 LIVEAVATAR_RUNTIME_MODE !== 'sandbox' 时直接 404,且判断先于 secret 校验,不会因响应差异泄露 secret 是否正确。
  • hooks/useRoom.ts:263-296 + hooks/useBrowserSourceClient.ts:357-401:并发启动路径现在按 Boolean(appConfig.sandboxId) 收窄,非 sandbox(本地/无 sandboxId)场景回退为原始串行逻辑;两处判断条件一致,未发现状态不一致或路径遗漏。
  • lib/session-dispatch-readiness.ts:37-58:新增 requireAgentSessionReady,仅在 prewarmRoomSession 内部 dispatch 请求中启用(session-dispatch-service.ts:300-306),不影响浏览器 Start 走的 dispatch/route.ts 正常 readiness 判定,职责边界清晰。
  • 相关测试(session-dispatch-readiness.test.mjssession-prewarm.test.mjsbrowser-room-session.test.mjs)均补充了对应用例,覆盖 sandbox/非 sandbox 分支与新 readiness 属性。

未发现需要阻塞合并的问题。残余风险:

  • 之前几轮 review 中的三个 P2(runWithinPrewarmDeadline 边界时序、VAD 路径假设单路由、prewarmUseStates 不清理)作者已在评论中说明为有意设计,本轮未见改动,维持原结论。
  • 真实内网/HK 双 Sandbox 环境的端到端 HIL 验证仍待按 PR 描述的部署 gate 执行,非代码静态审查可覆盖。

@lanyue-llk lanyue-llk left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review / Verify 结论

代码 Review:通过(无 P0/P1)
需求 Verify:有条件通过——代码路径和自动化验证已达标,但“真实首屏视频与人脸检测等待确实缩短”仍必须以 Internal Sandbox 的 HIL(prewarm → Start → 首帧 → 人脸检测 → release → 再次分配)作为最终证据,当前静态审查和单测不能替代这一项。

1. 设计目标与技术方案

方案能够实现目标,关键契约是闭合的:

  • POST /api/session/prewarm 只在 LIVEAVATAR_RUNTIME_MODE=sandbox 暴露,使用 Gateway 注入的 secret,并且 identity 全部取服务端环境变量;成功后一次性消费,失败只在超时操作真正 settle 后释放 guard。
  • prewarm 依次完成 Room、worker readiness、dispatch readiness;最终 readiness 同时要求 agentSessionReadyroom_audio_inputroom_video_input,但不要求浏览器视频轨道已经发布,符合“先预热进程/participant,首帧后再发视频”的目标。
  • Start 使用 LIVEAVATAR_VOICE_SESSION_ID 对齐预热 identity;只有存在 sandboxId 时才并行启动 managed local input 与 dispatch,本地 browser/xunfei 仍保持旧串行路径,兼容边界清楚。
  • 配套 lex-voice livekit-examples#226 的实际实现已核对:Browser video runner 可以提前启动,但 RoomInputPublisher 只有收到并成功转换第一个有效 frame 后才创建/发布 room_video,因此不会在 prewarm 阶段发布空/绿色轨道。
  • 45s 总预算、30s worker 上限与配套 Gateway 60s 外层预算一致;失败响应仅返回 phase/timings,详细错误留在服务端日志,Gateway 负责 fail-closed 清理 Room/Sandbox。

2. 实际运行、兼容性与变更范围

  • dispatch route 的协议和默认 8s 行为保留;prewarm 是新增的 Sandbox-only 能力,没有改变非 Sandbox 主链路。
  • agentSessionReady 对旧 template 不做兼容是有意的 fail-closed 迁移,不应静默降级;必须遵守“前端 + template + Gateway”部署顺序,反向部署时先关闭 prewarm。
  • 相对 API/asset URL、logo、font、VAD base path 的修改都服务于根路径、Gateway /s/<slug> 与 CubeSandbox /proxy/4003/ 三类入口;结合 Gateway 的 cookie/referer session routing 后路径语义成立,没有发现跨主题修改 primebot 等业务逻辑。
  • observability 的启动事件缓冲与阶段 marker 用于量化本次优化,属于主题内必要改动。

3. 非阻塞的简化建议

  • [P2] app/api/session/session-dispatch-service.ts 已达 743 行。 目前把普通 dispatch、in-flight 去重、prewarm 三阶段编排、deadline/cancel 和 LiveKit cleanup 放在一个文件中。逻辑本身有测试保护,但这是本 PR 唯一明显的超大实现文件。建议按稳定职责拆成 regular dispatch coordinator、prewarm orchestrator、deadline/cleanup helpers;保持当前函数式接口即可,强行增加类层次不会更简单。
  • [P2] lib/session-dispatch-readiness.ts:47-58 在 video-ready 分支前后重复检查 requireRoomInputParticipantsReady && !hasReadyRoomInputParticipants(...),可以先统一验证 room input participants,再单独验证 video track,减少分支和重复。

4. 验证证据

  • 独立 head 85acae5 快照本地执行:157/157 tests 通过。
  • ESLint、Prettier check、Next production build 通过;build 只有既有 onnxruntime 动态 require warning。
  • git diff --check 通过。
  • GitHub 最新 testclaude checks 均为 pass。

因此:代码可以合并,但需求验收状态应在 Internal HIL 完成前保持“有条件通过”,不要把 CI pass 等同于真实延迟目标已经验证。

@jiejuncai-ly

Copy link
Copy Markdown
Author

已核对最新 LinkAI review:本轮无 P0/P1,两个 P2 都是非阻塞维护建议,暂不扩大本 PR 范围。PR body 已补充真实验收边界:自动化验证已通过,prewarm 的最终延迟效果将在前后端合并并重建正式 Internal template 后完成 HIL。

@lanyue-llk
lanyue-llk merged commit 647d50e into lex-main Jul 29, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants