HyperFrames Motion Doctrine:向量法则、影片电流与 Seam Gate——把多场景视频变成"一次连续的镜头运动"
HyperFrames(Write HTML. Render video. Built for agents.)的仓库内建了一个面向动画创作的"技能(skill)"体系,其中 motion-doctrine 是最高层级的运动学总纲(GATEWAY):它规定任何多场景视频在每个接缝(seam)处"必须发生什么"、每个场景"如何表演",而具体参数与代码模板则下放到 cut-the-curve、oversized-cursor、seam-craft 等实现层技能。读完本篇,你将掌握 Vector Law(含 Z 轴 scale 符号规则)、The Current 向量预算、ledger.json 向量台账的写法,以及用 seam-stamp.mjs 生成接缝代码、用 seam-gate.mjs 数值化验收的完整工程化工作流。
这套规则针对的失败模式非常具体:各场景孤立创作,导致"观众眼睛的动量在每次剪辑处死掉",场景在入场与退场之间原地晃动(idle wobble)。Doctrine 的定位是决策层——它"决定每个接缝上发生什么",并明确声明其规则覆盖(supersede)通用/上游的运动指导。
一、Gateway 定位与路由图
motion-doctrine 是一个 GATEWAY 技能:在编排任何 HyperFrames 动画之前先加载它,它再把你路由到负责实现的具体技能。原文给出的路由表如下:
| 决策(本技能负责) | 实现技能(负责落地) |
|---|---|
| 接缝过渡的选择 + 参数 + 代码 | cut-the-curve §1–5(完整目录) |
| 文本/元素入场级联 | cut-the-curve §6(waterfall entry) |
| 场景内群组重定位(无剪辑) | cut-the-curve §7(nudge curve) |
| 光标主导动作 / 场景启动 / 变形点火 | oversized-cursor |
| 接缝渲染机制 / 白闪防护 | seam-craft |
| 产品发布 / 解说 / 字幕类工作 | 在对应上游技能之上叠加 text-beat-economics、brand-faithful、captions-overlay 等 overlay 技能 |
实现层的入口是 cut-the-curve/SKILL.md:五类速度匹配的接缝技术(Zoom-Through、Inverse Zoom-Through、Cut the Curve、Waterfall Cut、Rack-Focus Blur-Cut)加上两个场景内技术(Waterfall Entry、Nudge Curve)。其统一原则是"在峰值速度处剪辑,剪辑两侧的方向与速度必须匹配"——doctrine 定法律,cut-the-curve 给参数。
创作顺序(Authoring Order)
Doctrine 规定了一条严格的流水线顺序,这也是本文后续各节的组织线索:
向量台账(ledger.json)→ STAMP 主时间轴接缝(seam-stamp.mjs --ledger ledger.json --write index.html)→ 每个阶段指派 sustained-motion 路线 → carriers 与 causes → 构建场景 → VERIFY(seam-gate.mjs)。
其中一条关键工程约定:手写只留给 Tier-A 的 morph/match-cut;凡是 stamp 出来的接缝"按构造即通过门禁"(stamped seams pass the gate by construction)——因为生成器写出的缓动、时长与符号本身就满足向量法则。
二、The Seam Law:接缝法则
2.1 Vector Law——"如何退出,决定如何进入"
How Scene A exits determines how Scene B enters: same axis, same direction, matched speed, cut mid-motion on both sides.
四条子规则:
- Axis(轴)——x 永远是 x,y 永远是 y,Z 永远是 Z。跨剪辑绝不允许换轴。
- Direction(方向)——绝不允许镜像。对 Z 轴,方向 = scale 变化的符号:变大 = push(镜头向前),变小 = pull(镜头向后)。"退场在后退(receding),入场却从小变大(grow-from-small)"是一个被镜像的向量——这是最常见的违规,原因正在于 grow-from-small 是元素入场的第一默认选择。
- Speed(速度)——入场初速度 ≈ 退场末速度,通过镜像缓动实现(退出
power4.in+ 进入power4.out,同距离同时长;进入侧从"名义路径"的 50% 处接上)。具体机制见cut-the-curve。 - Phase(相位)——剪辑必须落在两侧都在运动途中的位置。在剪辑前减速停住,或在剪辑后从静止开始,都是一个"死拍(dead beat)"。
2.2 The Current——一部片子只有一条"电流"
每部影片选定一条主导方向(仓库默认惯例:向左 LEFT),所有普通接缝都使用它。其他向量是预留(RESERVED)资源——花掉一个就意味着它在表达什么:
| 向量 | 含义 |
|---|---|
| The current(向左) | "下一拍"——中性的向前推进 |
| 向上(Upward) | 升格——一个结论或揭示"高于"之前的一切 |
| Z 向前(zoom-through) | 钻入同一个思想的更深处 |
| Z 向后(inverse zoom) | 到达(ARRIVAL)——更大的东西落位 |
| Scale-burst(炸出画面) | 离开一个世界——表面从镜头前掠过 |
两条配套纪律:
- 绝不允许相邻接缝方向相反——ping-pong(往返摆)读起来就是错误;
- 方向变化必须有可见原因(点击 / 回弹 / 撞击)或章节边界。
2.3 Vector Ledger——先写账本,再动代码
在编写任何主时间轴之前,先把向量台账写成项目根目录下的 ledger.json(schema 见 references/seam-gate.md)。每个接缝一行:剪辑时间、exit 与 entry 的向量(轴 + 带符号方向,Z 行携带 scale 符号)、选择器、技术。Exit 与 entry 必须一致;某一行不匹配时,要修的是计划(plan),不是缓动。验证器在运行任何运行时采样之前,会先静态检查行的自洽性。
完整的 ledger.json 示例(三种接缝类型各一行):
{
"fps": 30,
"seams": [
{
"id": "hook→claim",
"cut": 4.2,
"technique": "cut-the-curve LEFT",
"exit": { "selector": "#el-hook", "axis": "x", "dir": -1 },
"entry": { "selector": "#el-claim", "axis": "x", "dir": -1 }
},
{
"id": "claim→payoff",
"cut": 10.2,
"technique": "inverse zoom-through",
"exit": { "selector": "#el-claim", "axis": "z", "dir": -1 },
"entry": { "selector": "#el-payoff", "axis": "z", "dir": -1, "scanRoot": "#el-payoff" }
},
{
"id": "ui→player (match cut)",
"cut": 60.6,
"type": "match-cut",
"carrier": { "out": "#resting-card", "in": "#product-video" }
}
]
}
各字段含义(来自 seam-gate.md 的 schema 说明):
cut——主时钟上的秒数,即"进入侧点火"的那一帧;type——"cut"(默认,完整向量检查)/"match-cut"/"morph"(只查载体连续性 + 零重叠;运动可以从边界处才开始);axis——"x"、"y"或"z"(z = scale)。dir——运动符号:x −1 = 向左,y −1 = 向上,z +1 = push(变大),z −1 = pull(变小);selector——承载接缝运动的元素。主时间轴移动 wrapper 时用 wrapper;接缝运动写在子场景内部时用场景内的 hero(id 或[data-hf-id=…])。用probe命令能帮你判断该用哪个;entry.scanRoot(z 接缝)——扫描"符号对抗"内部入场的子树,默认取 entry 选择器;carrier——"cut"行可选,match-cut/morph 必填。out/in的矩形必须在 cut±1 帧匹配(中心 12px / 尺寸 5% 容差,含祖先变换)。
2.4 Carriers——眼睛跟随的是物体,不是抽象概念
最强的接缝会把一个具体载体以匹配的位置和速度递过剪辑:走到一半的光标、收缩/停靠进下一个布局的容器、飞入精确槽位的标记、waterfall 剪辑中的词组。若没有天然载体,就让场景的 hero 元素来承担(部分位移 + 提前淡出,入场时在飞行途中)。绝不允许 crossfade——它根本没有任何载体。
2.5 Causal Motion——因果运动链
让每个动作都 visibly 由上一个动作点燃:click → squash → release spring → flight → impact → recoil → reveal。三条规则:
- 效果在原因帧上启动——同一时间轴位置,绝不"稍后一点";
- 反应幅度随暗示质量缩放:大元素回弹慢,小元素啪地一下;
- 力是改变方向的许可证;无因的方向翻转就是 ping-pong。
三、The Seam Gate:把法则变成构建门禁
Doctrine 给 Seam Gate 的定义是:"build gate——运行验证器,exit 0 才算接缝完成":
node <SKILL_DIR>/scripts/seam-stamp.mjs --ledger ledger.json --write index.html # 生成
node <SKILL_DIR>/scripts/seam-gate.mjs verify --ledger ledger.json --project . # 验证
在仓库中,<SKILL_DIR> 即 .agents/skills/motion-doctrine 所在目录。两个脚本零 npm 依赖,要求 Node ≥ 22 加一个本地 Chrome(gate 会自动找 ~/.cache/puppeteer 下的 chrome-headless-shell 或系统 Chrome)。
3.1 seam-stamp.mjs:从台账"盖章"出接缝代码
seam-stamp.mjs 是 Seam Gate 的"生成半边":读取 ledger.json,输出(或 --write 写回)主时间轴的接缝代码块。从源码可以看到它的生成逻辑:
- 场景清单与基础态:按出现顺序收集所有 exit/entry 选择器,第一个场景
gsap.set为可见(autoAlpha: 1),其余全部autoAlpha: 0归零变换;Z 型入场会被预置到"离焦状态"——pull(dir −1)预置scale: 1.25,push 预置scale: 0.78,并带上blur(18px)(见 seam-stamp.mjs#L37-L45)。 - X/Y 接缝(seam-stamp.mjs#L108-L120):
- exit:
tl.to(sel, { xPercent: 12*dir, autoAlpha: 0, duration: 0.34(默认), ease: "power3.in" }),起始于cut - 0.34s; - 剪辑点:
tl.set(sel, { autoAlpha: 0 }, cut)硬切; - entry:
tl.fromTo(sel, { xPercent: -travel*dir, autoAlpha: 0.35 }, { xPercent: 0, autoAlpha: 1, duration: 0.42(默认), ease: "power4.out", immediateRender: false }, cut)——从路径中途(0.35 不透明度)点火,正好落实 Vector Law 的"≥50% 接上"与 Phase 规则。 - 台账可选参数:
exit.dur/entry.dur覆盖时长,entry.travel(xPercent/yPercent 偏移,默认 10,柔化入场用 8),blur(Z 接缝,默认全画面 18px,文字 scale 用 10px)。
- exit:
- Z 接缝(seam-stamp.mjs#L92-L107):pull 时 exit
scale: 1 → 0.8+ blur,entry1.25 → 1配expo.out;push 时 exit1 → 1.18,entry0.78 → 1。退出时长默认 0.21s、进入默认 0.5s——进入约为退出的 2.4 倍,与 cut-the-curve 中 cut-the-curve 类接缝"entry ≈ exit × 1.27"、inverse-zoom "30% exit / 70% entry"的参数族一致。退出透明度是独立的none缓动 tween(避免power3.in把不透明度拖得太久)。 - 防呆与标记块:若同一行的 exit/entry 轴或方向不一致,脚本直接抛错 "fix the PLAN, not the stamp"(seam-stamp.mjs#L87-L90)。写回 HTML 时替换
// <seams:auto>…// </seams:auto>之间的块;无标记则插入到window.__timelines["main"] = tl;注册行之后(seam-stamp.mjs#L130-L140)。match-cut/morph 行只生成两侧的tl.set可见性开关,载体交接保持 Tier-A 手写。
一个值得注意的源码细节:生成器给 X/Y 的退出腿用的是 power3.in(而非 doctrine 文字里写的 power4.in),而验证器的 speed-match 检查对速度比的容忍度为 3 倍(下文 SPEED_RATIO),因此该组合在数值门禁上完全通过——这说明"镜像缓动"在数值层面被落实为可测的速度比,而不是对缓动函数名的字面匹配。
3.2 seam-gate.mjs:无头浏览器里的数值验收
seam-gate.mjs 是"验证半边",零 npm 依赖,通过**原始 CDP(Chrome DevTools Protocol)**驱动 chrome-headless-shell。它的工作方式:
--project <dir>会新起一个预览服务器(npx --yes hyperframes preview --foreground --no-open --port <5380+随机20>,并刻意删除HYPERFRAME_RUNTIME_URL环境变量——源码注释说明错误值会静默地以 200 HTML 通过探测),等待/api/projects就绪后打开…/preview/comp/index.html,跑完杀掉子进程;--url则复用已运行的服务器(注意:comp 编辑后要重启它,否则验的是过期 bundle);- 等待 HyperFrames 运行时(
window.__playerReady && window.__renderReady && window.__player)与document.fonts.ready后注入页内 harness:seek(t)用__player.pause()+__player.seek(t)逐帧定位,read()用getBoundingClientRect读中心坐标、宽比(有效 scale,自动包含祖先 wrapper 的变换)与祖先链累计不透明度; - 对每个接缝在
cut-0.1s、cut-1f、cut+1f、cut+0.1s四个时刻采样,再做以下检查。
从源码顶部常量区(seam-gate.mjs#L37-L44)可以看到门禁的全部数值判据:
| 常量 | 值 | 含义 |
|---|---|---|
VIS |
0.04 | 累计不透明度低于此值 = 不可见 |
EPS_XY |
15 px/s | 慢于此视为"静止"(判 exit-settled / entry-from-rest) |
EPS_Z |
0.04 es/s | Z 轴静止阈值(有效 scale 单位/秒) |
SPEED_RATIO |
3 | 入/退速度比超出 3 倍或小于 1/3 → WARN |
CARRIER_POS_TOL |
12 px | 载体中心跨剪辑容差 |
CARRIER_SIZE_TOL |
5% | 载体尺寸跨剪辑容差(含祖先 scale) |
每个检查与报告行的对应关系(与 seam-gate.md 的"What each check enforces"表一致):
| 报告行 | 对应法则 |
|---|---|
ledger |
计划内 exit/entry 向量自洽(axis + dir) |
exit-moving / entry-moving |
规则 1/4——不许停住的退出、不许静止起步的进入 |
exit-direction / entry-direction |
规则 2——实测运动符号必须等于台账符号(Z 轴即 scale 符号规则) |
speed-match(WARN) |
Vector Law §3——入场速度 ≈ 退场速度 |
zero-overlap |
逐帧只允许一侧可见——剪辑不是溶解 |
z-sign-scan |
规则 2 的扩展——进入场景自身的内部入场(在 cut+1f → cut+0.1s 窗口内扫描 scanRoot 子树)不得与接缝 Z 符号对抗 |
carrier-position / carrier-size / carrier |
载体矩形连续性,含祖先变换 |
速度与可见性的测量基于 getBoundingClientRect(x/y 用中心,z 用宽度比),因此祖先 wrapper 的变换自动被计入——这正是"台账里 selector 该写 wrapper 还是子场景 hero"要靠 probe 来定夺的原因。
此外还有 probe 子命令:
node <SKILL_DIR>/scripts/seam-gate.mjs probe --t 44.8 --project <project-dir>
它在指定剪辑时刻前后(默认 ±0.1s 窗口)对 #root 全树扫描(上限 900 个元素),按速度排序输出 top 14 个 mover 的选择器、vx、vy、vscale、不透明度变化与尺寸,并提示符号约定(x-: 左, y-: 上, scale+: push, scale-: pull)——即"为写台账行做侦察"。verify 支持 --json 机器输出、--fps(默认 30),退出码 0 = 通过、1 = 存在 FAIL、2 = 用法/环境错误。
3.3 脚本查不了、仍然由你负责的三条规则
- 编辑会重新打开接缝:任何对场景头/尾约 1 秒的改动(包括为匹配新 VO 重排时间)都会使该边界失审——重跑验证器。
- 音频是时钟(Audio is the clock):按 VO 的真实词时间戳重排场景,绝不为塞进时间槽而赶读;VO 重新生成会重开它的接缝。
- clip-gating 陷阱(zero-overlap FAIL 的常见原因):
data-start早于入场 tween 的 clip,会以初始不透明度被揭示——必须同时设autoAlpha: 0并且让data-start等于剪辑时间,绝不能更早。
这套门禁在仓库内的实战出口是周度 changelog 视频流程:changelog-video 技能将每周 changelog 渲染为 1080×1080 MP4,验收标准为 hyperframes check(0 errors)+ seam-gate verify(0 fail/warn),见 .agents/skills/README.md。
四、Part 2 — Performance:场景要一直在"表演"
4.1 禁止 idle wobble:运动必须"表演",不许"呼吸"
闲置正弦循环(breathe、float、drift、glow pulse)被禁止作为持续运动——它们读起来就是"视频在等待"。一个场景入场完毕却还剩好几秒,是规划 bug:该加故事,不该加晃动。入场与退场之间的每一段都必须由以下路线之一独占(在计划里指名路线):
| 路线 | 内容 |
|---|---|
| Staged reveals | 把内容扣住,在解说拍点上兑现——画面持续获得新信息(≥2 个内容组时的默认) |
| Camera with intent | 一条映射好的 scale+pan 路径:广角建立 → 行进 → 落在主体上 |
| Sequenced UI life | 产品随时间"活起来":进度前进、高亮步进、计数滚动 |
| Animated sequences | 元素演出一拍:卡片归栈、条目被拖走、结果组装 |
| Cursor-led action | 超大号光标带着眼睛走到触发器;它的 CLICK 点燃下一拍(oversized-cursor) |
验收测试:在任意一秒暂停——必须有一个"有意义的东西"正在飞行途中(一个 reveal 正在落位、镜头正在行进、UI 正在做解说所说的事)。
4.2 Stillness before climax——高潮前的静默
在重大动作与其结果之间安排 0.3–0.75s 的停顿——戏剧逗号。直接从动作跳到结果的场景会丢掉它。
4.3 Timing intents
- 单个入场 ≤ ~800ms;更长的铺垫应做成多元素 stagger,而不是一个慢元素;
- 退出 ≈ 入场的 75%。例外:cut-the-curve 把这条比例反转(入场约为退出的 127%)——这正是"接住速度"的代价;
- 总 stagger ≤ 500ms;8 个以上元素时收紧逐项延迟,或只 stagger 前几个;
- 禁用缓动:
bounce.out/elastic.out。入场过冲back.out(1.4–1.7)可以; - 相似元素共享同一 ease+duration 意图——绝不为每个元素发明独特的配对。
4.4 Transition vocabulary——全片只用 2–3 种场景间过渡
并反复使用;默认边界就是沿 current 方向的 cut-the-curve。手写的共享元素 morph(intent: morph)不计入该配额。
五、Anti-Patterns:一张对照表记住所有禁区
Doctrine 收尾的这张表浓缩了全文判罚逻辑:
| 不要 | 而要 |
|---|---|
| 孤立地设计每个场景的入场 | 先写向量台账 |
| 场景间 crossfade | 沿 current 方向的 cut-the-curve |
| 退场完成后再切场景 | 两侧都在运动途中剪辑 |
| 剪辑后从静止开始入场 | 从名义路径 ≥50% 处进入 |
| inverse-zoom 退场 → grow-from-small 入场(或 push → 过度收缩) | 匹配 scale 速度符号(Seam Gate z-sign-scan) |
| Z 接缝交接下,来场自身弹跳式 intro | 让开场帧保持已构图状态,或让符号匹配 |
| 用 idle wobble / breathe / float 填时间 | 指派一条 sustained-motion 路线;或加故事 |
| 无因的方向翻转 | 花掉一个"力",或保持 current |
| 把预留向量当花哨用法 | 默认 current;把它们花在意义上 |
| 反应比原因晚几帧 | 同帧点火 |
| 动作直接跳到结果 | 安排 stillness-before-climax(0.3–0.75s) |
六、技能生态中的位置与适用前提
- 两套技能命名空间:.agents/skills/ 是"仓库原生"技能(只在本仓库运行时被 Codex CLI 自动发现,承载 doctrine 重的创作流,如周度 changelog 视频);
skills/则是通过npx hyperframes skills分发给其他项目的市场技能集。.claude/skills/下有一份字节级镜像(CI 有 check-skill-mirror.mjs 强制同步),供 Claude Code 用户获得同样的自动发现。 - 依赖闭包:
changelog-video的五个依赖技能(motion-doctrine、cut-the-curve、captions-overlay、seam-craft、oversized-cursor)就地位于.agents/skills/下,使路由图在 clone 后即完整。 - 运行前提:Node ≥ 22、可用的无头 Chrome(
CHROME_PATH或~/.cache/puppeteer下自动发现)、一个能通过hyperframes preview起预览服务的项目目录;--project模式会在 5380–5399 端口段随机选口、用完即杀,不需要你手动管理服务器生命周期。
适用边界:motion-doctrine 是针对"多场景、有主时间轴、可 seek 的 HyperFrames 影片"的接缝与节奏纪律;它对单场景动画不构成额外约束(此时直接读 cut-the-curve 的 §6/§7 场景内技术即可)。它的价值不在"更花哨",而在于把"多场景像一次连续镜头运动"从一个审美直觉变成一份可静态检查(ledger 自洽)、可数值验证(verify 退出码 0)、可再生(stamp 幂等替换 <seams:auto> 块)的工程契约。
相关文件索引
- motion-doctrine/SKILL.md —— 本文主体:向量法则、current、Seam Gate、Performance 规则
- references/seam-gate.md —— stamp/gate 用法与
ledger.jsonschema - scripts/seam-stamp.mjs —— 台账 → GSAP 接缝代码生成器
- scripts/seam-gate.mjs —— CDP 驱动的数值验收器(verify / probe)
- cut-the-curve/SKILL.md —— 实现层:五种接缝 + waterfall entry + nudge curve 的完整参数目录
- .agents/skills/README.md —— 技能命名空间说明与 changelog-video 工作流
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00