Community编程与开发github.com

HyperFrames

HTML优先的视频创作技能,用于构建带GSAP动画的时间轴合成视频。

HyperFrames 是什么?

HyperFrames 是一个面向 AI 代理(如 Claude Code、Cursor、Codex)的 HTML 视频合成创作技能。它以 HTML 为视频的唯一真实来源,通过 `data-*` 属性定义时序、GSAP 时间轴驱动动画、CSS 控制外观的合成(composition)文件来生成视频。该技能强调先完成“布局前置动画”的流程:先将每个场景的“英雄帧”(即元素最完整可见的时刻)用静态 CSS 排好版,避免因猜测最终位置导致的意外重叠,然后再添加 GSAP 的入场和退场动画。技能内置了严格的“视觉标识门控”机制,要求在任何创作开始前定义 DESIGN.md(包括配色、字体、运动规则),并提供了 `visual-styles.md` 风格库供选用。它支持主合成和子合成(通过 `<template>` 加载外部 HTML)两种模式,通过 `data-track-index` 管理轨道堆叠、使用 `position: absolute; inset: 0` 的独立场景容器解决多场景内容中的高度溢出问题。该技能适用于在 Claude Code、Cursor、Codex 等 AI 编码工具中生成可预览的信息型短片或品牌宣传视频。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add OpenMinis/MinisSkills

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

HyperFrames 是做什么的?

首次使用? 在开始之前先运行环境检查:

python3 /var/minis/skills/hyperframes-cli/scripts/check-env.py

这将验证 minis-browser-use、ffmpeg 以及所需技能是否已安装。 如果缺少 hyperframes-cli 技能,请安装它:

python3 /var/minis/skills/hyperframes-cli/scripts/install-skill.py \
  hyperframes-cli --repo heygen-com/hyperframes --subdir skills

HTML 是视频的唯一真实来源。合成(composition)是一个包含用于时序的 data-* 属性、用于动画的 GSAP 时间轴以及用于外观的 CSS 的 HTML 文件。框架负责处理剪辑可见性、媒体播放和时间轴同步。

方法

在编写 HTML 之前,先从高级别思考:

  1. 什么 — 观众应该体验到什么?识别叙事弧线、关键时刻和情感节拍。
  2. 结构 — 有多少个合成,哪些是子合成哪些是内联,哪些轨道承载什么(视频、音频、叠加层、字幕)。
  3. 时序 — 哪些剪辑驱动持续时间,过渡落在何处,节奏如何。
  4. 布局 — 先构建最终状态。请参阅下面的“布局前置动画”。
  5. 动画 — 然后使用下面的规则添加运动。

对于小改动(修复颜色、调整时序、添加一个元素),直接跳到规则部分。

视觉标识门控

按此顺序检查:

  1. 项目中存在 DESIGN.md? → 读取它。使用其确切的颜色、字体、运动规则和“不要做的事情”。
  2. 存在 visual-style.md? → 读取它。应用其 style_prompt_full 和结构化字段。(注意:visual-style.md 是项目特定的文件。visual-styles.md 是包含 8 个命名预设的风格库 — 不同的文件。)
  3. 用户命名了一种风格(例如“瑞士脉冲”、“黑暗与科技”、“奢侈品牌”)? → 读取 visual-styles.md 中的 8 个命名预设。生成一个最小的 DESIGN.md,包含:## 风格提示(一段)、## 颜色(3-5 个带有角色的十六进制值)、## 排版(1-2 个字体系列)、## 不要做的事情(3-5 个反模式)。
  4. 以上都没有? → 在编写任何 HTML 之前询问 3 个问题:
    • 氛围是什么?(爆炸性 / 电影感 / 流畅 / 技术性 / 混乱 / 温暖)
    • 浅色还是深色画布?
    • 是否有任何特定的品牌颜色、字体或视觉参考? 然后根据答案生成一个最小的 DESIGN.md。

每个合成必须将其调色板和排版追溯到一个 DESIGN.md、visual-style.md 或明确的用户指示。如果你正要用 #333、#3b82f6 或 Roboto — 你跳过了这个步骤。

对于运动默认值、尺寸、入场模式和时间曲线 — 请遵循 house-style.md。house style 处理事物如何移动。DESIGN.md 处理事物外观。

布局前置动画

将每个元素定位在其最可见的时刻 — 即它完全进入、正确放置且尚未退出的帧。首先将其编写为静态 HTML+CSS。暂时不要添加 GSAP。

为什么这很重要: 如果你将元素定位在其动画起始状态(屏幕外、缩放为 0、透明度 0)并过渡到你认为它们应该落到的位置,你是在猜测最终布局。重叠直到视频渲染时才可见。通过先构建最终状态,你可以在添加任何运动之前看到并修复布局问题。

流程

  1. 识别每个场景的英雄帧 — 大多数元素同时可见的时刻。这是你要构建的布局。
  2. 为该帧编写静态 CSS。.scene-content 容器必须使用 width: 100%; height: 100%; padding: Npx; 并带有 display: flex; flex-direction: column; gap: Npx; box-sizing: border-box 来完全填充场景。使用内边距将内容向内推 — 永远不要使用 position: absolute; top: Npx 在内容容器上。绝对定位的内容容器在内容高于剩余空间时会溢出。仅保留 position: absolute 给装饰元素。
  3. 使用 gsap.from() 添加入场 — 从屏幕外/不可见 动画到 CSS 位置。CSS 位置是真实依据;补间描述到达那里的旅程。
  4. 使用 gsap.to() 添加退场 — 从 CSS 位置动画到屏幕外/不可见。

示例

/* scene-content 填充场景,内边距定位内容 */
.scene-content {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 120px 160px;
  gap: 24px;
  box-sizing: border-box;
}
.title {
  font-size: 120px;
}
.subtitle {
  font-size: 42px;
}
/* 容器填充任何场景尺寸(1920x1080、1080x1920 等)。
   内边距定位内容。Flex + 间距处理间距。 */

错误 — 硬编码尺寸和绝对定位:

.scene-content {
  position: absolute;
  top: 200px;
  left: 160px;
  width: 1920px;
  height: 1080px;
  display: flex; /* ... */
}
// 步骤 3:动画进入这些位置
tl.from(".title", { y: 60, opacity: 0, duration: 0.6, ease: "power3.out" }, 0);
tl.from(".subtitle", { y: 40, opacity: 0, duration: 0.5, ease: "power3.out" }, 0.2);
tl.from(".logo", { scale: 0.8, opacity: 0, duration: 0.4, ease: "power2.out" }, 0.3);

// 步骤 4:从这些位置动画退出
tl.to(".title", { y: -40, opacity: 0, duration: 0.4, ease: "power2.in" }, 3);
tl.to(".subtitle", { y: -30, opacity: 0, duration: 0.3, ease: "power2.in" }, 3.1);
tl.to(".logo", { scale: 0.9, opacity: 0, duration: 0.3, ease: "power2.in" }, 3.2);

多场景合成:每个场景一个容器

当合成包含多个按顺序出现的场景(A 退出,然后 B 进入)时,永远不要将所有场景的元素放在一个共享的 flex 容器中。即使每个元素以 opacity: 0 开始,flex 仍然为每个子元素分配高度。如果一个容器中有 5 个场景的内容,容器的总高度将远远超过舞台高度 — 然后 flex justify-content: center 会相对于这个过大的容器居中内容,将可见内容推出屏幕截图裁剪区域。

错误 — 所有场景在一个 flex 容器中:

<div class="scene-content"> <!-- flex 列,height:100% -->
  <!-- 场景 A 元素 -->
  <div id="title-a" style="opacity:0">标题 A</div>
  <div id="body-a"  style="opacity:0">正文 A</div>
  <!-- 场景 B 元素 — 即使在不可见时也占用 flex 高度 -->
  <div id="title-b" style="opacity:0">标题 B</div>
  <div id="body-b"  style="opacity:0">正文 B</div>
  <!-- 场景 C ... -->
</div>

正确 — 每个场景是独立的绝对层:

<!-- 场景 A -->
<div class="scene" id="scene-a">
  <div id="title-a" style="opacity:0">标题 A</div>
  <div id="body-a"  style="opacity:0">正文 A</div>
</div>
<!-- 场景 B — 对场景 A 的高度影响为零 -->
<div class="scene" id="scene-b">
  <div id="title-b" style="opacity:0">标题 B</div>
  <div id="body-b"  style="opacity:0">正文 B</div>
</div>
/* 每个场景独立填充舞台 */
.scene {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  padding: 80px 120px;
  box-sizing: border-box;
  z-index: 2;
  gap: 24px;
}

这是顺序场景唯一正确的模式。每个场景容器上的 position: absolute; inset: 0 与“布局前置动画”指南不冲突 — 该指南禁止在硬编码像素偏移上对内容元素(标题、卡片、统计数据)使用绝对定位。通过 inset: 0 填充完整舞台的场景容器是正确的且是必需的。

当元素随时间共享空间时

如果元素 A 在元素 B 进入同一区域之前退出,两者都应为各自的英雄帧设置正确的 CSS 位置。时间轴顺序保证它们永远不会同时可见 — 但如果你跳过布局步骤,你将无法捕获因时序错误而导致它们意外重叠的情况。

什么算作有意重叠

分层效果(文本后的发光、阴影元素、背景图案)和 z 轴堆叠设计(卡片堆叠、深度层)是有意的。布局步骤是关于捕获意外重叠 — 两个标题彼此重叠、一个统计数据覆盖标签、内容溢出画框。

数据属性

所有剪辑

属性必填值
id是唯一标识符
data-start是秒数或剪辑 ID 引用("el-1"、"intro + 2")
data-durationimg/div/compositions 必填秒。视频/音频默认为媒体持续时间。
data-track-index是整数。同一轨道的剪辑不能重叠。
data-media-start否源文件的修剪偏移量(秒)
data-volume否0-1(默认为 1)

data-track-index 不影响视觉分层 — 使用 CSS z-index。

合成剪辑

属性必填值
data-composition-id是唯一的合成 ID
data-start是开始时间(根合成:使用 "0")
data-duration是优先级高于 GSAP 时间轴持续时间
data-width / data-height是像素尺寸(1920x1080 或 1080x1920)
data-composition-src否外部 HTML 文件的路径

合成结构

通过 data-composition-src 加载的子合成都使用 <template> 包装器。独立合成(主 index.html)不使用 <template> — 它们将 data-composition-id 的 div 直接放在 <body> 中。在独立文件上使用 <template> 会隐藏浏览器的所有内容并破坏渲染。

子合成结构:

<template id="my-comp-template">
  <div data-composition-id="my-comp" data-width="1920" data-height="1080">
    <!-- 内容 -->
    <style>
      [data-composition-id="my-comp"] {
        /* 作用域样式 */
      }
    </style>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
    <script>
      window.__timelines = window.__timelines || {};
      const tl =

相关技能