Skip to content

feat(render3d): 出帧交给用户浏览器,worker 不再装 Chromium #714

Description

@johnnyzhang-eng

背景

出帧目前跑在 worker 进程里:providers/render3d/sprite.py 起一个本地 HTTP 服务当 docroot,用 node + Playwright Chromium 打开 bake_stage.htmlmixer.setTime 逐帧抓 WebGL 缓冲。docker-compose.yml 的 worker 用 target: runtime-render3d,node、Chromium、three 因此全部进了 worker 镜像。

2026-08-26 在部署机实测:worker 镜像 2.53 GB,backend 镜像 820 MB,其中 /ms-playwright 单独 656 MB;根分区 38G 已用 32G(84%),staging 的 worker 镜像同样 2.53 GB。

部署机没有 GPU,这条路只能走 SwiftShader 软件光栅。本机 2026-08-04 实测:12 帧 2214×1848 软件渲染 6.37s,峰值进程树 RSS 约 1.0 GB,峰值 CPU 760%,即需要 7.6 个核;部署机只有 4 核。服务器上的真实负载(18MB GLB + 4096 贴图 + 骨骼动画)至今没有实测数据。

同一台机器上 i2v 的峰值内存问题见 #690,一期已由 #695 合入。两者是同一台 4C8G 上的两笔账,本 issue 不碰 i2v 的算法。

路线图见 #712

问题

服务端渲染的这一段,用户那一侧有空闲 GPU,服务端没有;渲染结果本身也不参与计费与判定。继续留在服务端的代价是镜像多 1.7 GB、出帧时与 i2v 抢同一台 4C8G 的 CPU 与内存,而收益只是渲染环境统一。

方案

浏览器承担驱动循环与 WebGL 采样,worker 只做 Playwright 之后的部分。

浏览器:拉 model_3d_url → __ready → __setCamYaw → __setup(clip,i,n) → __coverage → __grab
      → 生帧 PNG 直传,key 绑 task_id
worker:校验张数、空帧、PNG magic → 像素化 → _lastmile → 成色闸 → 交付帧入库

优先把 bake_stage.html__* 钩子抽成前端可复用模块,不要另写一套 three 出帧。

前端必须带走的硬约束,缺一条就会把坏帧交给后处理:

  1. 抓 WebGL 缓冲,不对页面截图,透明底会被合成掉
  2. mixer.setTime(t) 采样,不实时播放,同一 clip 两次要能对账到采样时刻
  3. setPixelRatio(1)antialias: false
  4. 构图一次算定,横向跨度取 max(X, Z);多朝向转相机不转模型
  5. 覆盖率低于 MIN_COVERAGE(默认 0.005)判失败,禁止上传全透明帧
  6. clip 名与 ActionSpec.action 对齐,朝向与 want 对齐,张数等于 n_frames
  7. 材质只认 cel|lit|clay|toon|orig,拼错即抛不静默兜底。管线那份出帧台只认三种取值、其余静默落到同一分支,拿它做过的材质对照结论不成立,这条校验是防复发

任务 SLA:关标签、切后台、移动端 WebGL 失败一律判任务失败可重试;状态机要有前端出帧中这个状态,不要表现成 worker 还在跑。生帧直传复用媒体直传的 token 与重试策略。

后处理内存:32 张 1536×2560 RGBA 同时进 PIL 约 500 MB,逐帧处理做完即丢,且不与 i2v 同进程。

三渲二不套抠图(去白会吃浅灰甲),像素化仍按 ActionSpec

不包含

  • 不改帧数对账、_lastmile、成色闸与写回 actions 的行为
  • 不改 i2v 抽帧抠图算法
  • 不改三渲二的计费口径与人工确认闸
  • 不做多朝向出参的 UI,那条缺一个设计决定
  • 不承诺跨设备逐位一致的交付帧,见下

已知代价

交付帧随用户 GPU 与驱动变化,导出包不再有同一套精灵逐位一致的保证。本方案接受这一点,换掉应用机的 CPU 与镜像体积。若之后必须可复现,另开服务端抽检重渲,不在本 issue 范围。

验收

  • generation worker 镜像回到 runtime,镜像内没有 /ms-playwright,出帧路径不再 import bake_driver.mjs
  • 同一 ActionSpec:前端交 N 张合法 PNG,_finish 产出 N 张交付帧,成色闸照跑
  • 张数不符、覆盖率不足、空 dataURL 三种坏输入都被后端拒收,不写 actions
  • 4C8G 上只跑三渲二出帧时,worker RSS 不再出现 Chromium 量级的跳变
  • 环境开关 WINDUP_RENDER3D_CLIENT_BAKE=0 可回到服务端 Playwright 路径

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions