首页
/ HyperFrames changelog-video 构建规范详解:1080 方形母版时间线、品牌令牌与接缝机制

HyperFrames changelog-video 构建规范详解:1080 方形母版时间线、品牌令牌与接缝机制

2026-09-05 20:05:51作者:柯茵沙

HyperFrames 的 changelog-video skill 负责把一份周报式 changelog Markdown 变成一条 45–60 秒、1080×1080 方形的品牌化视频,而 build-spec.md 正是这条流水线的"构建宪法":它定义了母版时间线的命名契约、品牌字体与颜色令牌、动画背景的 ffmpeg 编码管线、场景坐标规范,以及接缝(seam)机制与 Lint 陷阱的完整解法。读完本文,你将掌握从 scaffold 到 seam-stamp、从字幕轨到渲染门禁的整套构建细节,并理解每条规则背后的渲染器行为依据。

单文档母版:为什么所有场景都写进一个 index.html

build-spec 的第一条约束是结构性的:整条视频是单文档 index.html,所有场景都是绝对定位在轨道 1(track 1)上的 .slide clip;存在一条母版时间线,且必须命名为 tl——因为 seam-stamp 工具生成接缝代码时直接发出 tl.* 调用,名字不对整个接缝系统就失效。这条时间线需要是 paused 的、被 pad 到总时长、并注册到 window.__timelines["main"]

仓库中的字面 scaffold master-skeleton.html 完整展示了这套契约:

  • 根节点声明合成尺寸与总时长:<div id="root" data-composition-id="main" data-start="0" data-duration="<TOTAL>" data-width="1080" data-height="1080">骨架 L46);
  • 时间线创建与 pad:const tl = gsap.timeline({ paused: true }); tl.to({}, { duration: /*<TOTAL>*/ 47 }, 0);骨架 L76-L77),骨架同时初始化 gsap.defaults({ overwrite: 'auto' })
  • 注册与接缝插入点:window.__timelines = window.__timelines || {}; window.__timelines["main"] = tl;,其后紧跟注释"seam-stamp.mjs inserts the <seams:auto> block after the registration above"(骨架 L114-L117)。

scaffold 还从 CDN 引入 GSAP 3.14.2(见 骨架 L9),并在 <head> 内联全部 @font-face 与布局样式。SKILL 文档明确要求:步骤 0 就是把 examples/master-skeleton.html 拷贝为 project/index.html,之后只允许填充占位符(<RANGE><TOTAL><CUT_N><DUR_N>、场景正文),不允许重写 scaffold 的 chrome、字体、调色板或布局壳SKILL.md 步骤 0)。

品牌令牌:字体、颜色与玻璃卡片的精确取值

build-spec 的第二部分是品牌令牌(以 HeyGen for Developers 为例),核心是一组 @font-face 声明与调色板注释。字体共 5 款,全部以本地 woff2 内嵌——skill 自带字体文件(assets/fonts/ 下有 ABCSolarDisplay-Bold、TT_Norms_Pro_Normal/Medium/Bold、tt_norms_pro_mono_regular 五个 woff2),构建时拷贝到项目 assets/fonts/

@font-face {
  font-family: "ABC Solar Display";
  font-weight: 700;
  src: url(assets/fonts/ABCSolarDisplay-Bold.woff2) format("woff2");
}
@font-face {
  font-family: "TT Norms Pro";
  font-weight: 400;
  src: url(assets/fonts/TT_Norms_Pro_Normal.woff2) format("woff2");
}
/* 同族 500 / 700 分别对应 TT_Norms_Pro_Medium / Bold */
@font-face {
  font-family: "TT Norms Mono";
  font-weight: 400;
  src: url(assets/fonts/tt_norms_pro_mono_regular-webfont.woff2) format("woff2");
}

build-spec 内嵌的调色板注释值得逐字继承,因为它把"为什么"也写清楚了:

  • ink(正文白)#f5f6f4,ink2 rgba(245,246,244,.72),dim rgba(245,246,244,.66)——注释特别强调 dim 不能低于 .66(而不是 .45),因为对比度门禁(contrast gate)会拦截玻璃面上小于 4.5:1 的小字;
  • 强调绿 #5ef17c,且是"配给制"(RATIONED):每个场景只允许一个绿色时刻
  • 背景底 #0a0c0b、chip 底 rgba(10,12,11,.78)、玻璃描边 rgba(190,255,205,.32)

组件级取值规则:玻璃卡(glass card)用 chip-bg 填充、1px 玻璃描边、圆角 22、box-shadow: 0 24px 60px rgba(0,0,0,.5),且明确禁止 backdrop-filter;chip 用等宽字体 18–22px、圆角 12、rgba(255,255,255,.14) 描边 + rgba(255,255,255,.05) 底。字体分工:展示标题用 ABC Solar Display 700,正文用 TT Norms Pro,一切代码/UI 标签用 TT Norms Mono。安全边距为 x/y ∈ [76, 1004]——这与 scaffold 里 kicker chip top: 44px; left: 76px、sec-chip top: 128px; left: 76px 的硬编码坐标(骨架 L21-L32)一一对应。

