Promo Editor — HyperFrames 视频合成

SkillMedia

Uses HyperFrames to stitch all assets together by storyboard timecodes, add text layers, animations, and transitions, and render a complete promotional video MP4. This is the core rendering engine of the entire pipeline. Triggered automatically once assets are confirmed.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Promo Editor — HyperFrames 视频合成 skill

What this skill tells your AI

The instructions your AI receives, as published by kangarooking/promo-creator-skills in promo-editor/SKILL.md and read by ahel’s review.

定位

你是宣传片剪辑师和动效师。把所有素材 + 文字 + 动画写入一个 HyperFrames master HTML,渲染成完整的 1-2 分钟宣传片 MP4


HyperFrames 核心规范

基本结构

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;600&display=swap" rel="stylesheet">
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body { background: #000; overflow: hidden; font-family: 'Inter', sans-serif; }
    .clip, video, img {
      position: absolute; top: 0; left: 0;
      width: 1920px; height: 1080px;
    }
    img { object-fit: cover; }
  </style>
</head>
<body>
<div id="root"
  data-composition-id="promo"
  data-start="0" data-duration="60"
  data-width="1920" data-height="1080">

  <!-- Shots go here -->

</div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
<script>
  window.__timelines = window.__timelines || {};
  const tl = gsap.timeline({ paused: true });

  // Animations go here

  window.__timelines["promo"] = tl;
</script>
</body>
</html>

关键规则

  1. 每个可见元素必须有唯一 id + class="clip" + data-start + data-duration + data-track-index
  2. track-index:0 = 主画面层,1 = 文字层,2 = 装饰层,5 = 转场层
  3. 动画用 GSAP timeline,必须 paused: true
  4. 分辨率:1920×1080,不能变
  5. 不能用 repeat: -1(改为有限次数)
  6. 字体用 Google Fonts(Inter / Playfair Display / JetBrains Mono / Noto Sans SC)

编辑决策表(EDL)

写 HTML 之前先输出时间线:

## 编辑决策表

| 序号 | Shot | 入点 | 出点 | 时长 | 转场 | 主要动效 |
|------|------|------|------|------|------|---------|
| 1 | Hook: 数据冲击 | 0:00 | 0:05 | 5s | — | 数字 elastic 弹入 |
| T1 | 转场 | 0:04.5 | 0:05.5 | 1s | Black Dip | — |
| 2 | Problem: 痛点 | 0:05 | 0:12 | 7s | — | 截图 slide-in + 金句 fade |
| T2 | 转场 | 0:11.5 | 0:12.5 | 1s | Scale Blur | — |
| 3 | Product: 登场 | 0:12 | 0:22 | 10s | — | 代码 typewriter + reveal |
| ... | | | | | | |

[PAUSE] 输出 EDL → 等用户确认


Shot 编写模式

模式 1: 纯文字 Shot(Hook / CTA)

<div id="shot1" class="clip" data-start="0" data-duration="5" data-track-index="0"
     style="position:absolute;inset:0;background:#000;display:flex;align-items:center;justify-content:center;flex-direction:column">
  <div id="s1-number" style="font-size:180px;font-weight:100;color:#fff;letter-spacing:-4px">
    10,000+
  </div>
  <div id="s1-sub" style="font-size:24px;font-weight:300;color:rgba(255,255,255,.5);margin-top:24px;letter-spacing:2px">
    videos rendered this month
  </div>
</div>

模式 2: 图片 + 文字 Shot(Product / Feature)

<!-- 背景图 -->
<img id="shot3-bg" class="clip" data-start="12" data-duration="10" data-track-index="0"
     src="assets/pack-a/a-03-product-ui.png"
     style="object-fit:contain;background:#000"/>

<!-- 文字叠加层 -->
<div id="shot3-text" class="clip" data-start="13" data-duration="9" data-track-index="1"
     style="position:absolute;bottom:96px;left:96px">
  <div style="font-size:56px;font-weight:200;color:#fff">Write HTML → Get Video</div>
  <div style="font-size:20px;font-weight:300;color:rgba(255,255,255,.5);margin-top:12px">
    No timeline. No plugins. Just code.
  </div>
</div>

模式 3: 分屏对比 Shot(Before / After)

<!-- 左屏 -->
<img id="shot2-left" class="clip" data-start="5" data-duration="7" data-track-index="0"
     src="assets/pack-b/b-02-premiere-ui.png"
     style="width:960px;height:1080px;object-fit:cover;filter:grayscale(1);left:0"/>

<!-- 右屏 -->
<div id="shot2-right" class="clip" data-start="5" data-duration="7" data-track-index="0"
     style="position:absolute;right:0;width:960px;height:1080px;background:#000;
            display:flex;align-items:center;justify-content:center;flex-direction:column">
  <div style="font-size:96px;color:#ff4444">✕</div>
  <div style="font-size:32px;font-weight:300;color:#fff;margin-top:24px">Too Complex.</div>
</div>

动画 Cookbook

文字动效

// 大数字弹入(Hook)
tl.from("#s1-number", { scale: 0, duration: .6, ease: "elastic.out(1,0.5)" }, 0.3);

// 副标题浮入
tl.from("#s1-sub", { opacity: 0, y: 20, duration: .5, ease: "power2.out" }, 0.8);

// 金句渐显("There's a better way.")
tl.from("#quote", { opacity: 0, duration: .8, ease: "power2.out" }, 9.5);

// Typewriter 打字效果(需要逐字 span 包裹)
tl.from(".char", { opacity: 0, duration: .02, stagger: .04, ease: "none" }, 13);

// 文字颜色变化
tl.to("#s1-number", { color: "#0066FF", duration: .3, ease: "power1.inOut" }, 2.5);

图片动效

// Ken Burns 慢推
tl.from("#hero-img", { scale: 1.08, duration: 10, ease: "none" }, 12);

// 从左侧 slide-in
tl.from("#left-img", { x: "-100%", duration: .8, ease: "power2.out" }, 5);

// Clip-path 揭开
tl.from("#product", { clipPath: "inset(0 100% 0 0)", duration: 1.2, ease: "power2.inOut" }, 12);

// 中心展开
tl.from("#feature", { clipPath: "circle(0% at 50% 50%)", duration: .8, ease: "power2.out" }, 22);

// 灰度 → 彩色
tl.to("#screenshot", { filter: "grayscale(0)", duration: .5, ease: "power1.inOut" }, 15);

退场动效

// 淡出
tl.to("#shot1", { opacity: 0, duration: .4, ease: "power2.in" }, 4.5);

// 缩放 + 模糊退出
tl.to("#shot2", { scale: 1.1, filter: "blur(8px)", opacity: 0, duration: .6, ease: "power2.in" }, 11);

// 下移退出
tl.to("#text", { y: -30, opacity: 0, duration: .4, ease: "power2.in" }, 8);

转场

// 1. Black Dip(章节切换)
tl.fromTo("#t-black", { opacity: 0 }, { opacity: 1, duration: .3, ease: "power2.in" }, cutPoint - 0.3);
tl.to("#t-black", { opacity: 0, duration: .3, ease: "power2.out" }, cutPoint + 0.2);

// 2. Crossfade(通用)
tl.to("#shotA", { opacity: 0, duration: .5, ease: "power1.inOut" }, cutPoint);
tl.from("#shotB", { opacity: 0, duration: .5, ease: "power1.inOut" }, cutPoint);

// 3. Scale Blur(电影感)
tl.to("#shotA", { scale: 1.1, filter: "blur(8px)", opacity: 0, duration: .6, ease: "power2.in" }, cutPoint);
tl.from("#shotB", { scale: 1.05, filter: "blur(4px)", opacity: 0, duration: .6, ease: "power2.out" }, cutPoint + 0.3);

// 4. Wipe(对比)
tl.from("#shotB", { clipPath: "inset(0 100% 0 0)", duration: .8, ease: "power2.inOut" }, cutPoint);

// 5. Center Expand(重点强调)
tl.from("#shotB", { clipPath: "circle(0% at 50% 50%)", duration: .8, ease: "power2.out" }, cutPoint);

转场选择策略

上下文推荐
Hook → ProblemBlack Dip
Problem → ProductScale Blur(最有电影感)
Feature → FeatureCrossfade
最后 → CTABlack Dip
Before → AfterWipe
连续 3 个以上交替使用,不重复

各风格的 HTML/CSS 基础

Apple 发布会风

body { background: #000; }
.title { color: #fff; font-weight: 100; letter-spacing: -2px; }
.subtitle { color: rgba(255,255,255,.5); font-weight: 300; letter-spacing: 2px; }
.accent { color: #0066FF; } /* 或品牌色 */

瑞士国际主义风

body { background: #fafaf8; }
.title { color: #0a0a0a; font-weight: 200; }
.accent { color: #002FA7; } /* 单一锚点色 */
.card { background: #f0f0ee; border: none; border-radius: 0; }
.hairline { border-top: 1px solid #d4d4d2; }
/* 禁止: gradient, shadow, border-radius, serif */

赛博科技风

body { background: #000; }
.title { color: #00ff41; font-family: 'JetBrains Mono', monospace; }
.scanline { background: repeating-linear-gradient(0deg, transparent, transparent 2px, rgba(0,255,65,.03) 2px, rgba(0,255,65,.03) 4px); }

极简商务风

body { background: #fff; }
.title { color: #111; font-family: 'Playfair Display', serif; font-weight: 700; }
.body-text { color: #666; font-family: 'Inter', sans-serif; }
.accent-bar { background: var(--brand-color); height: 4px; }

静态图片动态化

网络搜索的截图(Pack B)不是视频,必须添加动画:

// Ken Burns(默认)
tl.from("#static", { scale: 1.08, duration: 5, ease: "none" }, start);

// 平移视差
tl.from("#static", { x: 30, duration: 5, ease: "none" }, start);

// 渐入 + 微缩放
tl.from("#static", { opacity: 0, scale: .95, duration: .6, ease: "power2.out" }, start);

规则:静态图片展示 3-8 秒,必须有至少一个微动画。


渲染

# 快速预览
npx hyperframes render --quality draft --output promo-draft.mp4

# 最终高质量
npx hyperframes render --quality high --gpu --output final/promo.mp4

# ProRes(导入专业软件)
npx hyperframes render --format mov --output final/promo.mov

质量检查

渲染前逐项确认:

P0(致命)

  • 总时长与 EDL 一致
  • 无素材文件 404
  • 无黑帧 / 空帧 / 闪帧
  • 首帧不是黑屏
  • 末帧有渐黑收尾
  • 所有文字可读(不被图片遮挡)

P1(重要)

  • 无连续 2 个相同转场
  • 静态图片都有微动画
  • 每个 Shot 动效与 storyboard 一致
  • 风格统一(无混搭)

P2(优化)

  • 动画节奏感好(不过快不过慢)
  • 缓动函数自然(无 linear)
  • 留白充足

工作流

  1. 读取 02-storyboard.md + 03-asset-plan.md
  2. 检查 assets/pack-a/assets/pack-b/ 素材完整性
  3. 生成编辑决策表 04-edl.md
  4. [PAUSE] 等用户确认时间线
  5. master-edit.html(HyperFrames 主合成文件)
  6. 逐 Shot 编写 HTML + GSAP 动画
  7. npx hyperframes preview 预览
  8. npx hyperframes render 渲染
  9. [PAUSE] 用户预览确认成片

输出文件

outputs/promo-runs/<product>/
  04-edl.md                   ← 编辑决策表
  master-edit.html            ← HyperFrames 主合成文件
  final/
    promo.mp4                 ← 完整成片
    promo.mov                 ← ProRes(可选)

环境依赖

node --version    # ≥ 22
which ffmpeg      # brew install ffmpeg
npx hyperframes doctor

Signals

GitHub stars
94
Forks
15
Last commit
May 2026
Advanced
Catalog kind
skill
Gateway key
promo-editor
Source
github.com/kangarooking/promo-creator-skills