HyperFrames Registry 贡献指南:为 OpenMontage 新增 Block 与 Component 的完整工作流
【免费下载链接】OpenMontageWorld's first open-source, agentic video production system. 12 production pipelines, 100+ tools, 700+ agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage
HyperFrames 是 OpenMontage 视频生产系统中与 Remotion 并列的可选渲染运行时之一,擅长 HTML/CSS/GSAP 原生的动态排版、产品推广与注册表驱动的组合镜头(详见 skills/core/hyperframes.md)。本文档系统讲解如何为 HyperFrames Registry贡献一个新的 Block 或 Component,覆盖从澄清需求、搭建脚手架、遵循字幕与 VFX 硬性规则进行开发,到通过 lint/validate/render 校验、最终提交合并 PR 的完整闭环。读完你不仅能走通「想法 → 合并 PR」的六步流程,还能理解每一条编写约束背后的确定性渲染原理。
面向谁:为什么需要阅读这份贡献指南
.agents/skills/hyperframes-registry/是随仓库分发的一套 HyperFrames「Layer 3」技能之一,其职责是hyperframes add安装、Block 接线与注册表维护(定位说明见 skills/core/hyperframes.md 第 13-24 行)。其中:
- SKILL.md 覆盖「安装/接线既有条目」;
- 而本指南 contributing.md 覆盖的是反向动作——当现有注册表没有你需要的字幕样式、VFX 效果、转场、lower third 或可复用组件时,如何亲手制作一个新条目并向上游贡献,让它能像
data-chart、grain-overlay一样被全世界的项目通过hyperframes add拉取。
在 OpenMontage 的语境里,这类贡献通常发生在以下时机:compose 阶段把edit_decisions.cuts[i].type映射为某个注册表 Block,而现有注册表无法覆盖某种场景风格;或字幕需要一种新的 karaoke/打字机样式而remotion_caption_burn不适用(Remotion 专属、HyperFrames 暂无对等能力)。此时,本指南就是「自制一个可回归、可复用、可上架」条目的权威路线。
六步工作流总览
1. Clarify → 2. Scaffold → 3. Build → 4. Validate → 5. Preview → 6. Ship整条流水线把贡献者从模糊的创意一路推进到「已合并的上游 PR」。下面逐节拆解。
Step 1:Clarify——先确定条目类型与需求边界
动手写代码之前,先回答「你在构建什么」。注册表只有两种条目,二者在架构语义上完全不同:
| 条目类型 | 存放目录 | type 值 | 本质 | 典型例子 |
|---|---|---|---|---|
| Block(块) | registry/blocks/ | hyperframes:block | 拥有固定尺寸与固定时长的独立完整组合(自带独立 GSAP timeline) | 字幕样式、VFX 特效、标题卡片、lower third |
| Component(组件) | registry/components/ | hyperframes:component | 没有固定尺寸与时长的可复用片段,能适配任意组合尺寸 | CSS 特效、文字处理、overlay 叠加层 |
随后向需求方澄清三个问题:
- 用一句话描述这个效果是什么;
- 有没有视觉参考(URL、截图或文字描述);
- 谁会用它、在什么场景下用。
这个「定位」环节直接决定后文模板选择与registry-item.json清单的写法——Block 必须声明dimensions和duration,Component 则二者皆无。
Step 2:Scaffold——搭建注册表结构与命名空间
目录结构
Block与Component各自有固定的脚手架形态:
registry/blocks/{block-name}/ {block-name}.html registry-item.jsonregistry/components/{component-name}/ {component-name}.html registry-item.json命名约定与 ID 前缀
条目名使用 kebab-case,并配一个2-3 个字母的 ID 前缀。HTML 中所有元素 ID 都必须使用该前缀,以避免子组合(sub-composition)加载时发生 ID 冲突:
| 条目名 | ID 前缀 | 示例 ID |
|---|---|---|
cap-hormozi | hz | hz-cg-0、hz-cw-3 |
cap-typewriter | tw | tw-cg-0、tw-ch-0-5 |
vfx-chrome | vc | vc-canvas |
registry-item.json:使用规范模板
registry-item.json是条目的安装清单,必须基于规范模板生成(Block 与 Component 两套模板、含全部必填字段),可直接复制 templates.md 中的 starter。
Block 清单的关键形态如下(字段的完整语义见 discovery.md 的 manifest 字段表):
{ "name": "BLOCKNAME", "type": "hyperframes:block", "title": "Human-Readable Title", "description": "One sentence: what it does and who uses it", "dimensions": { "width": 1920, "height": 1080 }, "duration": 10, "tags": ["category", "subcategory"], "files": [ { "path": "BLOCKNAME.html", "target": "compositions/BLOCKNAME.html", "type": "hyperframes:composition" } ] }Component 清单去掉dimensions与duration,files[].type改为hyperframes:snippet:
{ "name": "COMPONENTNAME", "type": "hyperframes:component", "title": "Human-Readable Title", "description": "One sentence: what it does", "tags": ["category"], "files": [ { "path": "COMPONENTNAME.html", "target": "compositions/components/COMPONENTNAME.html", "type": "hyperframes:snippet" } ] }files[].target声明的是安装时的默认落盘路径。它会在用户端被hyperframes.json#paths重映射:以compositions/开头的 Block 目标被改写为<paths.blocks>/,以compositions/components/开头的 Component 目标改写为<paths.components>/(机制详见 install-locations.md)。因此贡献者编写 target 时应遵循这套默认前缀约定,让所有自定义项目布局都能正确继承。
标签分类法
tags决定条目在hyperframes catalog中的可检索性,按类别给出约定值:
- 字幕类:
captions、viral、professional、karaoke、minimal - VFX 类:
three-js、particles、shader、gpu - 转场类:
transition、shader、wipe、dissolve - Block 类:
lower-third、social、title-card、data-viz - Component 类:
effect、overlay、text-treatment
Step 3:Build——按类型套模板并遵守硬性规则
根据条目类型应用正确模板(templates.md 提供可直接复制粘贴的字幕模板、VFX 模板与 Component 模板,这些模板已经内嵌了能通过 lint 与 validate 的成熟模式)。模板中待替换的占位符包括BLOCKNAME、PREFIX、COMPNAME,以及字体、配色、入场动画、karaoke 高亮等风格化参数。
字幕类 Block 的「不可协商」规则
- 字号下限:比例字体(proportional)最小 96px;等宽字体(monospace)可放宽到64-72px——等宽字字符更宽,所需字号更小。
- 可读性:使用
-webkit-text-stroke: 2-3px或多层text-shadow,保证字幕压在任意画面上都可读。 - 溢出防护:对每一个文字组调用
window.__hyperframes.fitTextFontSize(),防止文案超出画布宽度。 - Karaoke 高亮:通过
tl.to(wordEl, { color/scale }, WORDS[wi].start)在对应单词时间点点亮当前词。 - 硬性终结(hard kill):对每一个group 在
g.end处执行tl.set(groupEl, { opacity: 0, visibility: "hidden" })——入场淡出之外必须把组彻底关闭,避免残影。 - 严禁
tl.from(el, { opacity: 0 })与同一位置的tl.set(el, { opacity: 1 })并存:from会把set覆盖掉(clobber),导致元素永远不可见;显示态一律改用tl.to。
这些规则并非口味问题,而是 HyperFrames「确定性 seek-and-capture」渲染的直接推论:window.__hyperframes.fitTextFontSize是运行时提供的排版度量助手(见 templates.md 字幕模板中#root-BLOCKNAME内.cap-container的用法);元素初始态必须可预测,from引入的隐式初始值会破坏逐帧 seek 的一致性。
逐字符动画(打字机 / scramble)
对需要逐字符出现的效果:
- 把每个字符包进
<span>,ID 为{prefix}-ch-{group}-{char}; - 用
tl.set按单词时间戳计算出的间隔做错峰(stagger); - 光标、装饰元素同样用
tl.set在时间轴时间点上驱动——不要用 CSS animation(CSS 动画不可 seek,无法被运行时快照定位)。
定位变体
字幕组的常见排版定位有标准写法:
- 居中:
display: flex; align-items: center; justify-content: center; - Lower third:
position: absolute; bottom: 100px; left: 0; width: 100%; text-align: center; - 左对齐:
position: absolute; bottom: 100px; left: 120px; text-align: left;
VFX Block(Three.js)规则
- 使用 CDN 引入的
three@0.147.0(global script,非 module); - 渲染驱动:
tl.eventCallback("onUpdate", renderScene); renderScene();——禁止requestAnimationFrame,否则逐帧捕获画面不可控; - State proxy 模式:GSAP 只动画一个普通 JS 对象,
renderScene读取该对象状态后绘制 Three.js 场景(对象上放rotY、camZ等属性,时间轴上tl.to(st, { rotY: ... })); - 随机性使用种子化 PRNG(
mulberry32),保证每帧渲染结果可复现。
所有类型通用的红线
无论 Block 还是 Component:
data-composition-id必须与window.__timelines["id"]中注册的 key 完全一致;- 所有元素 ID 带块名缩写前缀;
- 统一
gsap.timeline({ paused: true })——时间轴始终处于暂停态,由 HyperFrames 运行时负责 seek; - 禁止
Math.random()、禁止Date.now()。
这里的「无随机、无时钟、暂停时间轴、注册到window.__timelines」与 skills/core/hyperframes.md 中 OpenMontage 侧记录的运行时反模式一脉相承——repeat: -1无限补间、异步上下文/setTimeout/Promise 里拼 timeline 都会破坏确定性渲染;window.__timelines必须在页面加载后同步填满。
Component 模板的特殊性
Component 不是独立组合:模板要求背景transparent、不出现data-composition-id,也不注册window.__timelines——它被粘贴进宿主组合后,由宿主的 timeline 接管时序。所有 class 与 ID 都带COMPNAME前缀,避免污染宿主命名空间。
Step 4:Validate——两条零容忍校验命令
开发完成后进入校验,命令如下(0 errors / 0 console errors 为硬性门槛):
hyperframes lint # 0 errors required hyperframes validate --no-contrast # 0 console errors required两者语义不同:
lint是静态契约检查(重复 ID、轨道重叠、缺失data-composition-id、未注册 timeline 等);validate是基于浏览器的运行时检查——它会 seek 进暂停态的组合、截图、采样像素、计算 WCAG 对比度、验证window.__timelines注册与时间元素上的class="clip"。
开发迭代期可用--no-contrast推迟对比度检查,但最终交付前必须跑完整对比度校验。这与 OpenMontage 的 HyperFrames 验证协议一致(skills/core/hyperframes.md「Validation protocol」一节明确:lint/validate 未通过不得 render,静默渲染失败组合属于契约违规——HyperFrames 的价值恰在于能捕获 FFmpeg/Remotion 捕获不到的问题)。
Step 5:Preview——渲染预览并准备目录卡片
# Render preview video hyperframes render -o preview.mp4 # Snapshot for visual QA hyperframes snapshot --at "1.0,3.0,5.0,7.0" # Publish to hyperframes.dev for review npx hyperframes publishrender产出可审查的 MP4;snapshot在指定时刻(上例为 1.0s/3.0s/5.0s/7.0s)出静帧用于视觉 QA;publish把条目发布到预览站点供评审者在线体验。
目录卡片图:注册表目录卡片使用的 PNG 位于docs/images/catalog/{kind}/{name}.png({kind}为blocks或components),通常由 snapshot 生成。两种贡献者的差异在于:
- HeyGen 内部贡献者:运行
scripts/upload-docs-images.sh(需要 AWS profileengineering-767398024897),自动上传并生成卡片图; - 外部贡献者:把预览 MP4 附加到 PR 描述即可,维护者会在合并前代为生成并上传目录图。
Step 6:Ship——八步走完合并流程
所有步骤缺一不可。任何一步缺失都会产生一个破损的目录条目。
设{kind}为你在 Step 1 确定的blocks或components,{name}为条目名:
# 1. Create branch git checkout -b feat/registry-{name} # 2. Format HTML npx oxfmt registry/{kind}/{name}/*.html # 3. Update registry/registry.json — add entry to the "items" array: # { "name": "{name}", "type": "hyperframes:block" } (or "hyperframes:component") # 4. Generate catalog docs page npx tsx scripts/generate-catalog-pages.ts # 5. Publish to hyperframes.dev so reviewers can preview npx hyperframes publish # 6. Stage everything git add registry/{kind}/{name}/ registry/registry.json docs/catalog/ # 7. Commit git commit -m "feat(registry): add {name} — {one sentence}" # 8. Push and open PR with hyperframes.dev link git push origin feat/registry-{name} gh pr create --title "feat(registry): {name}" --body "preview: {hyperframes.dev-url}"要点拆解:
- 分支按
feat/registry-{name}命名,与提交规范隔离。 - 格式化统一走
npx oxfmt(对*.html),保证代码风格可机械校验。 registry/registry.json顶层清单是发现入口(hyperframes catalog的数据源),向items数组追加{ "name": ..., "type": "hyperframes:block" | "hyperframes:component" }。scripts/generate-catalog-pages.ts负责把注册表同步生成到文档目录页,与卡片图配套。publish抢占你的预览 URL,供评审与 PR 描述引用。 6-8. stage、commit、push 后通过 GitHub CLI 开 PR,并把预览链接放进 body。
如果你没有 GitHub 账户:开 PR 需要先完成注册,然后执行gh auth login完成 CLI 认证。
Quality Gate:合并前的完整检查清单
提交 PR 之前,逐项核对以下质量门:
hyperframes lint→ 0 errorshyperframes validate→ 0 console errorsnpx oxfmt --checkpassesregistry/registry.jsonupdated with new entryscripts/generate-catalog-pages.tsrun(docs page generated)npx hyperframes publishrun(claim your project URL)- Preview MP4 attached to PR(外部贡献者)或 catalog PNG uploaded(内部贡献者)
- All IDs unique and prefixed
「All IDs unique and prefixed」正是 Step 2 命名约定的落地校验——lint 会拦截重复/无前缀 ID,但贡献者应在提交前自查。
从装配视角理解你的贡献:安装与接线
理解用户端如何消费条目,能帮你写出更顺手的registry-item.json与默认路径。
安装位置(详见 install-locations.md):
| 条目类型 | 默认安装路径 | 配置项 |
|---|---|---|
| Block | compositions/<name>.html | hyperframes.json#paths.blocks |
| Component | compositions/components/<name>.html | hyperframes.json#paths.components |
Block 接线:Block 是自带data-composition-id、尺寸、时长与 timeline 的独立组合,宿主通过带data-composition-src的<div>引入。运行时加载子组合后定位其window.__timelines注册,并相对宿主时间轴按data-start偏移同步 seek——宿主无需在自身 GSAP 代码里引用 Block 的 timeline(wiring-blocks.md)。这也解释了为什么贡献 Block 时必须严格保证data-composition-id↔window.__timelines["id"]的一致性。
Component 接线:读取安装后的文件(如compositions/components/grain-overlay.html),把 HTML 元素、<style>、<script>(若有)按注释头指引分别并入宿主组合,必要时把暴露的 GSAP timeline 调用加入宿主 timeline(wiring-components.md)。两条带完整步骤的实战走查分别见 add-block.md(给视频右侧 40% 区域叠一个 5s 起播的data-chart)与 add-component.md(给标题加shimmer-sweep扫光并定制--shimmer-color/--shimmer-angle)。
附:模板与范例速查
贡献时最常打开的周边资源都集中在同一个技能目录下:
| 资源 | 内容 | 相对路径 |
|---|---|---|
| SKILL.md | hyperframes add安装/接线速查与总入口 | .agents/skills/hyperframes-registry/SKILL.md |
| templates.md | 字幕/VFX/Component/registry-item.json 全套复制粘贴 starter | .agents/skills/hyperframes-registry/references/templates.md |
| discovery.md | registry.json 清单读取、manifest 字段表、现有 97 个 Block 分类目录 | .agents/skills/hyperframes-registry/references/discovery.md |
| install-locations.md | 默认安装路径与hyperframes.json#paths重映射规则 | .agents/skills/hyperframes-registry/references/install-locations.md |
| wiring-blocks.md / wiring-components.md | 接线属性和合并步骤 | wiring-blocks.md / wiring-components.md |
| examples/ | add-block / add-component 完整走查 | add-block.md、add-component.md |
一条额外提醒:OpenMontage 侧的 HyperFrames 字体编译是确定性的,只内联编译器有映射的字体(安全选择如 Montserrat、Outfit、Inter、JetBrains Mono、Poppins、Playfair Display,详见 skills/core/hyperframes.md 的 gotchas 一节)。因此,字幕 Block 的模板默认加载 Montserrat 800/900 是稳妥选择——如果你在贡献时换用编译器未收录的字体,最终画面可能退化回系统 fallback 字体。
从「澄清需求」到「目录卡片上架」,HyperFrames Registry 的贡献链路把创意作品变成了可被hyperframes add复用、被确定性渲染引擎精确回放的工程资产——这正是它区别于普通前端 demo 的所在。
【免费下载链接】OpenMontageWorld's first open-source, agentic video production system. 12 production pipelines, 100+ tools, 700+ agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考