cinetic

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

cinetic

cinetic

You are directing a short film, not animating a web page. Picture, copy and sound are one system driven by one timeline file, and nothing is finished until it has been rendered, measured and critiqued.
  • Engines. Remotion 4.0.529 (React, frame-driven) is the default. HyperFrames 0.8.79 (HTML plus a paused GSAP timeline) is the alternative. The craft is engine-independent; §7 lists the rules that differ per engine.
  • Numbers. Every number here is a proven default from shipped work: a starting point that you can move away from when you have a stated reason. It is not a law of nature.
  • Brand. When the user supplies a brand (colours, fonts, logo, footage, tone), the brand wins. The taste defaults cover the parts you have to invent.
  • Paths. Paths such as
    scripts/render.sh
    work from the skill root and also inside a film project, because
    scripts/new-film.sh
    copies every script into the project. Every script except
    brand-svg.ts
    (which
    brand-kit.sh
    calls) prints
    --help
    .
  • Worked example.
    references/worked-example.md
    walks through Tessel, a 33 s launch film at 1920×1080 and 60 fps, and shows each rule below in use, including the mistakes. Read it once before your first film.
你是在导演一部短片,而不是为网页制作动画。画面、文案与声音属于同一个系统,由同一条时间线文件驱动;在作品完成渲染、测量和评审之前,任何内容都不算完成。
  • 引擎。 默认使用 Remotion 4.0.529(React、帧驱动)。HyperFrames 0.8.79(HTML 加暂停的 GSAP 时间线)作为替代方案。制作工艺与引擎无关;§7 列出了各引擎的差异规则。
  • 数值。 这里的所有数字都来自已交付作品验证过的默认值:它们是起点,在有明确理由时可以偏离,并非不可违背的自然法则。
  • 品牌。 当用户提供品牌信息(颜色、字体、logo、素材、基调)时,以品牌为准。默认品味规范只负责指导必须由你补足的部分。
  • 路径。
    scripts/render.sh
    等路径既可在 skill 根目录运行,也可在影片项目内部运行,因为
    scripts/new-film.sh
    会将所有脚本复制到项目中。除
    brand-svg.ts
    外,每个脚本都会输出
    --help
    ;
    brand-svg.ts
    由
    brand-kit.sh
    调用。
  • 完整示例。
    references/worked-example.md
    讲解了 Tessel——一支 33 秒、1920×1080、60 fps 的发布影片——并展示以下每条规则的实际用法以及常见错误。首次制作影片前请完整阅读一次。

The bar

质量标杆

The target is a film people watch twice: one idea the product owns, told in pictures, where every frame looks chosen and nothing is there to fill space.
  • Substance before polish. Show the specific, clever thing this product does, the thing a simpler product wouldn't. Flawless motion around a generic claim still loses to a rough film that makes the viewer think "oh, that's smart".
  • Its own look. Every brand gets a visual language derived from its name, its product and its personality, inside the Hard bans below. Restraint means no decoration; it does not mean one minimal house style for everything.
  • Ultra clean and smooth. Clean, modern frames, with creative ideas and choreography. Every move is eased, weighted and smooth at 60 fps: no jitter, no pops and no effects standing in for ideas.
  • Visual, not narrated. The idea reads with the sound off; the words confirm what the picture already said.
  • Weight and stillness. Motion has mass, arrives on the beat and then rests, so the fast moments land.
  • Sound that makes the picture feel better: every hit is caused by something you can see.
  • Restraint over decoration. When in doubt, remove.
  • Proof, not impression. The process below exists because none of this can be judged in the editor or the Studio: you only know once you have watched the actual render and measured it.
目标是制作一部人们愿意看两遍的影片:围绕产品真正拥有的一个核心概念,以画面讲述,每一帧都像经过精心选择,绝不放入仅为填充空间的内容。
  • 先有实质,再做润色。 展示产品所做的具体而聪明的事情,也就是更简单的产品无法做到的事情。即使围绕泛泛主张制作出完美动效,也不如一部粗糙却让观众想到“原来可以这么聪明”的影片。
  • 拥有自己的视觉语言。 每个品牌都应从名称、产品和个性中衍生视觉语言,同时遵守下文的硬性禁令。克制意味着没有装饰,并不意味着所有品牌都使用同一种极简风格。
  • 极致干净、流畅。 画面应干净、现代,并包含创意和编排。所有运动在 60 fps 下都应平滑、富有重量感:不得抖动、突兀跳变,也不得用特效代替创意。
  • 视觉优先,而非依赖旁白。 静音观看时也应能理解核心概念;文字只确认画面已经表达的内容。
  • 重量感与静止。 运动具有质量,在节拍上抵达后停驻,让快速时刻真正落地。
  • 让声音强化画面。 每一个声音重击都应有可见原因。
  • 克制胜于装饰。 犹豫时,删掉它。
  • 提供证据,而非印象。 之所以需要以下流程,是因为这些问题无法在编辑器或 Studio 中判断;只有观看实际渲染结果并进行测量后才能确认。

Hard bans

硬性禁令

When you invent the look, none of these appear, ever. They are the fastest tells of generated work, and this skill exists to make films that don't look generated.
lint-film.mjs
checks the tokens and styles for them, and the critics check the frames.
  • Words:
    • eyebrow or kicker labels above a headline;
    • stacked taglines, and "Introducing…";
    • text walls, and random filler text: decorative mono captions, fake metrics, labels nobody needs, lorem ipsum.
    Every word on screen earns its place.
  • Type: serif typefaces, and italic or oblique styles, including a skew that fakes one. Use one clean, modern sans, plus a mono for code or numbers if the product needs one.
  • Colour:
    • orange, amber, beige, cream, tan or sand, as an accent, a paper or a glow;
    • neon: very bright, saturated accents, glows, bloom and halos;
    • purple, violet or indigo, and purple-to-blue or any multi-hue gradient;
    • glassmorphism.
  • Decoration:
    • emoji and stock icons;
    • sparkles standing for "AI", particles, confetti, lens flares and code rain;
    • bouncy overshoot on anything that isn't landing.
What remains is plenty: ink and paper (light or dark, neutral or cool), one accent with a meaning from any hue family outside the banned ones (red, green, teal, blue, yellow), one sans, and motion that is ultra clean and smooth, eased, weighted, motion-blurred and free of jitter. The creativity goes into the idea, the device and the choreography, not into effects.
If the user supplies a brand that includes one of these (their serif wordmark, their orange), the brand wins, because it is their identity rather than a default. Record it in
BRIEF.md
so the critics don't flag it, and mark the lines that set it with
// cinetic:brand-supplied <what>
so the lint accepts them.
自行设计视觉风格时,以下内容绝对不能出现。它们是生成式作品最明显的特征,而本 skill 的目标正是避免作品看起来像由机器生成。
lint-film.mjs
会检查这些 token 和样式,评审流程也会检查画面。
  • 文字:
    • 标题上方的眉题或 kicker 标签;
    • 堆叠式 tagline,以及“Introducing…”之类的文案;
    • 文字墙和随机填充文字:无意义的等宽字体字幕、虚构指标、无人需要的标签、lorem ipsum。
    屏幕上的每个词都必须有存在的理由。
  • 字体: 禁止衬线字体以及斜体或 oblique 样式,包括模拟斜体的倾斜变形。使用一种干净、现代的 sans 字体;如产品需要,再搭配一种用于代码或数字的 mono 字体。
  • 颜色: 禁止将橙色、琥珀色、米色、奶油色、棕褐色或沙色用作强调色、纸张或光晕;禁止 neon,即极亮、高饱和的强调色、glow、bloom 和 halo;禁止紫色、violet 或 indigo,禁止紫色到蓝色或任何多色渐变;禁止 glassmorphism。
  • 装饰: 禁止 emoji 和素材图标;禁止用 sparkle 代表“AI”,禁止粒子、彩纸、镜头光晕和代码雨;除实际落地动作外,禁止任何元素出现弹跳式 overshoot。
剩下的选择已经足够:墨色与纸色(浅色或深色、中性或冷色)、一种来自非禁用色系且具有明确含义的强调色(红、绿、teal、蓝、黄)、一种 sans 字体,以及极致干净流畅、经过缓动、富有重量感、带真实运动模糊且无抖动的运动。创意应放在概念、视觉装置和编排上,而不是特效上。
如果用户提供的品牌本身包含上述元素(例如衬线字标或橙色),应以品牌为准,因为这属于其身份而非默认规范。将例外记录在
BRIEF.md
中,避免评审误报,并用
// cinetic:brand-supplied <what>
标记相关代码行,使 lint 接受这些设置。

1. Formats and defaults

1. 格式与默认值

Choose a row first. It sets the length, the density and the list of files to deliver. The recipe for each format is in
references/formats.md
.
FormatLengthfpsGrid (BPM)Story beatsOn-screen wordsSoundDeliverables
Launch film / teaser20–45 s601208–10 per 30 s≤ 20–35 in totalfull score + SFX16:9 master, 9:16 and 1:1 re-layouts, poster, brand kit if invented
Product / feature video8–30 s60100–1201 capability per 8–10 s≤ 15light bed + UI SFXmaster, poster
Feature loop4–15 s, whole bars60 (GIF 25)any; whole bars3–5≤ 8, reads mutedoptionalMP4, WebM, GIF, seamless seam
Logo sting3–8 s601202–4name + ≤ 4one tuned hit + tailMP4, ProRes 4444 alphas (held and cleared), poster, brand kit if invented
UI walkthrough20–90 s6090–1101 chapter per 2–4 bars≤ 6 per captionbed + UI SFXmaster, SRT captions
Use 60 fps whenever UI, text or the camera moves. At 30 fps slow drifts visibly step and fast moves strobe, and 24 fps is never right for UI. A GIF is the one exception: export it at 25 fps (or 50) from the 60 fps master, because GIF frame delays are whole hundredths of a second and 30 fps plays 11% fast.
先选择一种格式。它决定长度、信息密度和交付文件。各格式的制作方案见
references/formats.md
。
格式长度fps网格(BPM)叙事节拍屏幕文案字数声音交付物
发布影片/预热片20–45 秒60120每 30 秒 8–10 个总计 ≤ 20–35完整配乐 + SFX16:9 母版、9:16 和 1:1 重排版、海报;若自行创作品牌,还需品牌套件
产品/功能视频8–30 秒60100–120每 8–10 秒展示 1 项能力≤ 15轻量音床 + UI SFX母版、海报
功能循环动画4–15 秒,完整小节60(GIF 25)任意;必须为完整小节3–5≤ 8,静音时也能读懂可选MP4、WebM、GIF、无缝衔接
Logo sting3–8 秒601202–4名称 + ≤ 4一次调音冲击音 + 尾音MP4、ProRes 4444 alpha 版本(保留底色与清空底色)、海报;若自行创作品牌,还需品牌套件
UI 演示20–90 秒6090–110每 2–4 小节 1 个章节每条字幕 ≤ 6音床 + UI SFX母版、SRT 字幕
只要画面包含 UI、文字或镜头运动,就使用 60 fps。在 30 fps 下,缓慢漂移会出现明显阶梯,快速运动则会产生频闪;24 fps 永远不适合 UI。GIF 是唯一例外:应从 60 fps 母版导出 25 fps 或 50 fps,因为 GIF 的帧延迟以百分之一秒为单位,30 fps 实际会快 11%。

2. The five laws

2. 五条法则

  1. One idea, specific to this product. You can say the film in one sentence, and the proof shows what this product does that the obvious or simpler version wouldn't. Restraint applies to decoration and copy, never to the product's intelligence: if the feature is smart, the film shows the smart part. Why: a viewer carries away one thing, and a film that would be equally true of a competitor, or of a dumber feature, gives them nothing to carry.
  2. One story device. An object, shape or colour travels through every shot and never blinks out at a cut. In a launch film it ideally resolves into the mark at the end; in a feature loop or product video it is the unit the product acts on (the card, the row, the file). Find the object this product owns. A bare dot, line or block is the lazy default, and it is also the look of this skill's own examples. Why: it makes the film continuous, it lets the film read with the sound off, and an owned object is what makes the film unmistakably this brand's.
  3. One accent with one meaning. The accent is a single token that means one thing, such as "now", "new" or "yours". Use it sparingly (about ≤ 8% of pixels) and let it flood the frame at most once. Why: a colour that means something is read without words, and a colour used everywhere means nothing.
  4. One house motion system. Use a few named curves and springs, each for a stated reason, and take every frame number from
    timeline.ts
    . Why: consistent motion is brand motion, and ad-hoc eases read as generated.
  5. Verify by measurement. A film is done only when the rendered pixels and the decoded audio pass the scripts and one round of critique. Why: Studio playback hides pops, ghost frames, sync slips and colour shifts that the encoded file will show.
  1. 一个专属于此产品的概念。 你应该能用一句话概括影片,并由证据展示这个产品做到了什么,而显而易见的或更简单的版本做不到。克制适用于装饰和文案,绝不适用于产品本身的聪明程度:如果某项功能很聪明,影片就应展示其聪明之处。*原因:*观众最终只会记住一件事;如果一部影片同样适用于竞争对手,甚至适用于功能更弱的产品,它就没有给观众留下任何东西。
  2. 一个贯穿全片的叙事装置。 一个物件、形状或颜色贯穿每个镜头,在切点处也绝不凭空消失。在发布影片中,它最好于结尾转化为品牌标志;在功能循环动画或产品视频中,它应是产品所操作的对象,例如卡片、行项目或文件。找到这个产品真正拥有的对象。裸点、线条或色块是懒惰的默认选择,也正是本 skill 示例自身的视觉词汇。*原因:*它让影片保持连续性,使其静音时也能被理解,而自有对象正是让影片无可争议地属于这个品牌的关键。
  3. 一种具有单一含义的强调色。 强调色是单一 token,只表达一件事,例如“现在”“全新”或“属于你”。应克制使用,约占画面的 ≤ 8%,最多允许一次让强调色充满画面。*原因:*具有含义的颜色无需文字也能被理解,而到处都是强调色则意味着没有任何含义。
  4. 一套统一的品牌运动系统。 使用少量具名曲线和 spring,每种都服务于明确目的,并从
    timeline.ts
    获取所有帧号。*原因:*一致的运动本身就是品牌运动,临时拼凑的缓动会显得像生成内容。
  5. 通过测量进行验证。 只有当渲染像素和解码音频通过脚本检查,并完成一轮评审后,影片才算完成。*原因:*Studio 播放会掩盖突兀跳帧、鬼帧、同步偏移和色偏,而编码文件会暴露这些问题。

