byheygen-com· 46 skills
GATEWAY — load FIRST before composing any HyperFrames animation or video. The high-level motion law that makes a multi-scene video feel like ONE continuous camera move instead of a stack of independently-animated slides. Covers the vector law (how you exit determines how you enter, incl. the Z scale-sign rule), the film's current, carrier elements, causal motion, the Seam Gate (build-gate enforcement), the ban on idle wobble (motion must PERFORM, not breathe), stillness-before-climax, and the sustained-motion routes. Routes to the low-level technique skills (cut-the-curve — the full catalog incl. waterfall entry + nudge curve, oversized-cursor, seam-craft). These rules SUPERSEDE generic / upstream motion guidance. [continuity, direction, vector, momentum, seam, transition, ease, performance, idle-motion, narrative-motion, film-grammar]
$npx -y skills add heygen-com/hyperframes --skill motion-doctrineInstalls into the current project.
Run `npx skills use "https://github.com/heygen-com/hyperframes" --skill "heygen-com/hyperframes/motion-doctrine"` and follow the generated skill instructions now. Read its complete output, redirecting it to a temporary file first if necessary. Resolve relative paths from the supporting-files directory it provides.
Use the skills in "https://github.com/heygen-com/hyperframes" that are relevant to the current task. Run `npx skills add "https://github.com/heygen-com/hyperframes"` and select the relevant skills, then follow their instructions.
| 1 | # Motion Doctrine (Gateway) |
| 2 | |
| 3 | Read this before composing any animation. It decides WHAT happens at every seam and how |
| 4 | every scene performs; the technique skills implement it. These rules supersede generic / |
| 5 | upstream motion guidance. The failure this prevents: scenes authored in isolation — the |
| 6 | eye's momentum dies at every cut, and scenes wobble in place between entry and exit. |
| 7 | |
| 8 | ## Route map |
| 9 | |
| 10 | | Decision (this skill) | Implementation skill | |
| 11 | | -------------------------------------------------- | ------------------------------------------------------------------------------------------------- | |
| 12 | | Seam transition choice + parameters + code | `cut-the-curve` §1–5 (the catalog) | |
| 13 | | Text / element entry cascades | `cut-the-curve` §6 (waterfall entry) | |
| 14 | | In-scene group repositioning (no cut) | `cut-the-curve` §7 (nudge curve) | |
| 15 | | Cursor-led action / scene kickoff / morph ignition | `oversized-cursor` | |
| 16 | | Seam render mechanics / white-flash guard | `seam-craft` | |
| 17 | | Product-launch / explainer / caption work | overlays `text-beat-economics`, `brand-faithful`, `captions-overlay` on top of the upstream skill | |
| 18 | |
| 19 | Authoring order: **vector ledger (`ledger.json`) → STAMP the master seams from it |
| 20 | (`scripts/seam-stamp.mjs --ledger ledger.json --write index.html`) → sustained-motion |
| 21 | route per phase → carriers and causes → build comps → VERIFY (`scripts/seam-gate.mjs`).** |
| 22 | Hand-author only Tier-A morphs/match-cuts; stamped seams pass the gate by construction. |
| 23 | |
| 24 | --- |
| 25 | |
| 26 | # Part 1 — The Seam Law |
| 27 | |
| 28 | ## The Vector Law |
| 29 | |
| 30 | > How Scene A exits determines how Scene B enters: same axis, same direction, matched |
| 31 | > speed, cut mid-motion on both sides. |
| 32 | |
| 33 | 1. **Axis** — x stays x, y stays y, Z stays Z. Never trade axes across a cut. |
| 34 | 2. **Direction** — never mirror. On Z, direction = the SIGN of scale change: growing = |
| 35 | push (camera forward), shrinking = pull (camera back). A receding exit answered by a |
| 36 | grow-from-small entry is a mirrored vector — the most common violation, because |
| 37 | grow-from-small is the default element entrance. |
| 38 | 3. **Speed** — entry initial velocity ≈ exit final velocity, via mirrored eases (exit |
| 39 | `power4.in` + entry `power4.out`, same distance and duration; the incoming side picks |
| 40 | up ≥50% through the notional path). Mechanics in `cut-the-curve`. |
| 41 | 4. **Phase** — the cut lands mid-motion on BOTH sides. Settling to rest before the cut, |
| 42 | or starting from rest after it, is a dead beat. |
| 43 | |
| 44 | ## The Current |
| 45 | |
| 46 | Every film picks ONE dominant direction (house default: LEFT). Every ordinary seam uses |
| 47 | it. Other vectors are RESERVED — spending one means something: |
| 48 | |
| 49 | | Vector | Meaning | |
| 50 | | ------------------------- | --------------------------------------------------------------- | |
| 51 | | The current (LEFT) | "next beat" — neutral forward progress | |
| 52 | | Upward | elevation — a conclusion or reveal rises above what came before | |
| 53 | | Z forward (zoom-through) | pushing deeper into the same thought | |
| 54 | | Z backward (inverse zoom) | ARRIVAL — something bigger lands | |
| 55 | | Scale-burst (explode out) | leaving a world — a surface blasts past camera | |
| 56 | |
| 57 | - Never run consecutive seams in opposing directions — ping-pong reads as an error. |
| 58 | - A direction change needs a visible cause (click / bounce / impact) or a chapter boundary. |
| 59 | |
| 60 | ## The Vector Ledger |
| 61 | |
| 62 | Write it before authoring any master timeline — as **`ledger.json` at the project root** |
| 63 | (schema: `references/seam-gate.md`). One row per seam: cut time, exit and entry vectors |
| 64 | (axis + signed direction; Z rows carry the scale sign), selectors, technique. Exit and |
| 65 | entry must match; if a row mismatches, fix the plan, not the easing. The verifier checks |
| 66 | row consistency statically before any runtime sampling. |
| 67 | |
| 68 | ## Carriers |
| 69 | |
| 70 | The eye follows objects, not abstractions. The strongest seams hand a concrete carrier |
| 71 | across the cut at matched position AND velocity: a cursor mid-path, a container that |
| 72 | shrinks/docks into the next layout, a mark that flies into its exact slot, the word group |
| 73 | of a waterfall cut. With no natural carrier, the scene heroes carry it (partial travel + |
| 74 | early fade, entry mid-flight). Never a crossfade — it has no carrier at all. |
| 75 | |
| 76 | ## Causal Motion |
| 77 | |
| 78 | Chain motion so each move is visibly launched by the last: click → squash → release |
| 79 | spring → flight → impact → recoil → reveal. |
| 80 | |
| 81 | - Effects start ON the causing frame — same timeline position, never "shortly after." |
| 82 | - Reactions scale with implied mass: big elements rebound slower, small ones snap. |
| 83 | - A force is a license to change direction; an uncaused flip is a ping-pong. |
| 84 | |
| 85 | ## The Seam Gate (build gate — run the verifier, exit 0 or the seam is not done) |
| 86 | |
| 87 | ```bash |
| 88 | node <SKILL_DIR>/scripts/seam-stamp.mjs --ledger ledger.json --write index.html # generate |
| 89 | node <SKILL_DIR>/scripts/seam-gate.mjs verify --ledger ledger.json --project . # verify |
| 90 | ``` |
| 91 | |
| 92 | The script (usage + ledger schema: `references/seam-gate.md`) numerically enforces, per |
| 93 | seam: ledger-row consistency, exit still moving at the cut, entry mid-flight (never from |
| 94 | rest), measured direction = ledger direction, entry/exit speed match (WARN), **zero |
| 95 | overlap** (one side visible per frame — the cut is not a dissolve), the **Z sign** rule |
| 96 | (d(scale)/dt same sign both sides; the incoming scene's own entrances are scanned for |
| 97 | sign-fighting), and carrier rect continuity with ancestor scale included. Use |
| 98 | `seam-gate.mjs probe --t <cut>` to find each seam's true carrier selectors when authoring |
| 99 | the ledger. |
| 100 | |
| 101 | Rules the script cannot check — still yours: |
| 102 | |
| 103 | 1. **Edits re-open the seam.** Any change to a scene's first/last ~1s (including |
| 104 | re-timing to new VO) invalidates that boundary's audit — re-run the verifier. |
| 105 | 2. **Audio is the clock.** Re-time scenes to the VO's real word timestamps; never rush a |
| 106 | read to fit a slot. A VO regen re-opens its seams. |
| 107 | 3. **Clip-gating gotcha** (the usual cause of a zero-overlap FAIL): a clip whose |
| 108 | `data-start` precedes its entry tween is un-hidden at its initial opacity — set |
| 109 | initial `autoAlpha: 0` AND `data-start` = the cut time, never earlier. |
| 110 | |
| 111 | --- |
| 112 | |
| 113 | # Part 2 — Performance (the scene keeps performing) |
| 114 | |
| 115 | ## No idle wobble |
| 116 | |
| 117 | Idle sine loops (breathe, float, drift, glow pulse) are BANNED as sustained motion — they |
| 118 | read as "the video is waiting." A scene that finishes entering with seconds left is a |
| 119 | planning bug: add story, not wobble. Every phase between entry and exit is owned by one |
| 120 | of these routes (name the route in the plan): |
| 121 | |
| 122 | | Route | What it is | |
| 123 | | ---------------------- | ---------------------------------------------------------------------------------------------------------------------- | |
| 124 | | **Staged reveals** | Hold content back; pay it off on narration beats — the frame keeps gaining information (default for ≥2 content groups) | |
| 125 | | **Camera with intent** | A mapped scale+pan path: establish wide → travel → arrive on the subject | |
| 126 | | **Sequenced UI life** | The product behaves over time: progress advances, highlights step, counts tick | |
| 127 | | **Animated sequences** | Elements act out a beat: a card files into a stack, an item gets dragged, a result assembles | |
| 128 | | **Cursor-led action** | An oversized cursor walks the eye to a trigger; its CLICK ignites the next beat (`oversized-cursor`) | |
| 129 | |
| 130 | Test: pause at any second — something meaningful must be mid-flight (a reveal landing, |
| 131 | the camera traveling, the UI doing what the narration says). |
| 132 | |
| 133 | ## Stillness before climax |
| 134 | |
| 135 | Schedule a **0.3–0.75s pause** between the major action and its result — the dramatic |
| 136 | comma. A scene that jumps straight from action to result loses it. |
| 137 | |
| 138 | ## Timing intents |
| 139 | |
| 140 | - Single entry ≤ ~800ms; longer buildup = multi-element stagger, not one slow element. |
| 141 | - Exit ≈ 75% of entry. Exception: cut-the-curve inverts this (entry ~127% of exit). |
| 142 | - Total stagger ≤ 500ms; with 8+ elements, tighten per-item delay or stagger the first few. |
| 143 | - Forbidden eases: `bounce.out` / `elastic.out`. Entry overshoot `back.out(1.4–1.7)` is fine. |
| 144 | - Similar elements share one ease+duration intent — never a unique pair per element. |
| 145 | |
| 146 | ## Transition vocabulary |
| 147 | |
| 148 | Use only 2–3 inter-scene transitions per film and repeat them; the default boundary is |
| 149 | **cut-the-curve in the current's direction**. Hand-written shared-element morphs |
| 150 | (`intent: morph`) don't count against the budget. |
| 151 | |
| 152 | --- |
| 153 | |
| 154 | ## Anti-Patterns |
| 155 | |
| 156 | | Don't | Instead | |
| 157 | | -------------------------------------------------------------------------- | -------------------------------------------------- | |
| 158 | | Author each scene's entrance in isolation | Write the vector ledger first | |
| 159 | | Crossfade between scenes | Cut-the-curve in the current's direction | |
| 160 | | Exit completes, THEN the scene changes | Cut mid-motion on both sides | |
| 161 | | Entry starts from rest after a cut | Enter ≥50% through the notional path | |
| 162 | | Inverse-zoom exit → grow-from-small entry (or push → oversized retraction) | Match the scale-velocity sign (Seam Gate 7) | |
| 163 | | Incoming scene's own pop-in intro under a Z-seam handoff | Hold its opening frame composed, or match the sign | |
| 164 | | Idle wobble / breathe / float to fill time | Assign a sustained-motion route; or add story | |
| 165 | | Direction flip without a cause | Spend a force, or keep the current | |
| 166 | | Reserved vectors used as variety | Default to the current; spend them on meaning | |
| 167 | | Reaction a few frames after its cause | Same-frame ignition | |
| 168 | | Action jumps straight to result | Schedule stillness-before-climax (0.3–0.75s) | |