hyperframes-compose
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCompose Video
合成视频
HTML is the source of truth for video. A composition is an HTML file with attributes for timing, a GSAP timeline for animation, and CSS for appearance. The framework handles clip visibility, media playback, and timeline sync.
data-*HTML是视频的唯一真实数据源。合成作品是一个包含计时用属性、动画用GSAP时间线、外观用CSS的HTML文件。框架会处理片段可见性、媒体播放和时间线同步。
data-*Approach
实现思路
Before writing HTML, think at a high level:
- What — what should the viewer experience? Identify the narrative arc, key moments, and emotional beats.
- Structure — how many compositions, which are sub-compositions vs inline, what tracks carry what (video, audio, overlays, captions).
- Timing — which clips drive the duration, where do transitions land, what's the pacing.
- Execute — then implement using the rules below.
For small edits (fix a color, adjust timing, add one element), skip straight to the rules.
When no or animation direction is provided, follow house-style.md for motion defaults, sizing, and color palettes.
visual-style.md在编写HTML之前,先从高层梳理需求:
- 内容定位——观众应该获得怎样的体验?梳理叙事脉络、关键节点和情绪节奏。
- 结构设计——需要多少个合成作品,哪些是子合成、哪些是内联内容,不同轨道承载的内容(视频、音频、叠加层、字幕)。
- 时间规划——哪些片段决定总时长,转场的位置在哪里,整体节奏如何。
- 执行实现——按照以下规则进行开发。
如果是小幅修改(修正颜色、调整时长、添加单个元素),可以直接跳过思路环节参照规则执行。
当没有提供或动画方向说明时,动效默认参数、尺寸和调色板请遵循house-style.md的规范。
visual-style.mdData Attributes
数据属性
All Clips
所有片段
| Attribute | Required | Values |
|---|---|---|
| Yes | Unique identifier |
| Yes | Seconds or clip ID reference ( |
| Required for img/div/compositions | Seconds. Video/audio defaults to media duration. |
| Yes | Integer. Same-track clips cannot overlap. |
| No | Trim offset into source (seconds) |
| No | 0-1 (default 1) |
data-track-indexz-index| 属性 | 必填 | 取值 |
|---|---|---|
| 是 | 唯一标识符 |
| 是 | 秒数或者片段ID引用 ( |
| img/div/合成作品必填 | 秒数。视频/音频默认使用媒体本身的时长。 |
| 是 | 整数。同轨道的片段不可重叠。 |
| 否 | 源媒体的裁剪偏移量(秒) |
| 否 | 0-1(默认1) |
data-track-indexz-indexComposition Clips
合成作品片段
| Attribute | Required | Values |
|---|---|---|
| Yes | Unique composition ID |
| Yes | Takes precedence over GSAP timeline duration |
| Yes | Pixel dimensions (1920x1080 or 1080x1920) |
| No | Path to external HTML file |
| 属性 | 必填 | 取值 |
|---|---|---|
| 是 | 唯一的合成作品ID |
| 是 | 优先级高于GSAP时间线的时长 |
| 是 | 像素尺寸(1920x1080 或 1080x1920) |
| 否 | 外部HTML文件路径 |
Composition Structure
合成作品结构
Every composition is a wrapping a with . Each must include its own GSAP script and register its timeline:
<template><div>data-composition-idhtml
<template id="my-comp-template">
<div data-composition-id="my-comp" data-width="1920" data-height="1080">
<!-- content -->
<style>
[data-composition-id="my-comp"] {
/* scoped styles */
}
</style>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<script>
window.__timelines = window.__timelines || {};
const tl = gsap.timeline({ paused: true });
// tweens...
window.__timelines["my-comp"] = tl;
</script>
</div>
</template>Load in root:
<div id="el-1" data-composition-id="my-comp" data-composition-src="compositions/my-comp.html" data-start="0" data-duration="10" data-track-index="1"></div>每个合成作品都是一个标签包裹的带属性的。每个合成作品必须包含自己的GSAP脚本并注册其时间线:
<template>data-composition-id<div>html
<template id="my-comp-template">
<div data-composition-id="my-comp" data-width="1920" data-height="1080">
<!-- content -->
<style>
[data-composition-id="my-comp"] {
/* scoped styles */
}
</style>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<script>
window.__timelines = window.__timelines || {};
const tl = gsap.timeline({ paused: true });
// tweens...
window.__timelines["my-comp"] = tl;
</script>
</div>
</template>在根文件中加载:
<div id="el-1" data-composition-id="my-comp" data-composition-src="compositions/my-comp.html" data-start="0" data-duration="10" data-track-index="1"></div>Video and Audio
视频与音频
Video must be . Audio is always a separate element:
muted playsinline<audio>html
<video
id="el-v"
data-start="0"
data-duration="30"
data-track-index="0"
src="video.mp4"
muted
playsinline
></video>
<audio
id="el-a"
data-start="0"
data-duration="30"
data-track-index="2"
src="video.mp4"
data-volume="1"
></audio>视频必须设置。音频始终使用独立的元素:
muted playsinline<audio>html
<video
id="el-v"
data-start="0"
data-duration="30"
data-track-index="0"
src="video.mp4"
muted
playsinline
></video>
<audio
id="el-a"
data-start="0"
data-duration="30"
data-track-index="2"
src="video.mp4"
data-volume="1"
></audio>Timeline Contract
时间线约定
- All timelines start — the player controls playback
{ paused: true } - Register every timeline:
window.__timelines["<composition-id>"] = tl - Framework auto-nests sub-timelines — do NOT manually add them
- Duration comes from , not from GSAP timeline length
data-duration - Never create empty tweens to set duration
- 所有时间线初始状态为——由播放器控制播放
{ paused: true } - 每个时间线都要注册:
window.__timelines["<composition-id>"] = tl - 框架会自动嵌套子时间线——请勿手动添加
- 时长以为准,而非GSAP时间线的长度
data-duration - 绝对不要创建空补间动画来设置时长
Rules (Non-Negotiable)
硬性规则
Deterministic: No , , or time-based logic. The renderer must produce identical output every time.
Math.random()Date.now()GSAP: Only animate visual properties (, , , , , , , , transforms). Do NOT animate , , or call /.
opacityxyscalerotationcolorbackgroundColorborderRadiusvisibilitydisplayvideo.play()audio.play()Animation conflicts: Never animate the same property on the same element from multiple timelines simultaneously — causes flickering in headless renders.
Never do:
- Forget registration
window.__timelines - Use video for audio — always muted video + separate
<audio> - Nest video inside a timed div — use a non-timed wrapper
- Use (use
data-layer) ordata-track-index(usedata-end)data-duration - Animate video element dimensions — animate a wrapper div
- Call play/pause/seek on media — framework owns playback
- Create a top-level container without
data-composition-id
确定性:不得使用、或者基于时间的逻辑。渲染器每次运行必须生成完全一致的输出。
Math.random()Date.now()GSAP:仅可对视觉属性做动画(、、、、、、、、变换属性)。请勿对、做动画,也不要调用/。
opacityxyscalerotationcolorbackgroundColorborderRadiusvisibilitydisplayvideo.play()audio.play()动画冲突:不要同时从多个时间线对同一个元素的同一个属性做动画——会导致无头渲染时出现闪烁。
绝对禁止操作:
- 忘记注册
window.__timelines - 用视频承载音频——始终使用静音视频+独立的组合
<audio> - 将视频嵌套在带计时属性的div中——请使用不带计时属性的容器包裹
- 使用(请用
data-layer)或者data-track-index(请用data-end)data-duration - 对视频元素的尺寸做动画——对包裹它的div做动画即可
- 对媒体调用play/pause/seek方法——播放逻辑由框架管控
- 创建不带的顶层容器
data-composition-id
Editing Existing Compositions
编辑现有合成作品
- Read the full composition first — match existing fonts, colors, animation patterns
- Only change what was requested — don't rewrite untouched sections
- Don't rewrite entire files for small changes
- Preserve timing of unrelated clips
- 先通读完整的合成作品代码——匹配现有的字体、颜色、动效模式
- 仅修改需求指定的内容——不要重写未涉及的部分
- 不要为了小幅改动就重写整个文件
- 保留不相关片段的时间设置
Typography and Assets
排版与资源
- Every composition loads its own fonts (or
@importin@font-face)<style> - Use for local fonts — renderer needs fonts loaded before capturing
font-display: block - Add to media loaded from external URLs
crossorigin="anonymous" - Minimum readable text: 20px landscape, 18px portrait
- All files (video, audio, fonts, images) live at the project root alongside
index.html - From sub-compositions, use to reference root files
../
For PiP, title cards, and slide show patterns, see patterns.md.
For data, stats, and infographics, see data-in-motion.md.
- 每个合成作品自行加载字体(在中使用
<style>或者@import)@font-face - 本地字体请设置——渲染器需要在捕获帧之前加载完成字体
font-display: block - 从外部URL加载的媒体需要添加属性
crossorigin="anonymous" - 最小可读文字尺寸:横屏20px,竖屏18px
- 所有文件(视频、音频、字体、图片)都存放在项目根目录,和同级
index.html - 子合成作品中引用根目录文件请使用路径
../
如需了解画中画、标题卡、幻灯片等模式,请参考patterns.md。
如需了解数据、统计信息、信息图表相关内容,请参考data-in-motion.md。
Output Checklist
输出检查清单
- Every top-level container has
data-composition-id - Every composition has ,
data-width,data-heightdata-duration - Compositions in own HTML files, loaded via
data-composition-src - wrapper on sub-compositions
<template> - registered for every composition
window.__timelines - 100% deterministic — no randomness
- Each composition includes GSAP:
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
- 所有顶层容器都带有
data-composition-id - 所有合成作品都设置了、
data-width、data-heightdata-duration - 合成作品存放在独立的HTML文件中,通过加载
data-composition-src - 子合成作品外层包裹了标签
<template> - 每个合成作品都注册了
window.__timelines - 100%确定性——无任何随机逻辑
- 每个合成作品都引入了GSAP:
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>