| name | beat-performance-pipeline |
| description | 把"3D角色一段连续表演"(如 揭小贤走到茶桌坐下冲茶讲解)拆成 Beat(与配音cue逐句对齐的最小动作单元), 每个 Beat 走 设计→实现→多维evaluator(workflow)→loop 的生产管线。核心物料=【坐标契约 scene-layout.json】 (角色/道具/落座点/抓取点共用一份坐标,authoring与runtime一致=手到壶到)。当任务涉及:分镜化角色表演、 与配音同步的动作序列、道具拿放(re-parent)、走路/坐下/倒茶类动作、茶汤/重力类物理合理性检查、 逐beat评审 —— 时使用本 skill。配套 workflow:项目 workflows/beat-eval-loop.star。 ⚠️ 活文档:揭小贤茶艺表演的每个 beat 实作经验都往本文件追加。 |
Beat 表演生产管线(分镜化 3D 角色表演)
-1. 目标 / 最终验收标准 / 技术栈(评审与决策的基准,先读)
目标(一句话)
扫功夫茶冰箱贴 → 揭小贤完整演出【临现招手 → 走到茶桌 → 坐下 → 拿壶 → 六式冲茶(烫杯/纳茶/高冲/低斟/关公巡城/韩信点兵) → 敬你一杯】的 29.6s 表演,与配音逐句同步,AR 尺度下可爱、对版、物理可信、流畅 —— 让用户的体感是"一个小向导刚刚请我喝了杯功夫茶"。
最终验收标准(全部满足才算这一期完成)
- 功能:点「听讲解」后 B1–B14 全序列自动演完;每 beat 起止与配音 cue 误差 <0.3s;「再听一次」从 B3 重入且道具已复位。
- 质量闸:每个 beat 过 Tier A 全部不变量 + Tier B 五维(判定规则:每维 双模型≥1 pass,且 ≥4/5 维 pass;双模型对同一维分歧→以"更严"一方的 issues 为修复输入,修后复评);正面机位全程无可见穿模;所有道具拿/放无瞬移(re-parent 连续)。
- 物理:坐姿支撑(髋在凳上/脚踩地)、壶倾角规则(非倒茶<15°)、茶流重力(±5°)、端杯水平(<10°)全部机检通过。
- 性能:iPhone Safari 真机流畅(无 >1s 卡顿);本期新增 3D 资产合计 ≤3MB;模型可靠加载(此前 5.3MB 曾加载失败,3.2MB 稳)。
- 体验(Tier C,唯一终审=用户):真机看整段"像小向导请你喝茶"——生动、可爱、不出戏;用户签字才封板。
- 工程:vitest 全绿;走 worktree+PR+merge;skill/契约文件同步更新。
技术栈选择(及为什么——都是验证过的结论,别再重选)
| 层 | 选型 | 为什么(替代方案为何不用) |
|---|
| 角色动画 | Blender 程序化 IK+bake | 已验证(Greet/Pour);Mixamo 要登录且 502 过;Tripo preset 与 mixamo-spec 骨架不兼容且无茶艺动作 |
| 走路位移 | clip 原地走 + runtime position lerp | 游戏标准技法;烘根位移会和锚定/重播打架 |
| 道具建模 | Tripo text_to_model + gltf-transform 狠减(28MB→<1MB) | 静物是 Tripo 甜区;手工建模不必要 |
| 对版 2D | codex 图生图(-i 锁参考) | 已验证可出对版可爱图;是"美术手感"的来源 |
| 口型 | 2D 说话脸 + 离线振幅包络 | 3D 口型在此资产上四法皆败(死路已证);Web Audio 在 iOS 截断配音(已踩) |
| 时序编排 | audio.currentTime = 唯一时钟驱动 beat 状态机/口型/字幕 | 单时钟零漂移(已验证);不用独立计时器 |
| 空间布局 | scene-layout.json 坐标契约(authoring与runtime共读) | "手到壶到"的根基;杜绝散落硬编码 |
| 茶流/热气 | billboard sprite(条件显隐) | 移动端流体模拟不现实;sprite 够读、够轻 |
| 评审 | Tier A python/Blender 机检 + Tier B harness 双模型 workflow + Tier C 用户 | 三层闭环已验证(口型一役);缺陷只下沉不上浮 |
| 运行时/部署 | MindAR+A-Frame / GCE+cloudflare | 既有栈不动;iOS 非 meshopt+webp 铁律 |
0. 为什么用 Beat
一段 30s 连续表演没法整体评审/迭代;Beat = 与配音 cue 逐句对齐的最小动作单元(0.7–4s),
每个 beat 有自己的【物料/动作规格/可机检不变量/视觉评审点】→ 评审环才有抓手,失败只重做一个 beat。
1. 生产流程 v2(2026-06-12 全量复盘后重设计;旧"拿到什么先做什么"流程作废)
任务本质=一出微型舞台剧。工程件自底向上(runtime/管线),内容件自顶向下(剧本→分镜→资产→舞台→表演)——旧流程所有返工都源于把内容也自底向上做。
阶段0 立项 北极星+验收标准+工具能力实证清单(依赖的能力先真实成功调用一次才进计划)
阶段1 剧本 配音文案→TTS→cue表=唯一时钟
阶段2 分镜★ 先出**空间设定包**(2a):场景平面图/侧视图(从坐标契约正交渲染,非画的)+人-桌-凳-茶具尺寸关系图
+道具三视图(turnaround)——作为分镜与建模的**输入**;再(2b)codex 逐cue生成分镜
(每格带全套茶桌茶盘,空间一致,有位移的格要画出移动轨迹/起止位)→评审→【用户批G0】
阶段3 资产★ 从分镜推导道具清单→输入标准先行(对版参考/A-pose/无道具)→生成→压制gate
→Tier V 视觉美感闸(§2.5)→资产总览用户过目;原点/bbox实测,不许拍脑袋
阶段4 舞台★ 照分镜摆3D:原点修正+bbox进契约+可达性预验(臂长vs所有交互点)
→"3D vs 分镜"并排图→【用户批G1】→契约冻结(冻结前禁止下游并行)
阶段5 表演 逐beat串行闸:codex设计→codex脚本(/tmp工件)→主循环Blender执行(每次干净导入)
→Tier A(本地确定性,不依赖provider)→渲染(机位=分镜机位)
→Tier B(基准=像不像分镜那格)→过闸入库;walk/sit优先动捕,程序化只做手势
阶段6 集成 白名单导出→资产链路检查表(新模型必须确认动画已重绑)→【无视觉证据不得部署】→真机=用户终审
1.5 验收矩阵(2026-06-12 G0-v3 批准后立;每步三层验收,缺一层=该步未完成)
| 步骤 | ① 自动脚本验收(确定性,本地) | ② 视觉验收 | ③ 代码验收 |
|---|
| 3a 道具参考图 | 文件存在>100KB;轮廓比例机检(PIL 前景 bbox,如桌 h/w∈[0.32,0.48]) | 主循环对版分镜+美感初筛 | — |
| 3b 建模+压制 | GLB 可 parse;bbox 三轴比例进容差;压后≤单件预算、总和≤3MB | 4 视角渲染→双模型 Tier V(对版/美感/压缩损伤/语义,基准=参考图+分镜) | 压制参数有出处 |
| 4 舞台 v3 | 接地误差<0.005;桌上物 y=桌面±0.005;bbox 互不穿插;出生点+路径点距桌 footprint≥0.05;全交互点 reach≤0.95×臂长 | 正交三视图+与 sb_S 对位并排图→双模型+主循环(G1') | 契约 diff 审:每个数字写得出推导来源 |
| 5 动画重校 | 每 clip 自检 print PASS(脚穿/髋漂/触达/躯干上限/循环闭合) | (并入渲染步统一看) | 脚本 diff 审:只许坐标/时序变,逻辑不许漂 |
| 6 渲染+Tier B | 帧数=窗口×24±1;角色入画机检(前景 bbox 占画面高 25-70%);strip 拼装 exit 0 | 每 beat 单帧先审→全量;beats-visual-batch 双模型 5 维,基准=对应分镜格;主循环终筛 GIF | 机位表逐项=分镜镜头表 |
| 7 集成 | 导出 clip 清单=JYX_BEATS 引用集合(脚本读 GLB 比对);beat 窗口铺满 [0,29.6] 无缝隙无重叠(脚本验);build/tsc 0 错;资产总预算复核 | 本地 preview 逐 beat 截图证据包(=「无视觉证据不得部署」的证据) | runtime diff claude 关键位审 |
| 8 部署+终审 | 部署后 curl 200;线上资产 hash=本地 | 真机=用户终审 | — |
横切纪律(根因→规则):
- 交付=验收物在手且过闸;"命令跑完/HTTP200/机检绿"都不算完成。
- 产出物校验闸:子任务空产出/只有开场白=FAILED 熔断上报,禁止静默当"没问题"下传。
- provider 评审撞 infra=阻断,绝不降级放行;核心不变量本地确定性化。
- 单变量迭代+两轮不涨熔断;一切渲染先单帧过目再全量。
- 角色分工:codex=生成产能(分镜/参考图/动作设计/脚本/取证);主循环=关键位(审实物/Blender执行/美术终筛/集成);用户=G0/G1/终审三个拍板点。
- 完整复盘报告(6根因+证据)见 session-forensics-v2 run(2026-06-12)。
2. 核心物料:坐标契约 scene-layout.json(一切空间关系的唯一真源)
{ "units":"character_height=1.0", "anchor":"magnet center, x右 y上 z朝用户",
"P0_spawn":[0,0,0.05], "table_pos":[...], "table_top_z":0.xx,
"stool_pos":[...], "seat_hip":[...], "pot_on_table":[...],
"cups":[[c1],[c2],[c3]], "gaiwan":[...], "walk_path":[[..],[..]] }
- Blender 动画 authoring 与 runtime 布局读同一份契约 → 手伸向
pot_on_table 的 IK 目标 = runtime 壶的真实位置 = 手到壶到。
- 改布局=改契约文件,动画与场景同步变;不许在代码/脚本里散落硬编码坐标。
- ⚠️ 坐标系映射(已实证冻结,2026-06-11 B0):
blender = (c_z, c_x, c_y) × H + (0,0,z0),其中 H=角色 Blender 世界身高(实测 0.997≈1.0,契约单位≈Blender 米),z0=脚底。循环置换、行列式+1,相对几何全保。**推导曾给出错的 −c_x(把桌放反到角色右侧),靠"放标记物→渲染→对照 AR ry=270 真实朝向"才抓出来——映射永远实证,别信推导。**角色在 Blender 面朝 +X=契约 +z(朝用户);角色左手侧=+Y=契约 +x。runtime 侧契约直接用(A-Frame 锚系原生),无转换。
- 时序契约:
audio.currentTime 是唯一时钟;beat 状态 = currentTime 的纯函数(给定 t 能无状态推导出:当前 beat、walk 位移比例、壶/杯父子关系、茶流显隐)→ 暂停/seek/重播/锁屏中断天然正确。禁止事件驱动累积状态(中断后对不上)。重听=seek 到 7.5s(B3 起点)。
2.5 道具(资产)evaluator —— 任何道具进场景前必过(2026-06-12 被用户抓漏后强制化)
字节/三角数 gate(Tier A)只是底线,不是验收。 每个道具(桌/凳/壶/杯/盖碗/…)必须再过:
- Tier V 视觉美感闸(双模型 workflow):Blender 渲 正面+3/4 两视图 → codex+claude 评 ①对版(潮汕红绿金描金、Q版潮玩质感,和揭小贤同一世界观?)②美感(造型/比例/贴图好看吗)③压缩损伤(狠减面后破相/穿洞/UV撕裂?)④语义正确(空茶盘就该是空的——Tripo 常夹带私货,如"桌上自带一把壶"与可抓壶打架,必须重生成而不是凑合)。
- 不过 → 重生成/换提示词/换来源,不许"先用着"。 道具是每一帧都在镜头里的,丑一件毁全场。
- 流程:
Tripo 生成 → 压到 gate → 渲两视图 → 双模型视觉评审 → 过才进契约摆位。
2.6 Beat 验收的三条铁律(同日补,防再犯)
- Tier B 视觉评审(beat-eval-loop.star)是强制步,不是可选——"主循环自己瞄 filmstrip"只能当预筛,不算评审;每个 beat 必须跑双模型五维,记录在案。
- 涉及位移的 beat(走路/移动)验收物必须带空间位移:Blender 预览时给 armature 对象层加沿 walk_path 的位移动画(只为渲染,不烘进 clip),GIF 里看到"从 A 走到 B"——原地踏步的 GIF 验收不了"走到茶桌"。
- 验收 GIF 一律上线
public/beats/,用户看的是动图不是静帧。
3. 通用不变量(所有 beat 都检;每条标注测量层 B=Blender scrub / R=runtime 探针 / V=视觉评审)
测量层原则(评审纠出的关键):Blender 只测得到骨骼/物体变换;走路 lerp、re-parent 连续性、茶流 sprite、音频生命周期是 runtime 现象,必须用 R 层测——做法:页面挂 window.__jyxBeatProbe(每帧记录 t/beat/关键世界坐标/倾角),headless Chromium(Playwright)跑一遍录下来→python 断言;V 层=渲染给视觉 agent/人。
- (B) 坐姿/站定期间 髋漂移≈0;双脚 y≈地面;躯干-桌沿距>0(不入桌)。
- (B) 可达性:任何 IK 目标到肩的距离 ≤ (上臂+前臂)×0.95(Q版短臂,坐姿高冲/伸桌拿壶都要先验这条,不可达就改契约位)。
- (R) 道具 re-parent 帧世界变换连续:快照世界矩阵→换父→反算 local;探针记录切换前后世界位置差 <1% 身高。
- (R) 走路防滑步:lerp 位移速度 = 步频×步长 ±10%。
- (B+R) 液体物理(统一阈值,单位一律【度】):出流阈值全局唯一 >25°(B 层检壶倾角轨迹,R 层检 sprite 显隐与倾角一致,滞回 ±3° 防闪烁);非倒茶时段壶倾角 <15°;端杯全程杯倾角 <10°;(R)茶流方向≈重力 ±5°,起点=壶嘴,终点≈正下方;高冲流长、低斟流短。
- (R) 茶汤状态机(从无到有):三杯液面(小圆片)= t 的纯函数——B9 巡城起出现、到 B10 末升至 70%("七分满");B13 端起的杯必须带茶面。简化声明:不模拟烫杯弃水,液面只进不退(AR 尺度够)。
- (R) 音频生命周期:播放必须由用户手势启;锁屏/来电/切后台 → audio 暂停 → beat 纯函数自然冻结,恢复后从 currentTime 继续;「再听一次」= seek 7.5s 且道具状态由纯函数即时重算(无须手工复位)。
- (R) 道具拿起期间手-道具距恒定;表演结束(t>29.6)所有道具回契约初始位。
- 性能:本期新增 3D 资产逐项预算(总 ≤3MB):桌 ≤1.0MB(2.74 还要再压)/凳 ≤0.4/盖碗 ≤0.3/杯×3 ≤0.45(单杯 0.15)/壶 0.34(已达)/茶流+热气+液面 sprite ≤0.1;角色 GLB 增 4-6 个 clip 约 +0.05MB(clip 很小)。AR GLB 非 meshopt+webp。
4. 揭小贤·茶艺表演 Beat 细化表(活记录,29.6s 配音对齐)
配音 cue:0-4.5 你来啦/小向导 | 4.5-7.5 来先坐下 | 7.5-12 待客泡茶 | 12-14 工夫二字 | 14-14.7 烫杯 |
14.7-15.4 纳茶 | 15.4-16.1 高冲 | 16.1-16.9 低斟 | 16.9-18 关公巡城 | 18-19.2 韩信点兵 |
19.2-21.1 都有学问 | 21.1-26.3 品字/七分满/人情 | 26.3-29.6 敬你慢慢品
时间戳=cue 显式绑定(状态机/机检/重播 seek 的依据);倾角单位一律【度】;不变量后括号=测量层(B/R/V)。
| Beat | [t_start,t_end] | 物料 | 动作要点 | 特别注意(物理/空间) | 关键不变量 |
|---|
| B0 茶席组装 | (离线) | 桌/凳/壶/3杯/盖碗 GLB + scene-layout.json | Blender 统一尺度朝向;桌高≈角色腰;第一件事:实证坐标系映射 | 尺度=角色身高1.0;按概念图 scene_1 摆 | 桌高=0.45±0.05;契约真值回写;映射函数冻结 |
| B0.5 临现招手 | (点击前,不计时) | Greet clip(已有) | 循环招手,茶席已在右侧 | 等「听讲解」;点击=用户手势解锁 audio | (已验收的 Greet) |
| B1 走步 | [0.0,4.5] 哎/你来啦/我是揭小贤/小向导 | WalkInPlace clip | 2-3步弧线+lerp位移+渐转向 | 防滑步;下摆穿模→抬腿小;绕开桌角;bob 2-3%;4.5s走~0.5单位=慢悠悠正好 | (R)速度匹配±10%;(B)脚不入地;(R)终点=凳前±5% |
| B2 坐下 | [4.5,7.5] 来/先坐下/喝杯功夫茶 | SitDown clip+凳 | 髋先后移到凳上方再降;膝~90°;脚触地 | 长袍穿模→桌面遮挡;凳高=契约seat_hip | (B)落座髋=凳面±2%;脚触地;髋xy=凳心±5% |
| B3 拿壶 | [7.5,9.0] 我们潮汕人待客 | (壶在桌) | 右手IK→pot_on_table→抓→提 | mitten手:壶贴掌心柄朝外;先验可达性;re-parent快照法 | (B)抓帧手壶距<2%;(B)可达;(R)切换位置差<1% |
| B4 持壶介绍 | [9.0,14.0] 头一桩…工夫二字 | — | 持壶轻晃+左手比划 | 壶口朝上不漏茶 | (B)倾角<15° 全程 |
| B5 烫杯 | [14.0,14.7] 烫杯 | 茶流sprite | 壶横扫三杯上方浅倒(snap) | 0.7s=17帧:只做"扫"一个要素,无预备 | (B)壶x扫过≥2杯;(R)流随壶 |
| B6 纳茶 | [14.7,15.4] 纳茶 | — | 左手向壶口捏指撒茶 | 左手别穿壶/脸 | (B)左手-壶口距<5% 一次 |
| B7 高冲 | [15.4,16.1] 高冲 | 茶流(长) | 壶猛提向下倒,标志动作 | 壶别穿帽/头;先验坐姿可达——够不到头顶就改"尽臂长最高点" | (B)壶y>可达上限90%;倾角>40°;壶-头距>阈 |
| B8 低斟 | [16.1,16.9] 低斟 | 茶流(短) | 壶降到杯沿高贴近倒 | 与高冲对比明显 | (B)壶y<桌面+2杯高;倾角25–40° |
| B9 关公巡城 | [16.9,18.0] 关公巡城 | 茶流 | 持续出水匀速横扫三杯往返 | 壶嘴对准杯列;流终点依次划过三杯 | (B)壶x单调扫3杯再返;倾角>25°全程;平滑 |
| B10 韩信点兵 | [18.0,19.2] 韩信点兵 | 茶流(滴) | 三次点滴,一杯一点 | 每点壶嘴对准杯心 | (B)倾角峰=3;每峰壶x=杯x±半杯距 |
| B11 放壶 | [19.2,21.1] 一道道都有学问 | — | 壶放回桌+直腰点头 | 壶底贴桌;放下倾角→0 | (R)壶位=初始±2%;(B)倾角<5° |
| B12 品字手势 | [21.1,26.3] 品字/七分满/人情 | 液面sprite升至70% | 左手摊掌指三杯 | 茶汤状态机在此段完成"七分满" | (R)液面=纯函数(t) |
| B13 敬茶 | [26.3,29.6] 来/这第一杯敬你/慢慢品 | 前杯re-parent | 双手捧前杯向用户前伸+微躬定格 | 杯水平<10°(带茶面);杯不穿桌 | (B)抓帧手杯距<阈;前伸>15%;杯倾<10° |
| B14 复位 | [29.6+](ended) | — | 杯归位→坐姿呼吸idle | 状态=纯函数(t),重播seek 7.5s即自洽 | (R)道具=契约初始位 |
5. 实现技法(已验证的,引用配套 skill)
- 动画 authoring:Blender IK 摆位→渲染迭代(我当眼)→
nla.bake(visual_keying;Blender 5.x 用 bpy.ops.pose.select_all 不是 bone.select)→ ACTIONS 导出多 clip。见 blender-mcp。
- 走路位移:clip 原地走 + runtime 对
a-gltf-model position lerp(标准游戏技法)。
- re-parent:
bone.add(obj)/快照世界矩阵;A-Frame 实体可被 three bone.add 收编(jyx-handprop 组件)。
- 口型=2D 说话脸(振幅包络),与 beat 并行不冲突;字幕=HTML 层。
- 道具来源:静物=Tripo text_to_model(28MB 原始→gltf-transform simplify 到 <1MB);对版 2D=codex 图生图。
7. Runtime 重构清单(2026-06-11 代码库交叉审计,30 条对抗验证确认;开工前必读)
Blockers(不修没法做 beat)
- 无 beat 状态机:jyx-anim 是 2 态事件机,从不读 currentTime → 重写为 beat→clip 调度器:startNarration 的 rAF(已是唯一时钟消费者)解析 beatId 并发布;每 beat 配 clip 名/loop|one-shot/
action.time = t − beatStart(纯函数,支持任意 seek 进场)。
- jyx-talk-start 立刻播 Pour(与 walk-first 冲突)→ 删 toTalk/toIdle 二元;Greet 只作 B0.5 待机。顺带抓到现行 bug:actions 注册表只有 Greet/Idle/Talk,'Pour' 从没注册——线上讲解时其实在播 Talk!
- jyx-handprop 永久挂手+只切可见性(壶凭空出现在手=瞬移)→ 重写为 beat 驱动 re-parent:
Object3D.attach 语义,B0 在桌上、B3-enter 挂手、B11-enter 放回;永不拿可见性当抓取;杯(B13)复用同组件。
- 无位移系统(角色 position 静态)→ B1 walk lerp + B2 髋路径要建,且=纯函数(t)。
- GLB 只有 4 clips——WalkInPlace/SitDown/GrabPot/六式/敬茶全缺(Blender 排产清单)。
- teatable 2.61MB 独占预算 87% → 再压(≤1.0MB)。
7/8. 打断与重听:二元状态机表达不了"走一半静音";再听一次永远从 t=0(违验收#1)→ 全由"纯函数(t)+seek 7.5s"解决。
Majors(精选)
- talkface 是固定位 sibling——角色一走,2D 嘴脸就和头分家 → talkface 必须挂头骨(同 handprop 思路)或每帧跟随头骨世界位。
- scene-layout.json 零代码读取(坐标全硬编码/URL)→ runtime 加载契约。
- 双时钟问题:mixer 走 wall-clock dt、beat 走 currentTime → iOS 卡顿/中断会撕开 → mixer 也改由 t 驱动(
action.time = t − beatStart 一并解决)。
- 2D teaboard.webp 与 3D beat 冲突(杯是像素抓不了)→ B0 后弃用,换 3D 茶席。
- B1 反直觉:4.5s 是超预算(0.5 单位拉满 4.5s = 慢动作)→ 走 ~2.5s + 到位后 0.5s 整理 + 招手过渡填满。
- B5–B10 不变量轴写错(对照契约应为 x 横向)→ 已在表中用 x。
- 结束/静音都回"站立 Greet"=瞬移 → 结束态=坐姿 idle(纯函数 t>29.6 段)。
- char GLB 3.33MB 已贴"稳定上限",新 clip 须以 ACTIONS 增量导出(clip 很小)验证总量。
- targetLost 中 narration 继续但按钮卸载(无法停)→ targetLost 暂停 audio(纯函数自然冻结)。
- B3 可达性实测 97–116% 臂长(临界!)→ 契约 pot_on_table 朝角色挪近(B0 校准时定)。
Minors(记账):crossfade 按 beat 配置(快拍 0.08–0.12s,位移拍 0.2–0.3s);茶流 sprite 系统列入 B0 todo;删除死重 11.8MB teapot.glb;cues 4.5s 处 50ms 重叠;audio.play() 拒绝被吞(加 catch 提示);组件卸载取消 rafRef;页面总重 ~10.4MB 需关注。
二跑补全(36 条确认+完整综合)的精确化增量
- 阈值定值:B7 壶-头距 >0.08(B0 按头网格 bbox 标定);B13 抓帧手-杯距 <0.02(与 B3 同量级)。
- B1 子分配(定稿):招手 0–2.0s(盖住"哎/你来啦/我是揭小贤")→ 走路 2.0–4.0s(0.26u/s,3 步@1.5步/s)→ 转身 4.0–4.5s(~250°/s,Q版可接受)。原"4.5s 慢悠悠正好"作废(=1/3 步速的慢动作漂移)。
- 契约 schema 增 4 字段(B0 从 GLB bbox 自动提取回写):
pot_spout(茶流起点/B6 左手目标)、pot_grasp(抓取点≠壶中心,柄朝外)、cup_dims{height,radius}(B8 用)、table_bbox(躯干-桌沿距的"沿")。
- 结束态规则:t≥B2 末 → 桌边 SitIdle(新 clip,排产+1);否则 → 出生点 Greet。静音/中断=冻结(pause+保持姿态),绝不路过站立 Greet(防穿桌瞬移起立)。
- MJ-11 targetLost 中场:narration 播放中丢锚 →
audio.pause()+冻结 mixer+pill 提示"对准冰箱贴继续看表演";re-found → 同 t 恢复(纯函数天然续上)。静音按钮在播放中常驻(不随 cameraState 卸载)。
- MJ-12 单时钟落实到 mixer:
mixer 不喂墙钟 dt,改 dt = currentTime − lastT(或 setTime(beatLocalT));补 onPause/onStalled/onWaiting;beat 转换一律电平触发(状态=纯函数,re-parent 幂等),漏帧自愈。
- MJ-9 GLB 体积工程:导出保持动画优化(基线 4 clips=18.7KB,导出后断言动画总字节<200KB);需要余量时 gltf-transform quantize(KHR_mesh_quantization,iOS 可用、不是 meshopt!)可把几何 2.79MB→~1.4MB——⚠️ 早前"quantize 会 prune skin"的坑要先小样验证再上。
- 逐资产 gate(实测锚定):桌≤0.8(已达 790KB/21.6K tris ✓)/盖碗≤0.4/杯≤0.25(1 个 GLB 运行时克隆 3 实例,绝不出 3 份文件)/凳≤0.25/sprite≤0.05/角色clip增量≤0.12 → 总计 ~1.7–2.1MB,3MB PASS 有余量。
- re-parent 不变量的家:vitest(真 three 场景+GLB 骨架)+ Playwright runtime scrub;Blender 只保诚实代理(抓取帧手骨世界位 vs 契约 <2%)。"手-道具距恒定"删除(同义反复)。
5.5 决策记录(用户授权自主决策后,每个 gate 决定记录在此,用户保留否决权)
- 2026-06-12 G0 分镜:有条件通过——审分镜时发现配音"来,先坐下"的主语是观众(主人邀客),不是角色自己坐下 → 叙事重定向为"坐姿主人版":格1=坐席后招手、格2=向观者请坐手势(重生成),格3-7 不变。walk/sit 从关键路径移除。
- 2026-06-12 纪律:「无视觉证据不得部署」即刻生效(阶段6 硬闸)。
- 2026-06-12 战略:C 先行(坐姿主人版到可发布)+ B 增强(Mixamo 动捕 walk 入场,等用户下载后插回;runtime beat 表加行即支持)。
- 2026-06-12 G0 用户反馈(部分否决上一条):分镜方向获认可,但①走路必须回来——补"走入→落座"过程格,角色是真实位移不是静止换姿势(纯坐姿版作废,改为完整版:走入→招手→落座→请坐→茶艺);②每格分镜必须显示全套茶桌茶盘(场景一致性);③暴露 workflow 重大缺口:图像生成缺空间设定层(平面图/三视图/尺寸关系)→ 已补为阶段2a,空间设定包=分镜与建模的输入。3D 茶桌与分镜不对版,批 G0 后照分镜重建。
- 2026-06-12 分镜 v3(走路版):叙事=走入挥手(0-3s)→落座(3-4.5s)→请坐手势(4.5-7.5s)→茶艺(同前)。sb_0/sb_1b 已生成,原 sb_1(坐席挥手)退役。待用户批 G0-v3。
- 2026-06-12 道具全面设计先行(用户两次斥茶桌丑后立规):每个道具都要"设计→多候选参考图→美感筛选→建模→Tier V 对版",不许直接文生3D 拍脑袋。新茶桌三视图设定已出(矮长条深红木+金雕花,对版分镜);存量道具(壶/盖碗/杯/凳)逐个对版分镜重审,不对版的重做。
- 2026-06-12 道具链终态:桌v3(mv多视图,h/L 0.343)PASS;壶v3(紫砂)WARN接受;盖碗(青花)WARN接受;杯v4(空杯)重抽过损伤闸;凳=v2(对版过/太矮胖)本地 z×1.6 拉伸定型——因 Tripo 积分耗尽(code 2010),凳v3建模未跑成,本地拉伸是免积分折衷(凳90%被遮挡)。⚠️ 需要更多建模时请用户充值。
- 2026-06-12 桌高 0.45→0.36:Tier B 揭示坐姿可见带只剩 0.17(肩仅高出桌面0.07,俯拍又全是Q版巨帽=「只见帽子」),分镜里桌面只到坐姿下胸口。降到 0.36 → 可见带 0.26(头+肩+上胸)。教训:道具尺寸要按"坐姿可见带"反推,不是按"站高比例"拍。
- 2026-06-12 渲染欠曝总根源=会话引擎被切到 BLENDER_WORKBENCH(无视灯光+AgX压暗)——查 engine 应是渲染排障第一步,在调灯之前。
- 2026-06-12 Tier B 渲染评审三轮熔断:轮1全必修(暗+机位平=桌面墙)→轮2涨分仍必修(俯拍=帽伞)→轮3 改分镜对齐中景(sb_4构图:正面略俯20°人居中半身)。教训:特写机位对Q版大帽角色 = 低仰角中景,俯角越大越只剩帽。
- 决策原则:每个决定亮牌给用户、附理由、可否决;执行中发现决定错了→改决定并记录,不硬扛。
6. 踩坑追加区(每做一个 beat 往这里记)
- 2026-06-11 开工前评审(双模型,11/11 critic 产出)在 B0 之前抓出 12 个设计缺口——时间戳列缺失/单位混用/茶流阈值矛盾/坐标系映射缺失/Tier A 层错配/茶汤无状态/可达性没人验/音频生命周期/3MB无清单 等,全部已回写本文档。教训:生产文档自己也要过评审环,"写得顺"≠"自洽可执行"。其中最值钱的一条:把 beat 状态做成 currentTime 的纯函数 一举解决 暂停/seek/重播/中断 全部边界。
- 2026-06-11 B0 真机首炸:scale 弹出动画 × 单位测量 = 道具巨型堆叠。角色入场有
scale 0→1.5 弹出动画,jyx-locomotion 在 model-loaded 时量身高 → 量到 ~0 → __jyxUnit 无效 → 所有 jyx-place 永远等待 → 道具以原始尺寸(米级)堆在原点,巨型白杯吞掉角色。修:① 删 scale 弹出动画(正确性>花哨)② 测量改 tick 重试直到"值>0.3 且连续两帧稳定" ③ 道具就位前一律 visible=false(防原始尺寸闪堆,这条升级为通用规则)。教训:任何"等模型加载后测一次"的逻辑都要怀疑入场动画/异步时序;隐藏直到就绪是默认姿势。
- 2026-06-12 B1-walk 首个 beat 闭环跑通,沉淀 5 条:
① 脚踝≠脚底(必踩坑):foot IK 目标是脚踝,authoring 写"着地=y0"会让脚底入地 ~2%身高 → 所有脚部 IK 目标统一 +
ANKLE_FIX≈1.8%H;Tier A 的"脚不入地"逮住了它(这就是闸的价值)。
② beat-build workflow 实战形态:codex 设计+落脚本(/tmp/beat_scripts/.py 工件)质量可以很高(631行体系完整);claude 评审 worker 掉线时,主循环顶上当关键位(本来就更强:能直接跑验证)。
③ 脚本必须自带自检 print(逐帧脚z/髋漂移/循环角差/PASS 总判)→ 主循环 grep 即 Tier A,零额外脚本。
④ 验收 GIF 标准通道 = repo public/beats/<beat>.gif 随部署上线,用户手机开 URL 看动图签字;Next 生产模式不认 build 后塞进 VM 的文件(404),别走捷径。
⑤ 坐姿一致性(B2 起的硬规矩):B2 坐下的末帧姿势存成 /tmp/beat_scripts/seated_pose.json(骨→四元数),B3-B14 所有坐姿 clip 从它加载作基底——否则每个 clip 的"坐姿"各坐各的,切 beat 必跳。
- (逐 beat 继续填)