动画背景:把循环源片编码成"整片时长"的 MP4

build-spec 称之为"house pattern"的动画背景有一段硬性管线:把 skill 自带的源片 bg-pattern.mp4 编码到与整片完全相同的时长。原因写在文档里——渲染编译器会把视频 clip 的槽位缩短到媒体长度(shorten a video's slot to the media length),所以编码时长必须 ≥ 总时长:

ffmpeg -y -stream_loop 15 -i <SKILL_DIR>/assets/bg-pattern.mp4 -t <TOTAL> \
  -vf "scale=1080:1080,fps=30,eq=saturation=0.72,drawbox=c=black@0.5:t=fill" \
  -an -c:v libx264 -crf 20 -pix_fmt yuv420p assets/bg-pattern-<TOTAL>s.mp4

滤镜链的每个环节都有意图:缩放满 1080 方形、锁 30fps、saturation=0.72 压饱和度,最后 drawbox=c=black@0.5:t=fill 整体压暗——文档警告"保留这层压暗(keep the darkening crush),原始图案太刺眼了"。这条命令与 SKILL.md 步骤 0 的 bootstrap 命令块完全一致,说明它是"非协商"的启动步骤。

挂载约束同样具体:<video id="bg-video" class="clip" muted> 放在 track 0,外加一层静态 rgba(8,10,9,.25) 的 scrim div(scaffold 中即 #bg-scrim骨架 L19)。<video> 必须有 id(否则渲染结果静默黑屏),且必须保持平面 2D(不能有 3D 祖先节点)。scaffold 中 bg-video 与 BGM 的挂载示例:

<video id="bg-video" class="clip" src="assets/bg-pattern-<TOTAL>s.mp4"
  muted data-start="0" data-duration="<TOTAL>" data-track-index="0"></video>
<audio id="bgm" src="bgm.mp3" data-start="0" data-duration="<TOTAL>"
  data-track-index="2" data-volume="0.14" data-media-start="0"></audio>

场景解剖学:chrome、标题、主题场、Outro 与字幕轨

build-spec 把一条 changelog 视频的 DOM 拆成五种角色,每种的坐标与时长预算都是定死的:

Chrome(无计时,z-index 6):左上角 kicker chip 显示 HYPERFRAMES WEEKLY · <RANGE>;右上角进度点(progress dots)每个主题一个,用 tl.set 在每个切点改 backgroundColor——active 为 #f5f6f4,done 为 .45 透明度。文档特别禁止用 tl.call 改状态,scaffold 里同样注释了"progress dots via tl.set at each cut (never tl.call)"(骨架 L79-L82)。

Title(≤2s):等宽 kicker 日期、ABC Solar h1 约 104px、绿色横线扫入。Title 是"影片开场",它是唯一自己手写 entry 的场景。

Theme 场景:sec-chip 0N · THEME NAME 位于 top 128,ABC Solar 主标题约 54px 位于 top 186,可视化 mock(来自可视化注册表)填充 y ∈ [288, 944] 区间。scaffold 中这些位置就是 .sec-chip / .sec-head 的 CSS 常量(骨架 L27-L32)。

Outro(≤3.5s):kicker FULL DIGEST、"See what shipped." 约 96px、绿线、等宽 URL chip、tagline;全部元素在结束前约 0.5s 淡出(含 chrome)。

字幕轨(caption rail,强制项):按 script-voice.md 的约定——top: 990px、font-size 32px、高 52px,TT Norms Pro 500,ink .94,柔和暗色 text-shadow;它是叠在影片之上的 overlay,不是预留色带。scaffold 内置了一段字幕 IIFE:读取 LINES 数组([{id, end, w:[[display, start], …]}]),逐词建 span,再用 tl.set 控制整句显隐、tl.to(0.12s,power1.out)逐词淡入(骨架 L89-L112)。渲染前必须把 captions.json 的内容填进 LINES——SKILL.md 把它定性为"空 LINES 是 shipped bug,不是风格选择",而门禁第 5 条会抽样渲染帧逐帧验证字幕可见。

接缝与内部生命:ledger、seam-stamp 与"内部节拍"纪律

build-spec 的"doctrine mechanics"部分是这条流水线最硬核的约束集,它建立在 motion-doctrine skill 之上(motion-doctrine/SKILL.md 定义了向量律与 Seam Gate),具体规则是:

  • ledger.json:每一条普通接缝都记为 cut-the-curve LEFT(x 轴、方向 −1),exit 与 entry 的 selector 都是 slide 的 wrapper;Outro 的 entry 记 travel: 8
  • seam-stamp.mjs --ledger ledger.json --write index.html 拥有所有 wrapper 的 entry/exit——作者本人不得手写接缝代码;Title(影片开场)只手写自己的 entry,exit 仍由 stamp 生成。
  • Slides 的 CSS 基态是 opacity: 0data-start 必须精确等于切点时间——这正是 motion-doctrine 指出的 clip-gating 陷阱:data-start 早于 entry tween 会让 clip 以初始透明度提前显形,造成零重叠门禁失败。
  • 每个场景的 shell(chip、headline、mock chrome、初始状态)在局部 t=0 就已"摆好"(COMPOSED),由 wrapper 把它飞进来;内部 reveal 必须在切点后 ≥0.4s 才开始、在下一切点前 ≥0.45s 结束(因为 stamped 的 exit 从 cut − 0.34s 开始)。
  • 每个内部节拍(beat)落在 vo-words.json 的一个 VO 词上;每个场景要声明它的持续运动路线(mock 用 sequenced UI life,checklist 用 staged reveals);每个场景一个绿色时刻。
  • GSAP 用法纪律:初始态用 gsap.set(...) 在构建时打;动画只用顺序的 tl.to(...)(禁用裸对象 keyframes、禁用 repeat: -1、禁用对 left/top 的 tween——基础位置写在 CSS,位移 tween x/y);计数器用带 onUpdate 的对象 tween(缓存 DOM 引用,绝不用 tl.eventCallback)。

seam-stamp 到底往 index.html 里写了什么,可以从 seam-stamp.mjs 的 emit 逻辑直接验证:在切点处生成成对的显隐指令(tl.set("<exit>", { autoAlpha: 0 }, cut) / tl.set("<entry>", { autoAlpha: 1 }, cut)脚本 L76-L77);cut-the-curve 变体则发出 exit 侧 power3.in 缩放+模糊+渐隐、entry 侧 expo.outfromTo脚本 L99-L106);travel 变体按方向符号位移后 power4.out 回位(脚本 L114-L118)。这解释了 build-spec 为什么要求 tl 必须存在、slide 必须 opacity: 0 起:stamp 生成的代码假设这些前置条件,否则渲染会出现重叠或闪帧。

VO 词级时间戳从哪来?SKILL.md 的完整链路是:script-tokens.json(双层脚本,display 给字幕、spoken 给 TTS)→ HeyGen TTS 生成 voiceover.mp3 + vo-words.jsonalign-captions.mjs 把 spoken 时间戳映射回 display token 产出 captions.json。该脚本用 Levenshtein 模糊匹配消耗词流(一个 display token 可对应多个 spoken 词,如 "C L I" = 3 个词),无法吸收的差异会打印 MISMATCH 并以退出码 1 终止(脚本 L90-L126)——SKILL.md 要求所有 MISMATCH 必须在构建前清零。若 TTS 只返回音频没有词级时间戳,SKILL.md 给出 whisper 强制对齐的兜底命令,保证字幕永不缺席。

Lint / Check 陷阱清单:全部踩过、全部预解

build-spec 最后一节是"全部命中过、且已给出解法"的陷阱清单,这是从多次实际构建中沉淀的经验值:

陷阱 解法(build-spec 原文规则)
mock 容器存在故意叠放,被布局 lint 拦 故意参与叠放的每个文本块上加 data-layout-allow-overlap,绝不加在 slide 根上;被 playhead/线穿过的元素加 data-layout-allow-occlusion
暗字对比度不达标 dim 文本最低 rgba(245,246,244,.66)(contrast gate 下限)
<audio> 缺失 id 每个 <audio> 都带 id;BGM 用 skill 自带的 house track(assets/bgm.mp3,159s 器乐)拷入项目并挂在独立轨道上,完整挂载属性见上文 bgm 示例(track 2、volume 0.14 压在 VO 之下;用户给了自己的曲子才替换)
改了代码预览却不变 预览服务器会缓存 bundle——改完必须重启,然后到原始 comp 页(/api/projects/<id>/preview/comp/index.html)用 window.__player.seek(t) 逐点验证

其中 data-layout-allow-caption-zone 这类语义化豁免属性也出现在 scaffold 的字幕容器上(骨架 L51),说明"豁免要加在具体元素上而非根节点"是整条 lint 体系的通用原则。

产物布局与交付门禁

结合 SKILL.md 的项目布局,build-spec 约束的所有文件最终落在一个标准目录里:index.html(单文档母版,场景即 slide、接缝已 stamp)、ledger.json(seam-stamp 输入)、script-tokens.json(VO 与字幕的共同事实源)、vo-spoken.txtvoiceover.mp3 + vo-words.json + captions.jsonbgm.mp3,以及 assets/fonts/assets/bg-pattern-<dur>s.mp4。交付前的门禁依次为:hyperframes check --caption-zone(0 error,dim 文本 ≥ .66 透明度、场景内容避开字幕轨)→ seam-gate.mjs verify 0 fail → 重启预览服务器后 __player.seek 抽查 3–4 个节拍 → 仅在用户要求时才渲染,渲染后从 MP4 抽帧验证字幕在场、背景视频不黑、无过小/冻帧。

适用前提:本文所有坐标、时长与命令均以当前仓库 .agents/skills/changelog-video/ 内的 skill 资产为准(1080×1080、约 45–60s、HeyGen Annie 配音);字体、背景源片与 BGM 都来自该 skill 的 assets/ 目录,scaffold 来自 examples/master-skeleton.html——按 SKILL.md 步骤 0 原样拷贝它们,而不是从上一版视频里复用 index.html,是保证成片"是这个 skill 的品牌"而不是"某个相似项目"的第一道防线。

登录后查看全文
热门项目推荐
相关项目推荐