插件安装: 在执行设置或新鲜度命令之前,请遵循 插件执行规则(当此技能位于 HyperFrames 插件内时)。独立安装请保留下面的更新说明。
HyperFrames 核心
Agent 陷阱(请先阅读):
- 使用 flex/
inset居中,不要使用 CSStransform: translate(-50%,-50%)然后对该节点进行 GSAPx/y操作。Lint 检查:gsap_css_transform_conflict。使用fromTo或xPercent/yPercent。 - 不要添加场景退出
tl.set(..., {visibility:"hidden"})。运行时已经隐藏了定时剪辑。内部节点上的不透明度淡出(或.clip上的opacity)就足够了。字幕硬关闭是另一条规则。 window.__timelines["id"]必须与根data-composition-id匹配。- 渲染后,读取摘要的第二行:
beginframevsscreenshot、GPU 模式、阶段时间。screenshot+ Linux 上的software gpu是慢速路径。
HyperFrames 从 HTML 渲染视频。组合是一个 HTML 文件,其 DOM 使用 data-* 属性声明时间,其动画运行时是可寻址的,并且其媒体播放由框架拥有。
此技能是技术合约——如何构建一个 hyperframes 项目。下文是构建指南;按主题的详细信息位于 references/(下一步索引),按需阅读。流程文档(简要、故事板、审查、制作、分派、帧工作器)位于 /hyperframes → references/。其他关注点位于同级领域技能中——hyperframes-animation、hyperframes-creative、media-use、hyperframes-cli、hyperframes-registry。/hyperframes 中的能力地图说明了每个技能涵盖的内容。
参考
| 文件 | 阅读目的…… |
|---|---|
references/minimal-composition.md | 从最小的可渲染组合骨架开始 |
references/composition-patterns.md | 选择整体式还是模块化;构建模块化 index.html;选择子组合原型 |
references/data-attributes.md | 查找任何 data-*(根/剪辑/子组合宿主/遗留别名);使用 class="clip" |
references/tracks-and-clips.md | 理解 data-track-index 控制什么(以及不控制什么)、z-index、相对于另一个剪辑的时间;使用 npx hyperframes timeline 列出每个轨道和剪辑 |
references/creator-editing-recipes.md | 复制真实的剪切/修剪/重新排序/重新计时/冻结/相机/遮罩/交叉淡入淡出/音频编辑配方及其限制 |
references/sub-compositions.md | 连接子组合(宿主属性、<template>、每个实例的变量)并在其内部制作动画 |
references/variables-and-media.md | 声明变量;放置 <video>/<audio>、设置音量、修剪 |
references/determinism-rules.md | 构建可寻址时间线;确定性禁止;布局/文本适配 |
references/full-screen-motion.md | 使用共享背景创作全帧运动 |
references/tailwind.md | 在 Tailwind v4 项目中工作(init --tailwind;运行时合约不同于 Studio 的 v3) |
关于动画运行时的具体信息(GSAP API、Lottie、Three.js 等),请前往 hyperframes-animation → adapters/<runtime>.md。
构建组合
两种根形式(不可互换)
- 独立(顶层
index.html):根<div data-composition-id="…">直接位于<body>中,没有<template>包装器。包装独立根会隐藏所有内容,并且lint会拒绝(standalone_composition_wrapped_in_template,错误)。 - 子组合(通过
data-composition-src加载):将根包装在<template>中。这是要编写的形状:加载器也接受普通的完整文档并回退到其<body>,但模板化形式是示例和工具所假设的。
⚠ 传输规则:对于模板化子组合,组装器会丢弃文件自身的
<head><style>/<script>(packages/core/src/compiler/compositionAssembly.ts,hasTemplate门),因此将<style>/<script>放入模板中。<link>在任何情况下都会被提升。 ⚠ 宿主 ID 约定:给宿主插槽、内部模板和window.__timelines["<id>"]键相同的 id。支持不同的本地 ID(组装器回退到文件中的第一个根),但不匹配是静默的,因此请匹配它们,除非你有理由不这样做。
文件形状、宿主连接和预渲染检查表 → references/sub-compositions.md。
根必须具有尺寸(静默布局错误)
独立根使用 width/height: 100%。画布大小是 data-width/data-height。运行时将这些像素戳印到组合根上。不要硬编码 #root 上的 1920px/1080px。骨架 → references/minimal-composition.md。
一个暂停的时间线
每个组合在 window.__timelines["<id>"](键 = 根 data-composition-id)处注册恰好一个 gsap.timeline({ paused: true })。在异步回调(document.fonts.ready)内构建它是支持的;重要的是你仅在构建完成后注册。渲染长度是根的 data-duration,而不是时间线的长度:超出它的时间线会被截断,而提前结束的时间线会保持其最后一帧。省略根 data-duration 则长度被推断(时间线、媒体窗口或适配器)。你不需要 window.__timelines = window.__timelines || {}:运行时在你的内联脚本运行之前创建注册表,并且 lint 不再要求它。不要手动将子时间线嵌套到宿主中;运行时会自动嵌套注册的子时间线。完整合约(包括非 GSAP 运行时)→ references/determinism-rules.md + hyperframes-animation/adapters/。
首次运行 lint 陷阱(保证第一次构建失败)
lint 确实会捕获的规则,但仅在事后。第一次就正确编写:
- 永远不要将 CSS 初始
transform与同一属性上的 GSAP tween 配对——CSS 值和 tween 的开始会冲突,并且lint会以gsap_css_transform_conflict拒绝。使用gsap.fromTo(el, { x: -40 }, { x: 0 })在 tween 内部设置初始状态,而不是使用 CSStransform: translateX(-40px)。 - 永远不要在
<video>/<audio>上放置crossorigin。lint会无条件地以media_crossorigin_breaks_preview(错误)拒绝,包括画布/WebGL/WebAudio 回读。没有抑制选项。 - 永远不要给
<video data-start>一个也带有data-start的祖先元素。lint会以video_nested_in_timed_element(错误)拒绝。给包装器或视频计时,而不是两者。 - 每个
<audio>都需要一个id。lint会以media_missing_id拒绝,并且没有id的<audio>永远不会被混合器拾取,因此渲染是静默的。 - 永远不要用
autoAlpha或visibility补间.clip——lint会以gsap_animates_clip_element拒绝。补间子元素。 - 命名的 CSS
font-family需要在文件中有一个@font-face指向提供的本地文件,否则lint会触发font_family_without_font_face。 - 子组合
#root使用width/height: 100%(或inset: 0),而不是硬编码的1920px/1080px。画布大小是data-width/data-height。
lint 错误也会关闭布局和对比度审计:check 然后报告 0 sample(s) 和 0/0 text checks,这看起来像一个干净的文件,但实际上什么也没运行。在信任这些数字之前,请清除 lint 错误。
不可协商的规则(自动化门可能遗漏的静默错误)
在此处提出;完整原理在链接的参考中。不要违反:
- 没有渲染时时钟/未播种的
Math.random/网络/输入状态;没有repeat: -1(使用有限计数)。→determinism-rules.md - 永远不要在
.clip元素上补间display、visibility或autoAlpha。框架拥有剪辑可见性,并且lint会拒绝(gsap_animates_clip_element)。补间子元素。→determinism-rules.md - 正文中没有
<br>;转换后的元素必须是块级 + 有尺寸;脉动的绝对装饰元素需要留出峰值间隙。→determinism-rules.md <video>/<audio>通过扁平文档查询找到,因此框架在任何嵌套深度(包括在子组合<template>或包装器内部)查找和定位它们。一个硬限制:如果<video data-start>位于另一个也带有data-start的普通元素内部,lint会报错,并且失败是真实的(错误的源帧,然后剪辑在中间槽消失),因此将计时放在包装器或视频上,永远不要两者都放。子组合宿主是例外的:子组合内部的媒体可以正确渲染。另一个警告是关于时间线,而不是放置:子组合时间线不能动画宿主根元素。→variables-and-media.md- 确保每个
id在组装后的页面中唯一(为子组合 ID 添加前缀,如#<id>-hero),以便你自己的#idCSS 和getElementById调用能正确解析。帧注入不再依赖于此:编译器会在每个video[src]/audio[src]/img[src]上打上文档唯一的data-hf-render-id。使用<source>子元素而不是src属性的媒体不会被打上标签,因此唯一的 ID 在那里仍然很重要。→composition-patterns.md - 在根组合上的全屏填充在正常渲染时是没问题的。它仅在分层合成路径(HDR 内容,或使用着色器过渡的组合)上被丢弃,其中引擎强制每个组合根透明,以便下方的层能显示。如果你的组合使用着色器过渡或 HDR 媒体,请将填充放在一个全屏子元素上(
position:absolute; inset:0)。→composition-patterns.md
编辑现有组合
- 首先阅读文件。保留无关的计时、轨道、ID、变量、媒体路径。
- 要了解项目时间线上的内容(轨道、剪辑、开始、结束、播放的内容),请运行
npx hyperframes timeline [--json],而不是阅读index.html和每个子组合文件。 - 匹配现有的组合 ID 和时间线键。
- 添加剪辑:根据其周围的剪辑有意图地设置其
data-start/data-duration。data-track-index是一个 Studio 显示通道,不是时间约束,因此它不需要是空闲的。 - 在根
data-duration之后结束的剪辑会被截断:在同一编辑中将根data-duration扩展到剪辑的结束(lint警告clip_ends_past_root_duration)。 - 任何组合元素上的
data-hidden在预览和渲染中都会隐藏它,覆盖其时间窗口;它是非破坏性/可逆的,并由 Studio 的时间线眼睛图标切换。 - 添加子组合:在连接宿主之前验证其内部的
data-composition-id。
验证
使用 hyperframes-cli 获取命令详情
-
npx hyperframes check通过(在 lint、运行时、布局、运动和对比度方面发现 0 个问题) - 包含子组合的项目:
npx hyperframes snapshot --at <midpoints>并目视检查每一帧 -
npx hyperframes preview --background用于审查(用户可以在 Studio 的时间线中编辑任何内容,并且服务器会在调用命令后保持运行) - 仅在用户批准后运行
npx hyperframes render