Community程式設計與開發github.com

HyperFrames

以 HTML 為核心的影片創作技能,支援組合式場景、時間軸動畫與佈局優先的工作流程。

HyperFrames 是什麼?

HyperFrames 是一個專為影片創作設計的 AI 助手技能,適合在 HeyGen、Claude Code、Cursor 等平台上使用。其主要理念是「HTML 是影片的真理源」,透過 HTML 中的 `data-*` 屬性、GSAP 動畫時間軸與 CSS 來定義每個場景的結構與動態。技能強調佈局優先於動畫:先將每個元素放在其最關鍵的可見時刻,再透過 GSAP `from()` 與 `to()` 添加進場與退場效果。它嚴格要求在使用前先定義視覺識別(透過 DESIGN.md 或視覺風格檔案),避免使用預設顏色或字型。為了支援多場景組合,每個場景應作為獨立的絕對定位層,避免共用一個 flex 容器導致內容超出版面。HyperFrames 支援子組合(sub-composition)透過 `<template>` 載入,獨立組合則直接放在 body 中。所有剪輯片段都必須指定 `id`、`data-start`、`data-duration`、`data-track-index` 等屬性,確保時間軸的嚴謹同步。這套工作流程特別適合需要精確控制每個元素出現時間與視覺層級的動畫影片製作者。

相容平台~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. 使用者指定了樣式名稱(例如「Swiss Pulse」、「dark and techy」、「luxury brand」)→ 讀取 visual-styles.md 以查看 8 個命名預設。產生一個精簡的 DESIGN.md,包含:## Style Prompt(一段)、## Colors(3-5 個十六進位值與角色)、## Typography(1-2 個字型家族)、## What NOT to Do(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 來填滿整個場景。使用 padding 將內容向內推 — 絕對不要在內容容器上使用 position: absolute; top: Npx。使用絕對定位的內容容器在內容高於剩餘空間時會造成溢出。position: absolute 僅保留給裝飾性元素使用。
  3. 使用 gsap.from() 加入進場動畫 — 從畫面外/不可見狀態動畫到 CSS 位置。CSS 位置是真理源;補間描述了到達那裡的過程。
  4. 使用 gsap.to() 加入退場動畫 — 從 CSS 位置動畫到畫面外/不可見狀態。

範例

/* scene-content 填滿場景,padding 定位內容 */
.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 等)。
   Padding 定位內容。Flex + gap 處理間距。 */

錯誤 — 硬編碼尺寸與絕對定位:

.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 column, 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/composition 需要填寫秒數。影片/音訊預設為媒體長度。
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 = gsap.timeline({
        paused: true,
        onComplete: () => console.log('組合完成')
      });
      // 在此加入補間動畫
      window.__timelines['my-comp'] = tl;
    </script>
  </div>
</template>

獨立組合結構:

<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
</head>
<body>
  <div data-composition-id="main-comp" data-width="1920" data-height="1080">
    <!-- 內容 -->
    <style>
      [data-composition-id="main-comp"] {
        /* 樣式 */
      }
    </style>
    <script>
      window.__timelines = window.__timelines || {};
      const tl = gsap.timeline({ paused: true });
      // 在此加入補間動畫
      window.__timelines['main-comp'] = tl;
    </script>
  </div>
</body>
</html>

GSAP 時間軸規則

  1. 每個組合一個時間軸:建立 window.__timelines[compositionId]。不要建立多個全域時間軸。
  2. 暫停時間軸:始終使用 paused: true。框架會控制播放。
  3. 相對標籤:使用 "<" 或 "+=N" 來相對於其他補間進行時間控制。
  4. 不要使用 tl.play() 或 tl.reverse():框架會處理這個。
  5. 相依性注入:如果子組合需要使用 GSAP,它必須在 <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script> 中包含 GSAP CDN。不要假設父層級有載入 GSAP。
  6. 不要在全域範圍使用 gsap:始終寫 window.gsap 或從 <script> 標籤載入。在 ESM 環境中匯入 GSAP。

相關技能