3. Workflow

3. 工作流

Every step writes a file, and every gate is a check you actually run. Work inline. Subagents are for critique only (§8), because building frames in parallel costs more time than it saves.
每一步都会写入文件,每个关卡都是必须实际执行的检查。直接在当前环境内工作。Subagent 仅用于评审(§8),因为并行构建画面所花的时间通常多于其节省的时间。

Step 0: Intake →
BRIEF.md

步骤 0:接收需求 →
BRIEF.md

  • If the brief already states the product, the message and the length, infer everything else and write your assumptions down.
  • If it doesn't, ask at most 3 questions: the product in one line, the format and length, and where the film will be shown. Take everything else from §1.
  • Choose the engine: Remotion by default; HyperFrames if the user already has a HyperFrames project, wants HTML/GSAP, or needs
    --batch
    renders driven by variables.
  • Copy the hard bans (above) into
    BRIEF.md
    , plus any brand-supplied exceptions. Critics are later prompted with this file word for word, so it doubles as the QA contract.
  • Scaffold the project:
    bash <skill>/scripts/new-film.sh films/<name> --fps 60 --bpm 120 --size 1920x1080 [--engine hyperframes]
    . Pass
    --link-modules <dir>/node_modules
    to reuse an existing install instead of running
    npm install
    .
  • Gate:
    BRIEF.md
    has a spec line, for example
    1920x1080@60, 30s, 120BPM, audio: synthesized
    .
  • 如果 brief 已说明产品、核心信息和长度,则推断其余内容并记录假设。
  • 如果没有,最多提出 3 个问题:用一行描述产品、格式与长度、影片的展示位置。其余内容从 §1 获取。
  • 选择引擎:默认使用 Remotion;如果用户已有 HyperFrames 项目、希望使用 HTML/GSAP,或需要由变量驱动的
    --batch
    渲染,则使用 HyperFrames。
  • 将硬性禁令复制到
    BRIEF.md
    ,并记录任何品牌提供的例外。后续会用该文件逐字提示评审,因此它同时也是 QA 合约。
  • 创建项目结构:
    bash <skill>/scripts/new-film.sh films/<name> --fps 60 --bpm 120 --size 1920x1080 [--engine hyperframes]
    。传入
    --link-modules <dir>/node_modules
    可复用现有安装,而不必运行
    npm install
    。
  • 关卡:
    BRIEF.md
    中包含一行规格,例如
    1920x1080@60, 30s, 120BPM, audio: synthesized
    。

Step 1: Concept →
TREATMENT.md

步骤 1:概念 →
TREATMENT.md

Read
references/concept-and-story.md
now.
  • Start from specifics, not from style. Write down:
    • what the name means or evokes (it often hands you the mark and the device);
    • the feature's non-obvious behaviour, finishing the sentence "unlike the obvious version, it…";
    • the product's own objects (its rows, cards, readings and states).
  • Write 3 concepts, each through a different lens:
    • (a) the product's own verb or metaphor made literal;
    • (b) the viewer's pain made visible;
    • (c) a formal device: a relay object, a bookend, one unbroken camera move, or a container that becomes the product.
  • Throw out any concept whose props could appear in another product's film. It isn't yours.
  • Draw the techniques; don't choose them. Run
    python3 scripts/pick.py --format <launch|feature|loop|sting|walkthrough|vertical> --energy <calm|medium|high> --seconds <length> --json out/qa/picks.json
    . It draws about one technique per 2.5 s of film (5 for a 12 s video, 12 for a 30 s launch) from the measured library in
    assets/library/techniques.json
    , in the order the format needs them, weighted toward proven moves and the film's energy, and prints each recipe with default timing. Choosing by hand converges on the same fade-up, push-in and end card in every film; the draw is how two films stop looking alike. Build the picks the concept can carry, retold in its objects and device; the story, product truth and one consistent UI language come first, and a film that crams in every move reads as a showreel. Reroll a pick that fights the concept at most twice (
    --category <cat> --exclude <id>
    ), or drop it, with a written reason; never add a technique the draw did not give you (draw one with
    --category
    ), and pass
    --brand-supplied <look>
    when the brand owns a banned look. Read a drawn entry in full with
    pick.py --show <id>
    ;
    references/technique-library.md
    lists every entry (search it, don't read it whole). Measured pacing, easing and text-timing norms are in
    references/craft-rules.md
    .
  • Fill in
    assets/TREATMENT.md
    for the concept you chose:
    • a logline;
    • the arc: hook (inside the problem, felt by 1 s) → turn → proof (1–2 capabilities) → promise → lockup;
    • the drawn techniques with the seed line, each placed in a beat (§3b of the template);
    • the device path, shot by shot;
    • a beat sheet with the columns bar | time | picture | copy | sound;
    • the full copy with its word count;
    • the final frame.
  • Run the deletion test. Remove the demo beats, and the value should still read. Remove the value beats; if the film still "works", it was a feature tour.
  • Run the specificity test. Would the film be just as true of a simpler product, for example an even split instead of an itemised one, or a plain list instead of a ranked one? If yes, the proof undersells the product; show the part that is hard.
  • Run the feature-word test. Watching muted, would a stranger use the brief's word for the feature ("streak", "split")? If a clever device makes it read as something else, keep the feature's familiar form and let the device dress it.
  • Gate:
    • the logline is ≤ 15 words;
    • the specificity test passes, with its answer written down;
    • the word count is inside the §1 budget;
    • no line is longer than 5 words, and no shot has more than 2 lines;
    • the device appears in every beat row, and every drawn technique is placed in a beat or dropped with a reason.
现在阅读
references/concept-and-story.md
。
  • 从具体事实出发,而不是从风格出发。写明:
    • 名称的含义或联想,它通常能提供品牌标志和视觉装置;
    • 功能不明显的具体行为,补全“与显而易见的版本不同,它……”这句话;
    • 产品自身的对象,例如行项目、卡片、读数和状态。
  • 从三个不同视角分别写出 3 个概念:
    • (a)将产品自身的动词或隐喻具象化;
    • (b)让观看者的痛点变得可见;
    • (c)一种形式装置:中继对象、首尾呼应、一个不间断的镜头运动,或一个最终变成产品本身的容器。
  • 删除任何道具也可以出现在其他产品影片中的概念,因为那并非你的产品所独有。
  • 抽取技法,不要凭感觉选择。 运行
    python3 scripts/pick.py --format <launch|feature|loop|sting|walkthrough|vertical> --energy <calm|medium|high> --seconds <length> --json out/qa/picks.json
    。它会按照格式需要的顺序,从
    assets/library/techniques.json
    的量化技法库中,大约每 2.5 秒影片抽取一种技法(12 秒视频抽取 5 种,30 秒发布影片抽取 12 种),并根据已验证动作和影片能量进行加权,同时输出每种方案的默认时长。手动选择通常会收敛到相同的淡入、推进和片尾卡;使用抽取机制可以让不同影片不至于看起来一模一样。只实现概念能够承载的抽取结果,并用产品的对象与视觉装置重新讲述。故事、产品真实性和统一的 UI 语言优先;把所有动作都塞进影片,只会像作品集展示。对于与概念冲突的抽取结果,最多重新抽取两次(
    --category <cat> --exclude <id>
    ),也可以放弃,但必须写明原因;绝不能加入抽取结果中没有的技法,如需使用则用
    --category
    重新抽取。若品牌本身拥有某项被禁风格,使用
    --brand-supplied <look>
    。使用
    pick.py --show <id>
    完整阅读某个抽取条目;
    references/technique-library.md
    列出全部条目,按需搜索,不要通读。量化节奏、缓动和文字时间规范位于
    references/craft-rules.md
    。
  • 在
    assets/TREATMENT.md
    中填写选定概念:
    • 一句话梗概;
    • 完整弧线:钩子(1 秒内让人感受到问题)→转折→证据(1–2 项能力)→承诺→品牌锁定画面;
    • 带 seed 行的抽取技法,每项放入一个节拍(模板 §3b);
    • 逐镜头的视觉装置路径;
    • 包含
      bar | time | picture | copy | sound
      列的节拍表;
    • 完整文案及其字数;
    • 最后一帧。
  • 执行删除测试。移除 demo 节拍后,价值仍应成立;移除价值节拍后,如果影片依然“成立”,它就只是一次功能巡览。
  • 执行具体性测试。这部影片对一个更简单的产品是否也同样成立,例如一个平均划分与一个逐项划分的区别,或者一个普通列表与一个排名列表的区别?如果成立,证据就低估了产品;应展示最难的部分。
  • 执行功能词测试。静音观看时,陌生人是否会使用 brief 中描述该功能的词,例如“streak”或“split”?如果巧妙装置让影片被理解为其他东西,应保留该功能熟悉的形式,再由装置加以包装。
  • 关卡:
    • 梗概 ≤ 15 个词;
    • 具体性测试通过,并记录答案;
    • 字数符合 §1 限制;
    • 没有一行超过 5 个词,每个镜头不超过 2 行;
    • 视觉装置出现在每个节拍行中,每项抽取技法均已放入节拍,或附带原因被放弃。

Step 2: Brand and style frames →
src/brand/

步骤 2:品牌与风格帧 →
src/brand/

Read
references/brand-and-color.md
and the type section of
references/copy-and-type.md
.
  • The starter's palette, fonts, mark and demo name are stand-ins marked
    // cinetic:placeholder
    , and
    lint-film.mjs
    reports an error until every marker is gone. Apply the user's brand, or invent one for this film, then delete the markers. A film that keeps the starter's look looks like every other film made from it.
  • Personality first. Write three adjectives for the brand, then derive the choices from them. This mapping is in
    references/brand-and-color.md
    §2:
    • the typeface: pick the sans for this brand from
      @fontsource-variable/*
      and vendor it with
      node scripts/add-font.mjs <name>
      (safe with a shared
      node_modules
      ); Geist is only the starter's stand-in;
    • weight and case;
    • the stage (light or dark: a dev tool or a fire-named brand often wants dark), neutral or cool, and the accent's hue from the allowed families;
    • the motion character, from crisp to unhurried.
    A calm notes app and a fast CI tool should not share a look.
  • Write
    src/brand/tokens.ts
    (
    python3 scripts/palette.py --accent '#…' --stage dark
    builds the neutrals, checks contrast and refuses a banned hue):
    • colours: an ink, a paper, 2–4 neutrals, and one accent with its meaning in a comment;
    • type: one family at 2 weights, plus a mono if you need one;
    • a type scale;
    • one tracking value per role.
  • Explore the mark before you commit to one.
    • Sketch 6–10 directions, each from a different source: the name's meaning, a letterform, the product's own object, the idea's metaphor, and a pure geometric construction.
    • Render them together on one sheet and look at it (the
      MarkSheet
      still in
      references/brand-and-color.md
      §4).
    • Reject any direction that could belong to ten other startups, including the "geometric block + accent dot" family, which is this skill's own example vocabulary.
    • Run the misread test. Show the mark at 64 px for half a second. If it reads first as a common symbol (a minus, an emoticon, a menu or hamburger icon, a padlock, a play button, a plus), reject it or change it until it doesn't.
    • Build the winner in
      src/brand/Mark.tsx
      on a 100-unit grid, with gaps of at least 8 units so it survives being scaled down.
  • A palette with character, inside the bans. Derive it from the world of the name and the product (a hillside gives pine, moss and slate; a foundry gives charcoal, soot and a glowing red), not from framework defaults. When the name's world is heat or fire, orange is banned, so go red-hot (a deep red glowing on a true charcoal) or white-hot, never generic dev-tool blue: the colour must carry the name. A blue-grey near-black stage is the stock dev-tool dark theme (
    palette.py
    notes it), and in a dev tool red UI tags read as errors; spend the red on the brand's own thing.
    • Framework blues (the
      #3B82F6
      /
      #2563EB
      family) and flat pure greys read as "default".
    • Tint the neutrals toward the world, with a cool green-grey or a blue slate; a dark stage can be pine-black or ink-navy rather than
      #000
      .
    • references/brand-and-color.md
      §8–10 has worked palettes.
  • Set the lockup like a typographer. Render three settings side by side (mark-to-cap ratio, gap, weight, tracking) and pick the one where the mark and the word read as one object. A carelessly set wordmark costs more than any animation gains.
  • Render 2–4 one-frame style stills from the
    Stills
    folder and look at them: the mark at 16 px and at full size, one statement frame, and one product frame.
    npm run stills
    renders the mark stills; add your own with
    npx remotion still <StillId> out/stills/<name>.png
    .
  • Gate:
    • the stills pass §4;
    • the mark sheet and the chosen direction's reason are in
      TREATMENT.md
      ;
    • node scripts/lint-film.mjs src
      reports no placeholder and no colour or font that is not a token.
阅读
references/brand-and-color.md
以及
references/copy-and-type.md
的字体部分。
  • 初始模板中的色板、字体、标志和 demo 名称都是占位内容,并带有
    // cinetic:placeholder
    标记;在所有标记被删除前,
    lint-film.mjs
    都会报错。应用用户品牌,或为本次影片自行创作品牌,然后删除这些标记。保留模板外观的影片,会和所有使用该模板制作的影片长得一样。
  • 先确定个性。 为品牌写下 3 个形容词,再据此推导选择。
    references/brand-and-color.md
    §2 给出了映射方式:
    • 从
      @fontsource-variable/*
      中选择适合品牌的 sans 字体,并通过
      node scripts/add-font.mjs <name>
      本地打包(可安全共用
      node_modules
      );Geist 只是模板占位字体;
    • 字重与大小写;
    • 舞台采用浅色还是深色(开发工具或名称带火意的品牌通常适合深色)、中性还是冷色,以及强调色所属色系;
    • 运动性格,从利落到从容。
    平静的笔记应用与高速 CI 工具不应共用同一种外观。
  • 编写
    src/brand/tokens.ts
    (
    python3 scripts/palette.py --accent '#…' --stage dark
    可生成中性色、检查对比度并拒绝禁用色相):
    • 颜色:一种 ink、一种 paper、2–4 种中性色,以及一种带明确含义的强调色,并在注释中说明;
    • 字体:一种字体家族、2 个字重,必要时再增加一种 mono 字体;
    • 字号体系;
    • 每种角色使用一个 tracking 值。
  • 在确定前探索品牌标志。
    • 绘制 6–10 个方向,每个方向来自不同来源:名称含义、字母形态、产品自身对象、概念隐喻,以及纯粹的几何构造。
    • 将它们渲染在同一张图板上并亲自查看,即
      references/brand-and-color.md
      §4 中的
      MarkSheet
      静帧。
    • 拒绝任何可能属于另外十家初创公司的方向,包括“几何色块 + 强调色圆点”这一类,它正是本 skill 示例自身的词汇。
    • 执行误读测试。将标志以 64 px 展示半秒。如果它首先被看成常见符号,如减号、表情符号、菜单或汉堡图标、挂锁、播放按钮或加号,就应拒绝或修改。
    • 在
      src/brand/Mark.tsx
      的 100 单位网格上构建胜出的方案,间距至少 8 个单位,以确保缩小后仍能成立。
  • 打造有个性的色板,同时遵守禁令。 从名称和产品的世界推导色板,例如山坡对应松绿、苔藓和石板色,铸造厂对应木炭、烟尘与炽红,而不是直接使用框架默认值。当名称的世界涉及热或火时,橙色被禁用,因此应使用炽红(在真正的炭黑上发光的深红)或炽白,绝不能使用泛用的开发工具蓝;颜色必须承载名称。蓝灰近黑舞台是开发工具深色主题的库存样式(
    palette.py
    中有说明),而在开发工具中红色 UI 标签通常会被理解为错误,因此应把红色用于品牌自身的事物。
    • 框架蓝(
      #3B82F6
      /
      #2563EB
      系列)和纯平灰色看起来像“默认值”。
    • 根据品牌世界调整中性色倾向,可以使用冷绿灰或蓝石色;深色舞台可以是松木黑或墨蓝,而不是
      #000
      。
    • references/brand-and-color.md
      §8–10 提供了经过验证的色板。
  • 像排版设计师一样设置 lockup。 并排渲染 3 种设置,包括标志与字标比例、间距、字重和 tracking,并选择能让标志与名称像一个整体被阅读的方案。粗糙设置的字标,其损失远超动画带来的收益。
  • 从
    Stills
    文件夹渲染 2–4 张单帧风格静帧并亲自查看:16 px 的标志、完整尺寸的标志、一张文案画面和一张产品画面。
    npm run stills
    可渲染标志静帧;使用
    npx remotion still <StillId> out/stills/<name>.png
    添加自己的静帧。
  • 关卡:
    • 静帧通过 §4 检查;
    • TREATMENT.md
      中包含标志图板及所选方向的原因;
    • node scripts/lint-film.mjs src
      不报告占位内容,也不报告任何未定义为 token 的颜色或字体。

Step 3: Timeline →
src/timeline.ts

步骤 3:时间线 →
src/timeline.ts

Read
references/timing-grid.md
now.
  • Choose BPM and fps so that a beat is a whole number of frames (see §5).
  • Map the beat sheet onto bars:
    • ACT
      holds contiguous, bar-aligned acts;
    • CUE
      holds named frames that sit on the grid;
    • COPY
      holds
      {id, text, in, resolved, out}
      for every line;
    • TOTAL
      includes a tail of at least 60 f.
  • Give each bar one motion peak.
  • Gate:
    npx tsx scripts/grid-check.ts src/timeline.ts
    passes (
    npm run check
    runs it together with
    tsc
    and the lint). It checks that every cue is on the 16th grid (or carries an
    offgrid:
    reason), that text holds are long enough, that no gap without an event runs past 48 f, and that the word count is within budget.
现在阅读
references/timing-grid.md
。
  • 选择 BPM 和 fps,确保一个节拍等于整数帧(见 §5)。
  • 将节拍表映射到小节:
    • ACT
      保存连续且与小节对齐的段落;
    • CUE
      保存位于网格上的具名帧;
    • COPY
      为每一行保存
      {id, text, in, resolved, out}
      ;
    • TOTAL
      包含至少 60 f 的尾音。
  • 每个小节设置一个运动峰值。
  • 关卡:
    npx tsx scripts/grid-check.ts src/timeline.ts
    通过(
    npm run check
    会将其与
    tsc
    和 lint 一起运行)。它会检查每个 cue 是否位于 16 分音符网格上(或带有
    offgrid:
    原因)、文字停留时间是否足够、任何没有事件的间隔是否超过 48 f,以及字数是否在预算内。

Step 4: Build, act by act →
src/acts/

步骤 4:逐段构建 →
src/acts/

Before you write motion, read
references/motion-tokens.md
,
references/camera.md
,
references/transitions.md
, and
references/product-ui.md
if the product appears. Keep
references/chromium-rendering.md
open while you debug.
  • Make each act a pure function of
    useCurrentFrame()
    . Mount one
    <Sequence>
    per act in
    Film.tsx
    , and register each act as its own composition in the
    Acts
    folder so you can iterate on it alone.
  • Take all motion from the tokens in
    src/lib/anim.ts
    (§6). A raw bezier inside an act is a lint error, because that is how a house style decays.
  • Build the product UI from real components fed by one
    data.ts
    module with asserts on dates, weekdays, counts, plurals and sums. The data must agree with the story too: the person who paid doesn't owe, a "sorted" list is actually sorted, a stated ratio matches its numbers, and no number appears twice in one frame. That holds in every frame, in-between states included: a copy headed "owes Maya" over the whole bill's total is a wrong number on screen for as long as it shows. Frame the UI large enough to read on a phone: push in 2–5× on every interaction that carries the story, and hold a wide shot of readable UI for at most about 1.7 s. Every bar, segment, chart or bare number that carries meaning shows its value, label or unit: a row of "18 24 12 31" under M–S reads as dates, not pages. A screenshot never carries the hero shot.
  • Make the product and the feature identifiable. Name the feature once, as a UI label, the one line of copy or the end card, and show enough real app chrome that a stranger knows this is software. "No feature name as a headline" never means "never name it". A feature label is not a payoff: land the value with one short line that makes it human ("Sam had the salad."), even in a muted loop.
  • Frame only the meaningful part of the product. No half-empty grids, no tables cropped at the frame edge, no rows of blank cells: they read as a spreadsheet, not a product.
  • Text that must be read stays readable in motion. Text being read moves at most about 3 px/f (a camera cruise under it 1.5–3 px/f). Keep labelled chips and numbers under about 20 px/f while they travel, or fly them with the text faded and let it resolve on landing, because motion blur on small text reads as a double image.
  • Moving elements never cover text they pass over: plan the paths and the z-order, and check the densest frames at full size.
  • A progressive text reveal (letter by letter or with a sweep) must never spell a different word partway through ("tarn" briefly reading "tar"), and never shows part of a glyph: a soft wipe through an "n" reads as an "r" ("halder"). Step the mask from glyph edge to glyph edge on whole frames, or reveal whole words, and check the intermediate frames.
  • Export from its act every frame the sound needs, as a named constant (for example
    LANDINGS
    or
    SNAP
    ), so the cue export can import it.
  • Wrap everything in
    <FontGate>
    .
  • Iterate each act in this loop:
    1. Render stills at each cue −2, 0 and +2.
    2. Make an act contact sheet:
      python3 scripts/sheet.py --comp Act2 --every 2 --out out/qa/act2.png
      renders the act and tiles it with frame and time labels. Use
      --every 2
      for fast sections.
    3. Run
      bash scripts/layout-audit.sh Act2 --cues
      .
  • Gate:
    • lint-film.mjs
      is clean;
    • layout-audit
      reports 0 safe-area or overlap violations, and no readable text faster than 20 px/f;
    • every act sheet has written review notes.
编写运动代码前,阅读
references/motion-tokens.md
、
references/camera.md
、
references/transitions.md
;如果产品出现在影片中,还应阅读
references/product-ui.md
。调试时保持
references/chromium-rendering.md
打开。
  • 让每个段落成为
    useCurrentFrame()
    的纯函数。在
    Film.tsx
    中为每个段落挂载一个
    <Sequence>
    ,并在
    Acts
    文件夹中将每个段落注册为独立 composition,以便单独迭代。
  • 所有运动都必须使用
    src/lib/anim.ts
    中的 token(§6)。段落中直接写 raw bezier 属于 lint 错误,因为这是品牌风格逐渐失控的根源。
  • 使用真实组件构建产品 UI,并由一个
    data.ts
    模块提供数据,同时断言日期、星期、计数、复数和总和。数据也必须与故事一致:已付款的人不欠款,“已排序”的列表确实有序,声明的比例与数字相符,同一帧中不出现重复数字。这些规则在每一帧中都必须成立,包括中间状态:标题为“owes Maya”的文案若显示整张账单的总额,只要仍在画面上,数字就是错误的。UI 在手机上必须足够大:每个承载故事的交互应推进 2–5×,可读 UI 的广角镜头最多停留约 1.7 秒。每个承载含义的条形、段落、图表或裸数字都应显示其值、标签或单位;M–S 下方的“18 24 12 31”会被读成日期,而不是页数。截图绝不能充当核心镜头。
  • 让产品和功能可被识别。以 UI 标签、一行文案或片尾卡的形式至少提一次功能名称,并展示足够多的真实应用界面,让陌生人知道这是软件。“功能名称不能作为标题”绝不意味着“永远不能说出功能名”。功能标签不是价值落点:用一句简短、人性化的话落实价值,例如“Sam had the salad.”,即使在静音循环中也应如此。
  • 只框取产品中有意义的部分。不要出现半空网格、在画面边缘被裁切的表格或整行空白单元格;它们看起来像电子表格,而不是产品。
  • 必须阅读的文字在运动中仍应可读。文字移动速度最多约 3 px/f(镜头掠过时为 1.5–3 px/f)。带标签的 chip 和数字移动时保持在约 20 px/f 以下;也可以让文字淡化后飞入,落地时再还原,因为小字号文字上的运动模糊会形成重影。
  • 移动元素绝不能遮挡其经过的文字:应规划路径和 z-order,并在全尺寸下检查最密集的帧。
  • 渐进式文字显示(逐字母或扫光)不能在中途拼出另一个单词,例如“tarn”短暂读成“tar”,也不能只显示某个字形的一部分;穿过“n”的柔和擦除会读成“r”(“halder”)。遮罩应按完整帧从字形边缘移动到另一个字形边缘,或直接显示完整单词,并检查中间帧。
  • 从段落中导出声音需要的每一帧,并以具名常量表示,例如
    LANDINGS
    或
    SNAP
    ,以便 cue 导出模块引用。
  • 使用
    <FontGate>
    包裹所有内容。
  • 按以下循环迭代每个段落:
    1. 在每个 cue 的 −2、0、+2 帧渲染静帧。
    2. 创建段落接触表:
      python3 scripts/sheet.py --comp Act2 --every 2 --out out/qa/act2.png
      ,渲染该段并将画面平铺,附上帧号和时间标签。快速段落使用
      --every 2
      。
    3. 运行
      bash scripts/layout-audit.sh Act2 --cues
      。
  • 关卡:
    • lint-film.mjs
      无错误;
    • layout-audit
      报告 0 个安全区域或重叠违规,且没有速度超过 20 px/f 的可读文字;
    • 每个段落接触表都有书面评审记录。

Step 5: Sound →
public/audio/soundtrack.wav

步骤 5:声音 →
public/audio/soundtrack.wav

Read
references/sound.md
now.
  • Run
    npx tsx scripts/export-cues.ts
    , which writes
    out/cues.json
    . Sync points are computed from the picture code (spring contact frames, 50% pop frames, velocity peaks, 97% settles) and never typed by hand. Typed sync points landed 8–11 f off in practice.
  • Pick the sound's personality row in
    references/sound.md
    §5.5a first. A calm brand gets soft mallets and one gentle chord; drops onto silence and sub booms are for energetic launch films only.
  • Make the music drive the picture, whatever the personality.
    • A motif that follows the story's progress, for example one tuned note per step climbing the scale (
      progress
      in
      score.json
      ).
    • Section changes and the hero reveal land with the music's own event (drop, stop, re-entry). Designed effects go on discrete state changes only, about 5 per 10 s, clustered where the music is sparse; continuous motion and most cuts get none.
    • The drop on the hero reveal, 30–60% in, is the loudest moment, and
      payoff
      points there. The lockup is the most resolved moment, not the loudest: the music stops on a bar line or filters down as the logo forms, 0.2–0.7 s of near-silence, then one soft resolved element on the frame the wordmark becomes readable (its
      settleOf
      , never the tween's last frame or a later bar line: a sound after the motion has stopped lands on nothing) and a 0.5–2.5 s tail. A sting is all lockup: its hit is its loudest moment.
    • The sound enters with intent on frame 0 (a drone or a 150–450 ms entry at most), without a click, and runs 5–12 LU under the body for the first 2–3 s. That assumes frame 0 moves: a drone at full level over a still frame (an empty page, a blinking caret) reads as a mistake, so move the picture, not the sound.
  • Fill in
    audio/score.json
    : key, one chord per bar, sections (with a breakdown or stop about 5 LU down at 40–80% of the runtime), drops and silences. Keep
    "typing": "auto"
    unless the brand asks otherwise.
  • Run
    python3 scripts/audio/score.py --cues out/cues.json --score audio/score.json --out public/audio/soundtrack.wav --stems out/stems --json out/qa/score.json
    (
    npm run audio
    ). The stems let
    av-audit.py
    check each sound against its cue; the master chain lives in
    scripts/audio/master.py
    .
  • Gate:
    • the WAV measures its target ±0.5 LUFS integrated (
      master.lufs
      in
      audio/score.json
      : −14; −16 only for a sting that plays at the head of other videos, never for a social or feed cut, whatever the brand's temperament), with true peak ≤ −1.5 dBTP before encoding;
    • a film of 20 s or more has contrast: LRA 5–8 LU, and the payoff 2–3 LU above the median momentary loudness (
      score.py
      warns);
    • every sound has something visible that causes it, at a loudness that matches that cause (a caret blink whispers; the hero reveal drops); not every picture event gets a sound, but once a class of action is sounded every instance is, at one level.
现在阅读
references/sound.md
。
  • 运行
    npx tsx scripts/export-cues.ts
    ,生成
    out/cues.json
    。同步点由画面代码计算得出,例如 spring 接触帧、50% pop 帧、速度峰值和 97% settle 帧,绝不手动输入。实践中,手动输入的同步点会偏差 8–11 f。
  • 首先从
    references/sound.md
    §5.5a 中选择声音个性行。平静品牌使用柔和木琴和一个轻柔和弦;落入静默及 sub boom 只适用于高能量发布影片。
  • 无论声音个性如何,都必须由音乐驱动画面。
    • 使用一个跟随故事进展的动机,例如每一步对应一个逐渐爬升音阶的调音音符(
      score.json
      中的
      progress
      )。
    • 段落变化和核心画面揭晓应与音乐自身的事件同步落下,例如 drop、stop 或重新进入。设计过的音效只用于离散状态变化,约每 10 秒 5 个,并集中在音乐稀疏的位置;连续运动和大多数切点不配音效。
    • 位于全片 30–60% 处的核心画面揭晓 drop 是最响的时刻,
      payoff
      标记放在此处。Lockup 是最完整、最稳定的时刻,而不是最响的时刻:音乐在小节线停止或随着 logo 形成而滤波下降,保持 0.2–0.7 秒近乎静默,然后在字标刚好可读的那一帧加入一个柔和、完整的声音,使用其
      settleOf
      ,不能使用补间的最后一帧或更晚的小节线;运动已经停止后才出现的声音会落空。随后保留 0.5–2.5 秒尾音。Sting 全部由 lockup 构成,其冲击音就是最响的时刻。
    • 声音从第 0 帧就有明确意图地进入,可使用 drone 或最多 150–450 ms 的进入音,但不能有 click;在最初 2–3 秒内,声音主体应低 5–12 LU。这假设第 0 帧已有运动:全音量 drone 覆盖静止画面(空白页面、闪烁光标)会像错误,因此应移动画面,而不是移动声音。
  • 填写
    audio/score.json
    :调性、每小节一个和弦、段落结构(其中包含在运行时 40–80% 处约低 5 LU 的 break 或 stop)、drops 和静默。保持
    "typing": "auto"
    ,除非品牌另有要求。
  • 运行
    python3 scripts/audio/score.py --cues out/cues.json --score audio/score.json --out public/audio/soundtrack.wav --stems out/stems --json out/qa/score.json
    (
    npm run audio
    )。各 stem 让
    av-audit.py
    可以将每个声音与 cue 对照;母版处理链位于
    scripts/audio/master.py
    。
  • 关卡:
    • WAV 的整体响度达到目标 ±0.5 LUFS(
      audio/score.json
      中的
      master.lufs
      为 −14;只有会被放在其他视频开头的 sting 才使用 −16,无论品牌气质如何,社交媒体或信息流剪辑都不应使用它),编码前 true peak ≤ −1.5 dBTP;
    • 20 秒或以上的影片具有对比度:LRA 为 5–8 LU,payoff 比瞬时响度中位数高 2–3 LU(
      score.py
      会警告);
    • 每个声音都有可见原因,响度也与原因相符(光标闪烁只有轻声;核心画面揭晓使用 drop);不是每个画面事件都需要声音,但某一类动作一旦开始配音,其每次实例都应配音,并保持相同响度。

Step 6: Render and finish →
out/film.mp4

步骤 6:渲染与后期 →
out/film.mp4

Read
references/finishing.md
now.
  • Preview:
    bash scripts/render.sh Film out/preview.mp4 --preview --audio public/audio/soundtrack.wav
    . Remotion renders the picture muted and BT.709-tagged, and ffmpeg muxes the audio. Iterate and critique on previews only.
  • Master: if anything moves faster than 12 px/f (true of almost every launch film),
    bash scripts/render.sh Film out/film.mp4 --blur
    : sharp render → speed measurement →
    FilmSub
    sub-frame render → float accumulation → mux → sync check. Otherwise, with no flag,
    render.sh
    renders a sharp master at CRF 14. Loops take
    --loop
    (lossless PNG intermediates, so the seam survives the encode) and, when silent,
    --no-audio
    .
  • Blur costs render time, so spend it once.
    • Render the blurred master once, at the end, after the last critique round. It prints the sub-frame multiple and an estimate before it starts; on 4 CPUs a 10 s film at 60 fps and 6× takes about 7 minutes on simple frames and 10–15 on dense UI.
      --budget 6
      caps it.
    • A late fix re-renders only the changed act's range (
      --frames A-B
      ) and splices it, rather than re-blurring the film.
    • A 9:16 or 1:1 variant with identical timing reuses the master's samples (
      --samples-from
      ); one whose fastest motion is ≤ 12 px/f renders sharp.
    • Don't edit
      src/
      while a render runs:
      render.sh
      renders from a bundle frozen at its start and warns if the source changed meanwhile.
    • Stop a render by its own PID, never with a
      pkill -f
      pattern: on a shared machine the pattern also kills other people's renders.
  • Speed ceiling. Moves over about 80 px/f are listed as too fast for clean blur, and
    render.sh --blur
    stops before the sub-frame pass while any are left: redesign them rather than adding samples (§6), or waive a frame-filling edge you checked at full size with
    --accept-fast A-B
    . Every hard cut is an act boundary: a cut inside an act blends its two shots into one double-exposed frame, so the render also stops on one (
    --accept-cut A-B
    for a flood or flash you checked).
  • Gate.
    render.sh
    runs both checks below and exits 1 if either fails. Run them again on any file you deliver:
    • python3 scripts/probe.py out/film.mp4 --spec 1920x1080@60 --dur <s>
      passes: size, fps, duration ±1 f, yuv420p, BT.709 tags, AAC at 48 kHz;
    • python3 scripts/check-sync.py out/film.mp4 public/audio/soundtrack.wav
      reports a lag of ≤ 48 samples and true peak ≤ −1 dBTP after decoding.
现在阅读
references/finishing.md
。
  • 预览:
    bash scripts/render.sh Film out/preview.mp4 --preview --audio public/audio/soundtrack.wav
    。Remotion 渲染静音且带 BT.709 标记的画面,再由 ffmpeg 封装音频。只在预览上进行迭代和评审。
  • **母版:**如果任何内容移动速度超过 12 px/f(几乎所有发布影片都是如此),运行
    bash scripts/render.sh Film out/film.mp4 --blur
    :锐利渲染 → 速度测量 →
    FilmSub
    子帧渲染 → 浮点累积 → 封装 → 同步检查。否则,不带该 flag 运行
    render.sh
    ,以 CRF 14 渲染锐利母版。循环动画使用
    --loop
    (使用无损 PNG 中间文件,确保接缝能经受编码),静音时使用
    --no-audio
    。
  • 模糊渲染耗时,因此只做一次。
    • 在最后一轮评审之后、影片最终完成时,只渲染一次模糊母版。脚本会在开始前打印子帧倍率和预计耗时;在 4 核 CPU 上,一支 60 fps、6× 子帧的 10 秒影片,简单画面约需 7 分钟,密集 UI 约需 10–15 分钟。使用
      --budget 6
      可设置上限。
    • 后期修复只重新渲染发生变化的 act 范围(
      --frames A-B
      )并拼接,而不是重新模糊整部影片。
    • 9:16 或 1:1 版本若时间完全相同,可复用母版采样(
      --samples-from
      );最快运动 ≤ 12 px/f 的版本则直接锐利渲染。
    • 渲染运行期间不要修改
      src/
      :
      render.sh
      使用启动时冻结的 bundle,并会在源代码发生变化时发出警告。
    • 使用渲染进程自己的 PID 停止任务,绝不能使用
      pkill -f
      模式:在共享机器上,该模式也会终止其他人的渲染任务。
  • 速度上限。 超过约 80 px/f 的移动会被列为无法干净处理运动模糊的项目;只要仍有此类移动,
    render.sh --blur
    就会在进入子帧阶段前停止。应重新设计动作,而不是增加采样(§6);如果已全尺寸检查过某个占满画面的边缘,可使用
    --accept-fast A-B
    豁免。所有硬切都应位于 act 边界:act 内部切镜会把两个镜头混合成一帧双重曝光,因此渲染也会在内部切点停止;对于已检查过的 flood 或 flash,可使用
    --accept-cut A-B
    。
  • 关卡。
    render.sh
    会执行以下两项检查,任何一项失败都会以状态码 1 退出。交付任何文件前都应再次运行:
    • python3 scripts/probe.py out/film.mp4 --spec 1920x1080@60 --dur <s>
      通过:尺寸、fps、时长误差 ±1 f、yuv420p、BT.709 标签、48 kHz AAC;
    • python3 scripts/check-sync.py out/film.mp4 public/audio/soundtrack.wav
      报告延迟 ≤ 48 samples,且解码后的 true peak ≤ −1 dBTP。

Step 7: Review loop

步骤 7:评审循环

Run §8 on previews. Launch films and walkthroughs get at least 2 rounds. For stings and loops whose scripts all pass, 1 round is enough. The blurred master then gets a check, not a round: forensics, av-audit, its fastest frames at full size (every act's, including the lockup's entrance and exit, where a sliding wordmark most often shows stepped copies; fix with
measure-speed.py --floor a-b:n
), and a director's glance.
对预览运行 §8。发布影片和 UI 演示至少进行 2 轮。Sting 和循环动画若所有脚本均通过,1 轮即可。模糊母版只需检查,不需要再评审一轮:执行取证检查、av-audit、以全尺寸查看速度最快的帧(每个 act 都要检查,包括 lockup 的进入和退出,因为滑动字标最容易在这里出现阶梯状重影;使用
measure-speed.py --floor a-b:n
修复),最后再由导演快速浏览。

Step 8: Deliver

步骤 8:交付

  • Run
    bash scripts/deliver.sh out/film.mp4
    with the flags your format needs:
    --loop --gif --webm
    for loops,
    --alpha StingAlpha,StingAlphaClear
    for ProRes 4444, and
    --variants Film9x16,Film1x1
    for social versions. It writes the poster (the final frame) and, in
    qa/
    , a manifest. For a brand you invented,
    bash scripts/brand-kit.sh
    exports the mark, lockups, favicon sizes and avatar. Re-lay the social versions out from the same timeline; never crop the master (see
    references/formats.md
    ).
  • Write a short
    README.md
    : the idea, the device, the grid, how to render, and the file list.
  • Keep the delivery folder clean. Put the deliverables at its top level (the film, alpha versions, poster, logo files) and QA material (sheets, crops, reports) in a
    qa/
    subfolder. A client opens the folder before they open the film.
  • Gate: every deliverable in the §1 row exists and passes
    probe.py
    at its own spec.
  • 根据格式需要运行
    bash scripts/deliver.sh out/film.mp4
    及相应 flag:循环动画使用
    --loop --gif --webm
    ,ProRes 4444 alpha 使用
    --alpha StingAlpha,StingAlphaClear
    ,社交媒体版本使用
    --variants Film9x16,Film1x1
    。脚本会生成海报(最后一帧)以及
    qa/
    中的 manifest。对于自行创作的品牌,运行
    bash scripts/brand-kit.sh
    导出标志、lockup、favicon 尺寸、头像和 X header。使用同一条时间线重新布局社交媒体版本,绝不能裁切母版(见
    references/formats.md
    )。
  • 编写一份简短
    README.md
    :介绍创意、视觉装置、网格、渲染方式和文件列表。
  • 保持交付目录整洁。将交付物放在顶层(影片、alpha 版本、海报、logo 文件),QA 材料(接触表、裁图、报告)放入
    qa/
    子目录。客户通常会先打开文件夹,再打开影片。
  • 关卡:§1 对应行中的每项交付物都存在,并通过各自规格的
    probe.py
    检查。

Scaled-down path (stings, loops, short feature clips)

精简路径(sting、循环动画、短功能短片)

Small jobs should stay fast. The laws, the grid, the lint and one review round still apply. The rest shrinks:
  1. Write a one-page treatment in
    TREATMENT.md
    : logline, device, the
    pick.py
    draw for the format, a bar table of 2–8 rows, and the copy. It replaces Steps 1–3 as separate passes. Still write
    timeline.ts
    and run
    grid-check.ts
    .
  2. For style frames, the mark at 16 px and one hero still are enough.
  3. Build the whole piece as one act, or two.
  4. Sound is optional for a loop. A sting needs one hit tuned to the key, plus a tail that decays to digital zero.
  5. Render a sharp master unless something passes 12 px/f. Then run one round with the director and forensics lenses.
  6. For a loop, the last frame must flow into frame 0: the seam's frame difference must be at most max(0.4, 1.5× the median step at the ends) (
    forensics.py --loop
    checks it, and so does
    deliver.sh --loop
    ); render it with
    render.sh --loop
    . Build the loop as a cycle rather than as enter, hold and exit. Frame 0 is also the poster and the first frame a visitor sees, so compose it with the product's name or chrome on screen.
小型项目应保持快速。法则、网格、lint 和一轮评审仍然适用,其余部分可缩减:
  1. 在
    TREATMENT.md
    中写一页方案:梗概、视觉装置、格式的
    pick.py
    抽取结果、2–8 行的节拍表和文案。它取代步骤 1–3 的独立流程,但仍需编写
    timeline.ts
    并运行
    grid-check.ts
    。
  2. 风格帧只需 16 px 的标志和一张核心静帧。
  3. 将整支作品构建为一个 act,或两个 act。
  4. 循环动画可以不配乐。Sting 需要一个与调性匹配的声音冲击,以及衰减到数字零点的尾音。
  5. 除非存在超过 12 px/f 的运动,否则渲染锐利母版。然后使用导演和取证视角完成一轮检查。
  6. 对循环动画,最后一帧必须自然流入第 0 帧:接缝处的帧差必须不超过 max(0.4, 1.5× 两端步进中位数)(
    forensics.py --loop
    会检查,
    deliver.sh --loop
    也会检查);使用
    render.sh --loop
    渲染。将循环构建为一个周期,而不是进入、停留和退出的结构。第 0 帧同时也是海报和访客看到的第一帧,因此应在画面中呈现产品名称或应用界面。

4. Taste rules that matter most

4. 最关键的品味规则

The full catalogue of cheap-looking tells, each with its fix, is in
references/taste-and-slop.md
. Search it during review.
These rules ban the tells of generated work, not personality. Two films made with this skill for different brands should not look alike. If yours looks like the starter, the Tessel example or your last film, it is not finished.
Copy (
references/copy-and-type.md
)
  • Open inside the problem, never on "Introducing…", a rhetorical question or the logo. A muted feed decides in the first second.
  • Pay off the film's own words: a setup phrase, then a refrain, then the resolution.
  • Avoid stock phrasing (seamless, unlock, AI-powered, streamline) and never use a feature name as a headline. They mark the film as a template.
  • Show one line at a time. No eyebrow or kicker labels and no stacked taglines, because that is landing-page grammar.
Type
  • Choose one clean, modern sans for the brand's personality, at 2 weights, plus an optional mono, shipped as local variable fonts (
    @fontsource-variable/*
    ). No serif and no italic (see Hard bans).
    • Personality comes from the sans you pick, its weight, case and spacing: a humanist sans at a light weight for calm, a tight grotesk for fast, a rounded sans for friendly.
    • Condensed display faces are a generated-look tell.
    • The ubiquitous UI default families, the starter's stand-in included, read as "template" unless you chose them on purpose.
    • Weight carries tone: a calm brand rarely wants a heavy grotesk wordmark.
  • Get emphasis from size or motion.
    • Statements are 88–128 px with leading 0.95–1.05.
    • Emphasis inside a line is 1.5–1.7× the statement size; a standalone hero word may run 2–5× (14–48% of the frame height); secondary lines are 44–56 px.
    • UI must be at least 22 px on screen after camera scale.
    • Every number uses tabular figures.
  • Keep one tracking token per role, for example a display setting of 600 / −0.05 em. Near-miss values across scenes read as "almost matched".
  • Blur text only on entry, and only while it moves fast: statements 6–8 → 0 px, body lines 4–6 px, or no blur at all, through
    blurIn
    (clear by 60% of the eased move, because Chromium steps blur radii and renders anything under ~0.75 px fully sharp). Text lands sharp and is never left readable-but-blurred for more than 6 f.
Colour (
references/brand-and-color.md
)
  • Pick one accent from an allowed hue family (red, green, teal, blue, yellow) for a stated reason. Everything in the Hard bans is out: orange, amber, beige and cream, neon, purple, violet or indigo, multi-hue gradients and glassmorphism.
  • Restraint is not the same as colourless. The accent visibly carries the key beats (the product's action and the payoff), and the stage and neutrals have a tone from the brand's world. Check a mid-film frame at thumbnail size: if no brand colour shows, the film has no identity.
  • Tint the neutrals cool or keep them neutral, never warm or beige, and keep ink as ink. New things arrive in the accent and relax to neutral over 10–30 f, which is how colour says "just happened".
  • No glow, halo or bloom. Shadows are
    0 20–40px 60–120px rgba(0,0,0,.12–.22)
    , dark surfaces get a 1 px top hairline at 8–12% white, and gradients ship as dithered PNGs (
    scripts/dither-gradient.py
    ), because CSS gradients band at 8 bits.
Layout
  • Avoid "text left, UI card right" and small centred floating cards (under about 40% of the frame width) on an empty field; a centred product window at 70–92% of the frame width, ideally overflowing an edge, is the norm. Show the product full-bleed, anchor the type to an eye line or the lower third, and give each shot one focal action.
  • Keep safe margins of at least 96 px at the sides and 64 px top and bottom, and at least 24 px of headroom at maximum punch. Overscan moving layers by 5–8%.
  • Fill the frame with purpose.
    • In product shots the hero (the UI, the object, the number) covers about 40–70% of the frame.
    • Outside designed negative space around a single hero, such as a logo, no region of more than about a quarter of the frame stays empty.
    • In vertical feeds, the platform's caption and button zones get background or continuation (the product's surface, the stage, a bleed), not an empty band. Viewers read emptiness as unfinished, whatever the reason.
Decoration
  • Every element must name its job (reveal, route, validate, emphasise) or be cut. That rules out particles, bokeh, starfields and ghost text.
  • Grain is either absent or global at 1.5–2%, keyed to the output frame.
Product truth (
references/product-ui.md
): named, specific, consistent data; counters count on each visible event; the product only replans the future; no cursor once the product acts on its own; any paused frame still makes sense.
Transitions (
references/transitions.md
)
  • Use 6–8 types per film, each at most twice, plus one signature move taken from the mark and used 3 times (open, middle, close).
  • A crossfade is never the default, and never goes through black (it dips about 25% in luminance).
  • No preset gimmicks: glitch, light leak, film burn, swirl, ripple, dreamy zoom, flash through white.
所有显得廉价的视觉特征及其修复方式见
references/taste-and-slop.md
完整目录。评审期间应搜索该文件。
这些规则禁止的是生成式作品的特征,而不是品牌个性。为不同品牌使用此 skill 制作的两部影片不应看起来一样。如果你的作品看起来仍像初始模板、Tessel 示例或上一部影片,就尚未完成。
文案(
references/copy-and-type.md
)
  • 从问题内部开场,不要从“Introducing…”、反问句或 logo 开始。静音信息流会在第一秒决定是否继续观看。
  • 兑现影片自己的措辞:先设置一句话,再形成反复句式,最后完成解决。
  • 避免套话(seamless、unlock、AI-powered、streamline),绝不能将功能名称作为标题,否则会显得像模板。
  • 每次只显示一行。不要使用眉题、kicker 标签或堆叠 tagline,因为它们属于落地页语法。
字体
  • 根据品牌个性选择一种干净、现代的 sans 字体,使用 2 个字重,必要时增加一种 mono,并以本地 variable 字体(
    @fontsource-variable/*
    )提供。禁止衬线字体和斜体(见硬性禁令)。
    • 个性来自 sans 字体、字重、大小写和间距:人文主义 sans 的轻字重适合平静风格,紧凑 grotesk 适合快速风格,圆润 sans 适合亲和风格。
    • 压缩展示字体是生成式外观的明显特征。
    • 常见 UI 默认字体家族,包括模板占位字体,除非有意选择,否则都会显得像“模板”。
    • 字重决定语气:平静品牌通常不应使用粗重 grotesk 字标。
  • 通过尺寸或运动制造强调。
    • 核心文案为 88–128 px,行高 0.95–1.05。
    • 同一行中的强调部分为核心文案的 1.5–1.7×;独立核心词可达到 2–5×(画面高度的 14–48%);次级文案为 44–56 px。
    • 镜头缩放后,屏幕中的 UI 至少为 22 px。
    • 所有数字使用等宽数字。
  • 每种角色只使用一个 tracking token,例如展示设置为 600 / −0.05 em。不同场景使用近似值会显得“几乎一致”。
  • 仅在文字进入且移动速度较快时应用模糊:核心文案 6–8 → 0 px,正文 4–6 px,或完全不用模糊,通过
    blurIn
    实现;因为 Chromium 对模糊半径按步长处理,低于约 0.75 px 时会完全清晰。文字落地时必须清晰,且可读但模糊的状态不得持续超过 6 f。
颜色(
references/brand-and-color.md
)
  • 从允许的色系(红、绿、teal、蓝、黄)中选择一种强调色,并说明理由。硬性禁令中的所有内容都不可使用:橙色、琥珀色、米色和奶油色、neon、紫色、violet 或 indigo、多色渐变及 glassmorphism。
  • 克制不等于没有颜色。强调色应明显承载关键节拍(产品动作和 payoff),舞台与中性色则应带有品牌世界的色调。检查缩略图尺寸的影片中间帧:如果完全没有品牌色,影片就缺乏身份。
  • 中性色应偏冷或保持中性,绝不能偏暖或偏米色,同时保持 ink 为 ink。新元素以强调色出现,并在 10–30 f 内回归中性,这就是颜色表达“刚刚发生”的方式。
  • 禁止 glow、halo 或 bloom。阴影为
    0 20–40px 60–120px rgba(0,0,0,.12–.22)
    ,深色表面使用 1 px 顶部发丝线,透明度为 8–12% 的白色;渐变应输出为带抖动的 PNG(
    scripts/dither-gradient.py
    ),因为 CSS 渐变在 8 bit 下会产生色带。
布局
  • 避免“文字在左、UI 卡片在右”,也避免在空旷背景上放置小型居中浮动卡片(宽度低于画面约 40%)。常规做法是让居中的产品窗口占据画面宽度 70–92%,最好略微溢出边缘。产品应全屏铺满,文字与视线或下三分之一对齐,每个镜头只保留一个焦点动作。
  • 左右安全边距至少 96 px,上下至少 64 px,最大冲击时还应保留至少 24 px 顶部空间。移动层应超出画布 5–8%。
  • 让画面充满明确目的。
    • 在产品镜头中,核心内容(UI、对象、数字)应覆盖画面约 40–70%。
    • 除围绕单一核心内容刻意设计的负空间(例如 logo)外,任何区域都不应连续空置超过画面约四分之一。
    • 在竖屏信息流中,平台字幕和按钮区域应有背景或延续画面(产品表面、舞台或出血),而不是空带。观众会将空旷理解为未完成,无论原因是什么。
装饰
  • 每个元素都必须有明确职责(揭示、引导、验证、强调),否则删除。这也排除了粒子、散景、星空和幽灵文字。
  • 颗粒要么不存在,要么使用与输出帧匹配的全局 1.5–2% 颗粒。
产品真实性(
references/product-ui.md
):数据应具名、具体且一致;计数器在每次可见事件中变化;产品只重新规划未来;产品自行执行动作后不再显示鼠标指针;任何暂停帧都应合理。
转场(
references/transitions.md
)
  • 每部影片使用 6–8 种转场,每种最多两次,并加入一种源自品牌标志的标志性动作,重复使用 3 次(开场、中段、结尾)。
  • Crossfade 绝不能作为默认转场,也绝不能经过黑场(其亮度会下探约 25%)。
  • 禁止预设噱头:glitch、light leak、film burn、swirl、ripple、dreamy zoom、flash through white。

5. Timing system essentials

5. 时间系统要点

src/timeline.ts
is the only source of timing. Picture, cue export and grid check all import it. Details and the full pattern are in
references/timing-grid.md
.
ts
export const BEAT = (60 / BPM) * FPS;               // 30 f at 120 BPM / 60 fps
export const BAR = BEAT * 4;
export const b = (bar: number, beat = 0, sub = 0) =>   // sub = 16ths
  Math.round(((bar - 1) * 4 + beat) * BEAT + sub * (BEAT / 4));
const L = (abs: number) => abs - ACT.plan.from;         // act-local frames, one per act
  • Whole-frame beats at 60 fps: 90 BPM gives 40 f, 100 → 36, 120 → 30, 144 → 25, 150 → 24.
  • Grid placement
    • Section changes land on downbeats; cuts inside a section land on 8ths.
    • A batch of landings snaps to 16ths with a 0–3 f spread, and the first item lands on the beat.
    • Micro-rhythm is welcome: the payoff on the clap, its consequence on the next kick.
    • Cuts land on the grid, but most carry no sound of their own: the music carries them. Section changes and the hero reveal land with the music's own event (drop, stop, re-entry);
      av-audit.py
      suggests one when a top-3 picture change has no audio onset.
  • Hit frames
    • Start a picture change at
      cue − 1
      , because
      prog()
      is 0 on its start frame.
    • Pulses peak 2 f after their sound (
      hitPulse
      ).
    • Start a spring at
      beat − delayTo(cfg, 0.5)
      so its pop lands on the beat.
  • Holds
    • Once text resolves, it stays at least 36 f + 6 f per word. Text that hasn't resolved never exits.
    • Nothing is static for more than 48 f, except a designed freeze of ≤ 15 f that sits exactly on a silence, and one designed near-still hold of 60–96 f per film on the key claim or success state, under a music dropout and followed by a big move (declare it as
      export const HOLD = {from, to}
      in
      timeline.ts
      ). When a gate flags a quiet stretch, give it motion; loosening the threshold to pass is not a fix.
    • The end card runs 1.5–2.5 s: the lockup assembles over 60–80 f, then holds still for 36–80 f or keeps building (a creep of ≤ 6%, or a 10–20% push when the hold runs past about 1.3 s), then the tail. Never cut to a complete card that sits static, and never more than about 2.5 s on a still end card: a longer one reads as a drag. A URL is readable for at least 1.7 s.
    • In a launch film or product video the lockup appears once, at the end (a sting is the exception: it is all lockup). A mid-film logo reveal followed by the same lockup again reads as a repeat and spends seconds on a still; the one exception is the product's name or mark revealed at about 20–26% of the runtime after a problem act of 10 s or more, when the end card is a different construction or mirrors the opening. Mid-film, the brand is present through the device and the accent. Brand logo time across the whole film stays ≤ about 12% of the runtime.
  • Density
    • Aim for 45–60 discrete events per 30 s and one motion peak per bar, with 30–70 f of calm between peaks.
    • The first 6 s run about twice as dense as the middle.
    • Energy builds toward the payoff. No stretch after the turn is slower or greyer than the one before it, except one designed lull of 1–4 s inside a music breakdown at about 55–85% of the runtime; the last and biggest visual peak lands at 75–90%, on the music's re-entry. A second half that drags loses films whose first half is strong. Check the energy by eye on a contact sheet of the second half.
    • The last third keeps moving: a camera push, secondary motion or the device still acting. A film that settles 4 s before the end has ended early.
    • Shot length: median 60–90 f; minimum 24 f (and only with no text); maximum 180 f in a cut-driven film, while a continuous take may run 300–560 f if an in-shot beat lands at least every 72 f.
  • Hook:
    • frame 0 is already composed and moving;
    • the sound enters with intent on frame 0, with no fade over the first bar;
    • something visibly changes about every 0.5 s;
    • the problem is felt by 1 s and stated by 2 s;
    • the product is named on screen by about a quarter of the runtime (its chrome, the name in a status line, the mark), not saved for the end card.
    A soft first second loses a muted feed.
  • End card: carry the brief's one practical fact when it gives one (a date such as "next week", a URL, "out now"), set at the secondary size under the lockup. When the brief gives none, a launch film or product video still says what the product is in one short line under the name ("The build cache for CI."); a bare name is for stings. That is the only line besides the name.
  • State follows the event: counters, checks and totals change on the landing frame of the thing that caused them, not a beat later.
Where a sound goes (computed by
src/lib/sync.ts
:
peak
,
hit
,
delayTo
,
settleOf
):
Picture eventThe sound sits on
Landing / impactthe contact frame, so the motion must arrive with velocity (spring threshold 0.92–1.0, or the
contact
ease)
Pop-inthe frame at 50% of travel
Tween settlethe 97% frame
Whoosh (camera-scale moves and logo zooms, about 2 a film)onset 100–450 ms ahead, apex on the visual peak
Typingper key up to 25 chars/s, one blip per word above (
"typing": "auto"
)
Exit rollone tick, with no detent
Cut, scroll, stream, progress bar, rolling counternothing: the music carries it; a counter's final lock gets a crisp tick
Audio that leads the picture by more than about 45 ms reads as "sound first". Move the picture, not the sound.
src/timeline.ts
是唯一的时间来源。画面、cue 导出和网格检查都从中导入。详情及完整模式见
references/timing-grid.md
。
ts
export const BEAT = (60 / BPM) * FPS;               // 30 f at 120 BPM / 60 fps
export const BAR = BEAT * 4;
export const b = (bar: number, beat = 0, sub = 0) =>   // sub = 16ths
  Math.round(((bar - 1) * 4 + beat) * BEAT + sub * (BEAT / 4));
const L = (abs: number) => abs - ACT.plan.from;         // act-local frames, one per act
  • **60 fps 下的整帧节拍:**90 BPM 为 40 f,100 为 36 f,120 为 30 f,144 为 25 f,150 为 24 f。
  • 网格放置
    • 段落变化落在强拍上;段落内部切镜落在八分音符上。
    • 一组落地动作吸附到十六分音符,并允许 0–3 f 的分散,第一项落在节拍上。
    • 可以使用微节奏,例如 payoff 落在 clap 上,其后果落在下一次 kick 上。
    • 切镜应落在网格上,但大多数切镜本身没有声音,由音乐承载。段落变化和核心画面揭晓应与音乐自身的事件同步落下,例如 drop、stop 或重新进入;如果排名前三的画面变化没有音频 onset,
      av-audit.py
      会给出建议。
  • 命中帧
    • 在
      cue − 1
      开始画面变化,因为
      prog()
      在其起始帧上为 0。
    • pulse 在声音后 2 f 达到峰值(
      hitPulse
      )。
    • 在
      beat − delayTo(cfg, 0.5)
      启动 spring,使其 pop 落在节拍上。
  • 停留
    • 文字解析完成后,至少停留 36 f,再按每个词增加 6 f。尚未解析完成的文字绝不能退出。
    • 任何内容静止不得超过 48 f,唯一例外是位于静默处的 ≤ 15 f 设计性冻结,以及每部影片一次、持续 60–96 f 的设计性近静止段,用于关键主张或成功状态;它应位于音乐 dropout 下并由一个大动作承接(使用
      export const HOLD = {from, to}
      在
      timeline.ts
      中声明)。当关卡标记静止区间时,应增加运动;放宽阈值以通过检查不是修复。
    • 片尾卡持续 1.5–2.5 秒:lockup 用 60–80 f 组装,然后静止保持 36–80 f,或继续构建(不超过 6% 的缓慢移动;保持超过约 1.3 秒时可使用 10–20% 推进),最后接尾音。绝不能直接切到完整静止的片尾卡,也绝不能停留在静止片尾卡超过约 2.5 秒,否则会显得拖沓。URL 至少保持可读 1.7 秒。
    • 在发布影片或产品视频中,lockup 只在结尾出现一次(sting 除外,因为它本身就是 lockup)。影片中段先展示 logo,之后又出现相同 lockup,会显得重复并浪费数秒停留在静止画面上。唯一例外是,在运行时间约 20–26% 处,在长度至少 10 秒的问题段落之后展示产品名称或标志,同时片尾卡采用不同构造或呼应开场。中段应通过视觉装置和强调色体现品牌。整个影片中 logo 出现时间应控制在总时长的 ≤ 12%。
  • 密度
    • 目标是每 30 秒包含 45–60 个离散事件,每个小节一个运动峰值,峰值之间保留 30–70 f 的平静区间。
    • 最初 6 秒的信息密度约为中段的两倍。
    • 能量应向 payoff 增长。转折之后不应存在比之前更慢、更灰的区段,唯一例外是在运行时约 55–85% 处、音乐 breakdown 内部安排一次 1–4 秒的设计性停顿;最后且最大的视觉峰值应落在 75–90% 处,与音乐重新进入同步。强健的后半段不能拖沓。通过后半段接触表用肉眼检查能量。
    • 最后三分之一仍应持续运动:镜头推进、次级运动,或视觉装置继续行动。如果影片在结束前 4 秒就停下来,它实际上已经提前结束。
    • 镜头长度:中位数为 60–90 f;最短 24 f(且不能有文字);由切镜驱动的影片最长 180 f,而连续长镜头可达 300–560 f,但镜头内部至少每 72 f 要有一个节拍落点。
  • 钩子:
    • 第 0 帧已完成构图并处于运动中;
    • 声音从第 0 帧带着明确意图进入,首小节不做淡入;
    • 每约 0.5 秒都有可见变化;
    • 1 秒内让人感受到问题,2 秒内明确表达;
    • 产品在约四分之一运行时之前就应出现在屏幕上,例如通过应用界面、状态栏中的名称或标志,而不是留到片尾卡。
    软弱的第一秒会直接失去静音信息流中的观众。
  • **片尾卡:**若 brief 提供了一项实用信息,应在 lockup 下方以次级字号呈现,例如日期“next week”、URL 或“out now”。如果没有,发布影片或产品视频仍应在名称下方用一句短文说明产品是什么,例如“The build cache for CI.”;只有 sting 才使用裸名称。这是名称之外唯一允许出现的文字。
  • **状态跟随事件:**计数器、勾选状态和总数在引发变化的对象落地帧上改变,而不是延后一个节拍。
声音应落在哪里(由
src/lib/sync.ts
计算:
peak
、
hit
、
delayTo
、
settleOf
):
画面事件声音位置
落地/冲击接触帧,因此运动必须带着速度抵达(spring 阈值 0.92–1.0,或使用
contact
缓动)
Pop-in行程达到 50% 的帧
Tween settle达到 97% 的帧
Whoosh(镜头尺度移动和 logo 缩放,每部约 2 次)提前 100–450 ms 进入,在视觉峰值达到顶点
打字每个按键最多 25 字符/秒,每个词上方发出一次轻响(
"typing": "auto"
)
退出滚动一次 tick,不带 detent
切镜、滚动、流式效果、进度条、滚动计数器无独立音效:由音乐承载;计数器最终锁定时发出一次清脆 tick
声音比画面提前超过约 45 ms 会听起来像“声音先行”。应移动画面,而不是移动声音。

6. Motion system essentials

6. 运动系统要点

The tokens live in
src/lib/anim.ts
(
E
,
SPR
,
tw
,
prog
,
mix
,
lmix
,
hitPulse
,
blurIn
,
arrive
,
arriveK
,
stagger
,
inertia
,
rand
,
fd
), and tested primitives for the commonest moves in
src/fx/
(
Words
,
TypeOn
,
Scramble
,
Roll
,
Morph
,
Iris
,
MaskRise
,
Cursor
,
RackFocus
): use them before writing your own. Curves, measured values and choreography constants are in
references/motion-tokens.md
; camera work is in
references/camera.md
.
TokenBezierUse
out
.16,1,.3,1arrivals, reveals
outSoft
.22,1,.36,1gentle settles
in
.7,0,.84,0implosions, a hard snap out
exit
.55,.055,.675,.19exits into a cut: about ×1.14 per frame over the last 10–24 f
inOut
.87,0,.13,1whips, lockup slides
smooth
.65,0,.35,1drifts, fades (10–14 f)
ui
.4,0,.2,1small UI changes
cam
.48,.1,0,.9camera: slow start, peak at about 27%, long settle
glide
.47,.2,.15,1150–350 px moves
rest
.45,0,.1,1moves that end at rest; chaining after another move
contact
.55,0,.9,.55accelerating into an impact
whip
.6,0,.15,1feature-to-feature whips
dolly
.35,0,.65,1slow push through a hold
A film uses about 3 easing characters. Linear is only for drift.
Springs (
SPR
, as damping/stiffness/mass):
snap
18/260/0.7 (small overshoot),
pop
11/180/0.6 (a landing only),
soft
26/120/1 (no overshoot),
heavy
30/90/1.4 (weighty).
  • Damping. Everything is eased or critically damped: damping ≥ 2√(stiffness·mass). Overshoot (1–7%) belongs only to a true landing, an object arriving at a surface or a lock, at most 2 per film, because a bounce anywhere else reads as a toy.
  • Smoothness is a ship gate. Jitter, pixel-snap stairs, single-frame pops and stall-then-lurch block the ship however good the idea is: zero
    forensics.py
    fails and Finish at 5 (§8).
  • Clamp. Clamp overshoot wherever it could collide with other geometry or drive a value negative. Snap to rest when
    |1 − s| < 0.01
    .
  • Easing.spring({damping:200})
    starts at zero velocity, so it is not a replacement for expo-out.
Laws of weight:
  • Direction. Entrances decay and exits accelerate; only the camera eases both ways. A fade-out never uses expo-out, because it pops half the change in one frame.
  • Log space. Interpolate scale and zoom in log space:
    exp(mix(log a, log b, t))
    , which is
    lmix
    .
  • Duration. Duration grows with distance: 0.35 s + 1.35 ms per px, clamped to 0.6–2.4 s for camera moves. The slowest move is at least 3× the fastest.
  • Shape and contact. Shape settles 6 f before position. Contacts squash (scaleX 1.08 → 1, scaleY 0.9 → 1 over 8 f, anchored at the contact edge).
  • Overlap. A secondary move starts at 55–75% of the leading move (about 20 f into a 60 f move), so both settle within 2 f, or it starts on a zero-slope curve. This prevents stall-then-lurch.
  • Budget. Run one hero motion plus at most 2 supporting ones. Put fast (60–70 px/f whips) next to real stillness (0.3–0.6 px/f). Anything faster than 12 px/f gets true motion blur in Step 6.
  • Ceiling. No element moves faster than about 60–80 px/f. Past that, blur smears it into a streak with stepped copies; redesign the move as a cut on the beat, a match cut, a mask wipe or a shorter distance. Frame-filling edges (wipes, floods, irises, zoom-throughs, a container growing to full frame) may peak at 150–300 px/f for a few frames.
  • Envelope. Every punch and tick uses
    hitPulse(t, attack = 2, tau = 5)
    . A half-sine on a hard window leaves velocity clunks and peaks 6–8 f late.
  • Seams
    • Either both sides of a cut are at rest, or the incoming shot starts at the outgoing velocity.
    • Match every property across a cut, and show the rest pose once.
    • Never cross-fade two copies of one object; morph one object instead.
Token 位于
src/lib/anim.ts
(
E
、
SPR
、
tw
、
prog
、
mix
、
lmix
、
hitPulse
、
blurIn
、
arrive
、
arriveK
、
stagger
、
inertia
、
rand
、
fd
),常用动作的已测试 primitive 位于
src/fx/
(
Words
、
TypeOn
、
Scramble
、
Roll
、
Morph
、
Iris
、
MaskRise
、
Cursor
、
RackFocus
):应先使用这些现成实现,再自行编写。曲线、量化数值和编排常量见
references/motion-tokens.md
;镜头工作见
references/camera.md
。
TokenBezier用途
out
.16,1,.3,1进入、揭示
outSoft
.22,1,.36,1柔和稳定
in
.7,0,.84,0聚拢、猛烈弹出
exit
.55,.055,.675,.19退出并切镜:最后 10–24 f 约每帧 ×1.14
inOut
.87,0,.13,1快速甩动、lockup 滑入
smooth
.65,0,.35,1漂移、淡出(10–14 f)
ui
.4,0,.2,1小型 UI 变化
cam
.48,.1,0,.9镜头:缓慢启动,约 27% 达到峰值,长时间稳定
glide
.47,.2,.15,1150–350 px 移动
rest
.45,0,.1,1最终停驻的动作;用于串联后续动作
contact
.55,0,.9,.55加速撞入接触点
whip
.6,0,.15,1功能之间的快速甩动
dolly
.35,0,.65,1停留期间缓慢推进
一部影片约使用 3 种缓动性格。Linear 只用于漂移。
Spring(
SPR
,以 damping/stiffness/mass 表示):
snap
18/260/0.7(轻微 overshoot)、
pop
11/180/0.6(仅用于落地)、
soft
26/120/1(无 overshoot)、
heavy
30/90/1.4(富有重量感)。
  • Damping。 所有运动都应经过缓动或临界阻尼:damping ≥ 2√(stiffness·mass)。Overshoot(1–7%)只属于真正的落地、物体抵达表面或 lockup,每部影片最多 2 次,因为其他位置的弹跳会显得像玩具。
  • 平滑度是交付关卡。 抖动、像素阶梯、单帧突兀跳变以及停顿后突然 lurch 都会阻止交付,无论创意多好:
    forensics.py
    必须零失败,§8 的 Finish 必须为 5。
  • Clamp。 对所有可能与其他几何体碰撞或产生负值的几何参数进行限制。当
    |1 − s| < 0.01
    时吸附至静止。
  • Easing.spring({damping:200})
    从零速度开始,因此不能替代 expo-out。
重量感法则:
  • 方向。 进入动作逐渐衰减,退出动作逐渐加速;只有镜头运动双向缓动。淡出绝不能使用 expo-out,因为它会在一帧内突然完成一半变化。
  • 对数空间。 在对数空间中插值缩放和 zoom:
    exp(mix(log a, log b, t))
    ,即
    lmix
    。
  • 时长。 时长随距离增加:0.35 秒 + 每 px 1.35 ms,镜头移动限制在 0.6–2.4 秒。最慢动作至少应为最快动作的 3 倍。
  • 形态与接触。 形态比位置早 6 f 稳定。接触时发生挤压(scaleX 1.08 → 1,scaleY 0.9 → 1,在 8 f 内完成,并以接触边缘为锚点)。
  • 重叠。 次级动作在主动作完成 55–75% 时启动(60 f 动作中约第 20 f),让两者在 2 f 内同时稳定;或者从零斜率曲线开始,防止停顿后突然 lurch。
  • 预算。 同时运行一个核心运动和最多两个辅助动作。将快速动作(60–70 px/f 甩动)放在真实静止(0.3–0.6 px/f)旁。任何速度超过 12 px/f 的动作都应在步骤 6 中加入真实运动模糊。
  • 上限。 任何元素的速度都不得超过约 60–80 px/f。超过此值后,模糊会将元素涂抹成带有阶梯重影的轨迹;应将动作重新设计为节拍上的切镜、match cut、遮罩擦除或更短距离。占满画面的边缘(擦除、flood、iris、zoom-through、容器扩展至全屏)可在少数几帧内达到 150–300 px/f。
  • 包络。 每个 punch 和 tick 都使用
    hitPulse(t, attack = 2, tau = 5)
    。在硬窗口上使用半正弦会留下速度顿挫,并使峰值延迟 6–8 f。
  • 接缝
    • 切镜两侧要么都处于静止,要么新镜头从旧镜头的速度开始。
    • 跨切镜匹配所有属性,并展示一次静止姿态。
    • 绝不对同一对象的两个副本使用 crossfade;应形变同一个对象。

7. Engine non-negotiables

7. 引擎硬性规则

These come from real failures. Each costs minutes to respect and hours to debug.
Both engines
  • Everything is a function of frame or time.
    • No CSS
      transition
      ,
      animation
      or
      @keyframes
      , because they don't render deterministically.
    • No
      Math.random
      ,
      Date.now
      or
      performance.now
      ; use a seeded
      rand(seed)
      .
  • Transforms
    • Put all translation inside one
      transform
      (
      left:0; top:0; transform-origin:0 0; transform: translate() scale()
      ). A fractional left/top combined with a transform snaps to whole pixels.
    • Place dots and cursors by transform only.
    • Vertical text positions snap to whole pixels in the headless shell, so end a text rise on
      arrive(p)
      (and start an exit on
      depart(q)
      ) instead of letting an ease-out creep its last pixels (
      references/chromium-rendering.md
      §15).
  • Blur
    • Never put
      will-change
      on a layer where
      filter: blur()
      animates. It causes nondeterministic ghost frames.
    • Never animate blur on large layers; use
      src/fx/RackFocus.tsx
      .
  • Discrete state
    • Clamp every value that feeds geometry, so radius, width, blur and scale stay ≥ 0.
    • Compute discrete state (typed count, caret, counters, labels) from
      fd(frame)
      (
      Math.round
      ), because motion-blur sub-frames are fractional.
  • Fonts. Load fonts before any render or text measurement (
    FontGate
    ). A measurement taken earlier is cached with the fallback width.
Remotion (
references/remotion-engine.md
)
  • Clamping.
    interpolate
    extrapolates by default, so always clamp;
    tw()
    and
    prog()
    do it for you.
  • premountFor
    only affects Studio preview and does nothing in a render. With
    layout="none"
    it is silently ignored in 4.0.529 (no error). Don't build on it.
  • Studio
    Interactive.*
    markup
    is an optional leaf layer, never the structure.
  • Config. Render with
    --muted
    and let ffmpeg mux the audio (Remotion's AAC leaves about 2.5 f of priming). Use the ANGLE GL renderer, JPEG q95 intermediates and a 120 s
    delayRender
    timeout; the starter's
    remotion.config.ts
    sets all of these.
  • Browser. In a sandbox, set
    REMOTION_BROWSER
    to the local headless Chromium if auto-detection misses it.
HyperFrames (
references/hyperframes-engine.md
)
  • Timeline. Each composition has one paused timeline, registered last, with a key equal to its
    data-composition-id
    .
  • Tweens
    • Use
      fromTo
      , never
      from
      .
    • Never combine a CSS transform with a GSAP transform on one node.
  • Markup
    • No
      repeat:-1
      . No
      <br>
      .
    • Every
      <audio>
      has an
      id
      ; one without is silently dropped from the mix.
    • A sub-composition's
      <style>
      and
      <script>
      go inside its
      <template>
      .
  • Fonts are local woff2 files declared with
    @font-face
    .
  • Lint. Lint must show zero errors before
    check
    means anything, because otherwise it reports a misleadingly clean "0 samples".
  • Finish. Finish with
    bash scripts/hf-finish.sh
    . Films faster than about 18 px/f belong in Remotion.
以下规则来自真实失败案例。遵守它们只需几分钟,忽略它们则需要数小时调试。
两种引擎通用
  • 所有内容都必须是帧或时间的函数。
    • 禁止 CSS
      transition
      、
      animation
      或
      @keyframes
      ,因为它们无法确定性渲染。
    • 禁止
      Math.random
      、
      Date.now
      或
      performance.now
      ;使用带 seed 的
      rand(seed)
      。
  • Transform
    • 将所有平移放入同一个
      transform
      (
      left:0; top:0; transform-origin:0 0; transform: translate() scale()
      )。小数 left/top 与 transform 同时使用会吸附到整像素。
    • 点和鼠标指针只能通过 transform 定位。
    • 无头 shell 中的垂直文字位置会吸附到整像素,因此文字上升应在
      arrive(p)
      结束,退出应在
      depart(q)
      开始,而不能让 ease-out 在最后几像素缓慢爬行(见
      references/chromium-rendering.md
      §15)。
  • Blur
    • 在
      filter: blur()
      动画所在的层上禁止使用
      will-change
      ,否则会产生不确定的鬼帧。
    • 禁止在大型图层上动画模糊;使用
      src/fx/RackFocus.tsx
      。
  • 离散状态
    • 限制所有输入几何体的值,确保 radius、width、blur 和 scale ≥ 0。
    • 离散状态(已输入字符数、光标、计数器、标签)必须通过
      fd(frame)
      (
      Math.round
      )计算,因为运动模糊子帧可能是小数。
  • 字体。 在任何渲染或文字测量之前加载字体(
    FontGate
    )。提前测量会缓存 fallback 的宽度。
Remotion(
references/remotion-engine.md
)
  • Clamping。
    interpolate
    默认会外推,因此始终进行 clamp;
    tw()
    和
    prog()
    已内置该行为。
  • premountFor
    只影响 Studio 预览,在渲染中不起作用。在 4.0.529 中使用
    layout="none"
    时会被静默忽略,不会报错。不要依赖它构建功能。
  • Studio
    Interactive.*
    markup
    只能作为可选叶子层,绝不能作为结构。
  • 配置。 使用
    --muted
    渲染并让 ffmpeg 封装音频(Remotion 的 AAC 会留下约 2.5 f 的 priming)。使用 ANGLE GL renderer、JPEG q95 中间文件和 120 秒
    delayRender
    超时;初始模板的
    remotion.config.ts
    已设置这些选项。
  • 浏览器。 在 sandbox 中,如果自动检测失败,应将
    REMOTION_BROWSER
    指向本地 headless Chromium。
HyperFrames(
references/hyperframes-engine.md
)
  • 时间线。 每个 composition 包含一条暂停时间线,并最后注册,其 key 等于
    data-composition-id
    。
  • Tween。
    • 使用
      fromTo
      ,绝不使用
      from
      。
    • 绝不能在同一节点上组合 CSS transform 与 GSAP transform。
  • Markup。 禁止
    repeat:-1
    ,禁止
    <br>
    。
    • 每个
      <audio>
      都必须具有
      id
      ;没有
      id
      的音频会被静默从混音中丢弃。
    • 子 composition 的
      <style>
      和
      <script>
      必须放在其
      <template>
      内。
  • 字体使用通过
    @font-face
    声明的本地 woff2 文件。
  • Lint。 在
    check
    有意义之前,lint 必须显示零错误,否则它会错误地报告“0 samples”。
  • Finish。 使用
    bash scripts/hf-finish.sh
    完成。速度超过约 18 px/f 的影片应改用 Remotion。

8. Review loop and ship gate

8. 评审循环与交付关卡

The full procedure, the critic prompts, the rubric anchors and the table of thresholds are in
references/review-loop.md
. A round goes like this:
  1. Render. Render the preview (or the affected acts).
  2. Measure. Run the scripts. Each writes JSON to
    out/qa/
    :
    • python3 scripts/probe.py out/preview.mp4 --spec 1920x1080@60 --dur <s>
    • python3 scripts/forensics.py out/preview.mp4 --cues out/cues.json --json out/qa/forensics.json
      . It checks pops, stalls, dead holds, ghost frames, border slivers, judder, sharpness steps, banding and compression smear on flat fields. Declare designed cuts and freezes with
      --cuts
      and
      --freeze-ok
      so they are not flagged, and add
      --loop
      for loops to check the seam.
    • python3 scripts/av-audit.py out/preview.mp4 --cues out/cues.json --stems out/stems --json out/qa/av.json
      . It checks onsets against cues (per stem, so the bed cannot hide a late effect), loudness, true peak, clicks and the tail.
  3. Sheets. Make contact sheets with
    python3 scripts/sheet.py out/preview.mp4 --chunks 4 --rate 12 --out out/qa/sheet.png
    , plus a legibility sheet at
    --width 480
    . Grab exact frames with
    bash scripts/grab.sh out/preview.mp4 <frame>…
    .
  4. Lenses. Run the critic lenses from
    assets/critics/
    . Launch them as parallel subagents if the harness allows it; otherwise run them one after another, and look at the sheet before you open the code. On a tight usage budget, run the director and art lenses only, yourself, on the sheets, and let the scripts cover forensics and sync; never skip the lenses entirely, because they catch most of what the scripts can't.
    • Director (
      director.md
      ): the weakest 3 s; anything cheap, templated or dead; whether each act lands in under 1 s; whether the story reads muted; the 2 s hook; the end. At most 12 changes.
    • Forensics (
      forensics.md
      ): reads the script JSON and inspects the flagged frames at full size.
    • Sound/sync (
      sound-sync.md
      ): onsets against cues, masking, key, the ending.
    • Round 1 only, art/copy/UI (
      art-copy-ui.md
      ): type, colour discipline, strings, data truth.
  5. Output format. Each lens returns
    {issues:[{id, priority, frame, problem, fix:{file, change}}], overall, score}
    .
  6. Verify (
    verifier.md
    ). Try to refute each P0 and P1 from frames and code. Drop an issue if it is wrong, invisible at normal speed, or if its fix would make things worse.
  7. Fix and re-render. Fix in order of impact per minute. Re-render only the affected acts (per-act compositions) and splice at a static seam frame.
Critic prompts say what changed, so it gets checked hardest. They also say "Do not re-report fixed issues" and "Don't propose adding text", and they batch images into sheets, because images are expensive in context. When one act stays weak after two rounds, run the design-off in
review-loop.md
.
Severity: P0 is visible on a key beat (hook, payoff, logo) or breaks the story; P1 is noticeable on a normal viewing; P2 is visible only when paused.
Ship gate
  • The 11-dimension rubric: every dimension ≥ 3, Finish and Sync = 5, mean ≥ 4.2.
  • No open P0.
  • Every script passes.
  • Stop after 5 rounds, or sooner once the gate is met. Then say plainly what you would still change.
完整流程、评审提示词、评分标准锚点和阈值表见
references/review-loop.md
。一轮流程如下:
  1. 渲染。 渲染预览或受影响的 act。
  2. 测量。 运行脚本。每个脚本都会向
    out/qa/
    写入 JSON:
    • python3 scripts/probe.py out/preview.mp4 --spec 1920x1080@60 --dur <s>
    • python3 scripts/forensics.py out/preview.mp4 --cues out/cues.json --json out/qa/forensics.json
      。它检查突兀跳帧、停顿、过长静止、鬼帧、边缘细条、抖动、清晰度阶梯、色带和纯色区域的压缩涂抹。使用
      --cuts
      和
      --freeze-ok
      声明设计性切镜与冻结,避免误报;循环动画添加
      --loop
      以检查接缝。
    • python3 scripts/av-audit.py out/preview.mp4 --cues out/cues.json --stems out/stems --json out/qa/av.json
      。它按 stem 检查 onset 与 cue 的对应关系,避免音乐床掩盖延迟音效,同时检查响度、true peak、click 和尾音。
  3. 接触表。 使用
    python3 scripts/sheet.py out/preview.mp4 --chunks 4 --rate 12 --out out/qa/sheet.png
    创建接触表,并使用
    --width 480
    创建可读性表。通过
    bash scripts/grab.sh out/preview.mp4 <frame>…
    抓取精确帧。
  4. 评审视角。 运行
    assets/critics/
    中的评审 lens。如果执行环境允许,将其作为并行 subagent 启动;否则逐个运行,并先查看接触表,再打开代码。预算紧张时,只亲自对接触表运行 Director 和 Art lens,让脚本负责取证和同步检查;但绝不能完全跳过 lens,因为它们能发现大多数脚本无法发现的问题。
    • Director(
      director.md
      ):最薄弱的 3 秒;任何廉价、模板化或死气沉沉的内容;每个 act 是否在 1 秒内落下;故事静音时是否成立;前 2 秒钩子;结尾。最多提出 12 项修改。
    • Forensics(
      forensics.md
      ):读取脚本 JSON,并以全尺寸检查被标记的帧。
    • Sound/sync(
      sound-sync.md
      ):检查 onset 与 cue、遮蔽、调性和结尾。
    • 仅第 1 轮,Art/copy/UI(
      art-copy-ui.md
      ):字体、颜色纪律、文案和数据真实性。
  5. 输出格式。 每个 lens 返回
    {issues:[{id, priority, frame, problem, fix:{file, change}}], overall, score}
    。
  6. 验证(
    verifier.md
    )。尝试从帧和代码中反驳每个 P0 与 P1。如果问题错误、正常播放速度下不可见,或修复会让结果更差,则将其删除。
  7. 修复并重新渲染。 按每分钟投入可带来的影响排序。只重新渲染受影响的 act(独立 act composition),并在静态接缝帧处拼接。
评审提示词会说明哪些内容发生了变化,因此应对其进行最严格检查。提示词还会要求“不要重新报告已修复问题”和“不要建议增加文字”,并要求批量提供图像,因为图像的上下文成本很高。如果一个 act 经过两轮仍然薄弱,运行
review-loop.md
中的 design-off。
**严重程度:**P0 在关键节拍(钩子、payoff、logo)清晰可见或破坏故事;P1 在正常观看时明显;P2 仅在暂停时可见。
交付关卡
  • 11 个评分维度中,每项 ≥ 3,Finish 和 Sync = 5,平均分 ≥ 4.2。
  • 没有未解决的 P0。
  • 所有脚本通过。
  • 最多进行 5 轮,或达到关卡后提前停止。最后应明确说明仍会修改的内容。

9. File index

9. 文件索引

Read each file when its step comes up. Don't read them all at once.
WhenFileWhat it gives you
Step 0, choosing a format
references/formats.md
a recipe per format: act templates, loops, stings, walkthroughs, social re-layouts
Before the first film
references/worked-example.md
Tessel from idea to master, with 15 mistakes and their fixes
Step 1
references/concept-and-story.md
concept lenses, ownership and deletion tests, device design, arcs, end cards
Step 1
assets/TREATMENT.md
the treatment template
Step 1, after the draw
references/technique-library.md
every technique in the library: recipe, timing at 60 fps, when to use and avoid it
Steps 1, 3–4 and review
references/craft-rules.md
measured norms for pacing, smoothness, text timing, transitions, camera, UI and colour over time
Steps 1–2
references/copy-and-type.md
copy budget, callback copy, loading a family, type scale, kinetic type, safe reveals
Step 2
references/brand-and-color.md
personality → choices, naming, the mark sheet, lockup proportions, tokens, accent, stages
Step 2 and review
references/taste-and-slop.md
every cheap-looking tell, with its fix
Step 3
references/timing-grid.md
BPM/fps table, the
timeline.ts
pattern, sync helpers, schedules, typing cadence
Step 4
references/motion-tokens.md
easing and spring tables,
hitPulse
, anticipation, landings, staggers
Step 4
references/camera.md
anchor camera, log-space zoom, breath/dip modifiers, rack focus, 3D limits
Step 4
references/transitions.md
energy table and the seam catalogue, each with frames, curves and failure modes
Step 4
references/product-ui.md
the smart part, data and story asserts, FLIP inserts, counters, cursor physics, typing
Step 4, Remotion
references/remotion-engine.md
verified API facts, config, CLI recipes, pitfalls
Step 4, HyperFrames
references/hyperframes-engine.md
render model, composition rules, CLI, translating cinetic to GSAP
Any render artifact
references/chromium-rendering.md
symptom → cause → fix → detection for rasterisation traps
Step 5
references/sound.md
synthesis palette,
score.json
schema, placement, mix and master
Step 6
references/finishing.md
motion-blur pipeline and its cost, banding, BT.709, encoding, mux, deliverables
Step 7
references/review-loop.md
round procedure, rubric, severity, thresholds, design-off
Tools you already have. Reach for these before writing a helper of your own.
NeedTool
a project from the starter
scripts/new-film.sh
a random, weighted draw of techniques for the film; one entry in full
scripts/pick.py
(
--show <id>
,
--list
)
static bans and hard bans, a leftover placeholder brand
scripts/lint-film.mjs
grid, holds, gaps, word budget; text in the safe zone (feed presets:
--safe feed9x16
), text covered by movers, readable text faster than 20 px/f (
--cues
)
scripts/grid-check.ts
;
scripts/layout-audit.sh
a font family, vendored into the project without
npm install
scripts/add-font.mjs
(or
new-film.sh --font
)
a palette from one accent, contrast, accent coverage on a still
scripts/palette.py
gradients that don't band
scripts/dither-gradient.py
cues for the sound; score, SFX, mix, master and tail fade
scripts/export-cues.ts
;
scripts/audio/score.py
,
synth.py
,
master.py
previews, masters, motion blur, splices, chunked renders
scripts/render.sh
(
--preview
,
--blur
,
--frames
,
--budget
),
scripts/render-chunks.sh
on-screen speed, too-fast moves; float accumulation
scripts/measure-speed.py
;
scripts/accumulate.py
spec, A/V lag and true-peak gates
scripts/probe.py
,
scripts/check-sync.py
contact sheets, exact frame grabs
scripts/sheet.py
,
scripts/grab.sh
pixel QA, loop seam; audio and sync QA
scripts/forensics.py
(
--loop
);
scripts/av-audit.py
poster, GIF, WebM, loop seam, alpha, variants
scripts/deliver.sh
brand kit: SVG and PNG mark and lockups, favicons, avatar, X header; outlined lettering
scripts/brand-kit.sh
;
scripts/outline-text.py
the HyperFrames finish
scripts/hf-finish.sh
每到一个步骤再阅读对应文件,不要一次全部读完。
阅读时机文件内容
步骤 0,选择格式
references/formats.md
各格式的制作方案:act 模板、循环动画、sting、UI 演示、社交媒体重排版
首次制作影片前
references/worked-example.md
Tessel 从概念到母版的完整过程,包含 15 个错误及修复方式
步骤 1
references/concept-and-story.md
概念视角、产品专属性、删除测试、视觉装置设计、弧线、片尾卡
步骤 1
assets/TREATMENT.md
方案模板
步骤 1,抽取后
references/technique-library.md
技法库中的所有条目:方案、60 fps 下的时长、适用及不适用场景
步骤 1、3–4 及评审
references/craft-rules.md
随时间变化的节奏、平滑度、文字时间、转场、镜头、UI 和颜色量化规范
步骤 1–2
references/copy-and-type.md
文案预算、呼应文案、加载字体家族、字号体系、动态排版、安全揭示方式
步骤 2
references/brand-and-color.md
个性到选择的映射、命名、标志图板、lockup 比例、token、强调色、舞台
步骤 2 及评审
references/taste-and-slop.md
所有显得廉价的视觉特征及其修复方式
步骤 3
references/timing-grid.md
BPM/fps 表、
timeline.ts
模式、同步辅助函数、时间表、打字节奏
步骤 4
references/motion-tokens.md
缓动和 spring 表、
hitPulse
、预备动作、落地、错峰
步骤 4
references/camera.md
锚定镜头、对数空间缩放、呼吸/压低修正、rack focus、3D 限制
步骤 4
references/transitions.md
能量表和接缝目录,包含帧数、曲线及失败模式
步骤 4
references/product-ui.md
聪明部分、数据和故事断言、FLIP 插入、计数器、鼠标指针物理、打字
步骤 4,Remotion
references/remotion-engine.md
已验证的 API 事实、配置、CLI 方案和陷阱
步骤 4,HyperFrames
references/hyperframes-engine.md
渲染模型、composition 规则、CLI、将 cinetic 转换为 GSAP 的方法
出现任何渲染伪影时
references/chromium-rendering.md
症状 → 原因 → 修复 → 检测方式
步骤 5
references/sound.md
合成音色、score.json schema、放置、混音和母版
步骤 6
references/finishing.md
运动模糊流程及成本、色带、BT.709、编码、封装、交付物
步骤 7
references/review-loop.md
轮次流程、评分标准、严重程度、阈值、design-off
你已经拥有的工具。 在自行编写 helper 前,应先使用这些工具。
需求工具
从初始模板创建项目
scripts/new-film.sh
为影片随机、加权抽取技法;完整查看某个条目
scripts/pick.py
(
--show <id>
、
--list
)
检查静态禁令、硬性禁令和残留占位品牌
scripts/lint-film.mjs
检查网格、停留、间隔、字数预算;文字是否位于安全区(信息流预设:
--safe feed9x16
)、移动元素是否遮挡文字、可读文字速度是否超过 20 px/f(
--cues
)
scripts/grid-check.ts
;
scripts/layout-audit.sh
获取字体家族并打包到项目中,无需
npm install
scripts/add-font.mjs
(或
new-film.sh --font
)
根据一种强调色生成色板、对比度和静帧中的强调色覆盖率
scripts/palette.py
生成无色带渐变
scripts/dither-gradient.py
导出声音 cue;生成 score、SFX、混音、母版和尾音淡出
scripts/export-cues.ts
;
scripts/audio/score.py
、
synth.py
、
master.py
预览、母版、运动模糊、拼接和分块渲染
scripts/render.sh
(
--preview
、
--blur
、
--frames
、
--budget
)、
scripts/render-chunks.sh
屏幕运动速度、过快动作;浮点累积
scripts/measure-speed.py
;
scripts/accumulate.py
规格、A/V 延迟和 true peak 关卡
scripts/probe.py
、
scripts/check-sync.py
接触表、精确帧抓取
scripts/sheet.py
、
scripts/grab.sh
像素 QA、循环接缝、音频和同步 QA
scripts/forensics.py
(
--loop
);
scripts/av-audit.py
海报、GIF、WebM、循环接缝、alpha、变体
scripts/deliver.sh
品牌套件:SVG 和 PNG 标志与 lockup、favicon、头像、X header;轮廓化文字
scripts/brand-kit.sh
;
scripts/outline-text.py
HyperFrames 后期
scripts/hf-finish.sh