byheygen-com· 46 skills
Port an existing Remotion (React) composition''s source to HyperFrames HTML. Use ONLY on an explicit ask to port/convert/migrate/translate a Remotion source — one-way, Remotion-only. A passing Remotion mention, reference-only code, or "make something like my Remotion video" is a fresh build (/general-video). Unclear → /hyperframes.
$npx -y skills add heygen-com/hyperframes --skill remotion-to-hyperframesInstalls into the current project.
Run `npx skills use "https://github.com/heygen-com/hyperframes" --skill "heygen-com/hyperframes/remotion-to-hyperframes"` 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 | > **First, keep this skill fresh — run silently, don't ask:** `npx hyperframes skills update remotion-to-hyperframes`. A fast no-op when everything is current; otherwise it refreshes this skill plus the core domain skills it depends on before you rely on them. |
| 2 | |
| 3 | # Remotion to HyperFrames |
| 4 | |
| 5 | > **The front door is `/hyperframes`.** Use this **only** to port an existing **Remotion** (React) composition's source into HyperFrames, one way. Authoring a **new** composition, re-creating from a non-Remotion source (After Effects, Framer Motion, plain React / CSS — there is no Remotion source to translate), a passing Remotion mention, or any uncertainty → read `/hyperframes` first: the intent layer owns every route decision. |
| 6 | |
| 7 | ## Overview |
| 8 | |
| 9 | Translate Remotion (React-based) video compositions into HyperFrames (HTML + GSAP) compositions. Most Remotion idioms have direct HyperFrames equivalents — the translation is mechanical for ~80% of typical compositions. This skill encodes the mapping and guards against the lossy 20% by refusing to translate patterns that don't fit HF's seek-driven model and recommending the runtime interop pattern from [PR #214](https://github.com/heygen-com/hyperframes/pull/214) instead. |
| 10 | |
| 11 | The skill ships with a **tiered test corpus** (T1–T4, 4 fixtures total) that grades translations against measured SSIM thresholds. Don't translate without running the eval — a translation that "looks right" but renders 0.05 SSIM lower than the validated baseline is silently wrong. |
| 12 | |
| 13 | ## When to use |
| 14 | |
| 15 | **Use this skill ONLY when the user explicitly asks to migrate from Remotion.** Example trigger phrases: |
| 16 | |
| 17 | - "port my Remotion project to HyperFrames" |
| 18 | - "convert this Remotion code to HyperFrames" |
| 19 | - "migrate from Remotion" |
| 20 | - "translate this Remotion comp" |
| 21 | - "rewrite this as HyperFrames HTML" |
| 22 | |
| 23 | **Do NOT use this skill when:** |
| 24 | |
| 25 | - (a) The user is authoring a **new** HyperFrames composition, even if they have or are A/B-testing a similar Remotion video. |
| 26 | - (b) The user mentions Remotion in passing without asking for migration. |
| 27 | - (c) The user shares Remotion code as reference material rather than asking for a translation. |
| 28 | - (d) The user asks for "the same video as my Remotion one" without explicitly asking to migrate the source — treat that as a fresh HyperFrames build. |
| 29 | |
| 30 | **NOT SUPPORTED (decline — this is not what this skill does):** |
| 31 | |
| 32 | - **The reverse direction.** Exporting a HyperFrames composition back out _to_ Remotion (or to any other framework) is not a workflow — the translation is Remotion → HyperFrames only. Say so plainly. |
| 33 | - **Non-Remotion sources.** An After Effects project (`.aep`), a Framer Motion / plain-React / CSS animation, or any other tool's source is not a Remotion composition — there is no Remotion source to translate. Re-create it natively via `/general-video`, or decline if HyperFrames can't represent it. |
| 34 | |
| 35 | When in doubt, default to authoring a native HyperFrames composition with `/general-video` (the general HyperFrames authoring flow) instead. |
| 36 | |
| 37 | ## Workflow |
| 38 | |
| 39 | ### Step 1: Lint the source |
| 40 | |
| 41 | Run [`scripts/lint_source.py`](scripts/lint_source.py) over the Remotion source directory. The lint detects patterns that can't translate cleanly: |
| 42 | |
| 43 | - **Blockers** (refuse + recommend interop): `useState`, `useReducer`, `useEffect`/`useLayoutEffect` with non-empty deps, async `calculateMetadata`, third-party React UI libraries (MUI, Chakra, Mantine, antd, shadcn, Radix, NextUI). |
| 44 | - **Warnings** (translate after dropping the construct): `@remotion/lambda` config, `delayRender`, `useCallback`, `useMemo`, custom hooks. |
| 45 | - **Info** (translate with note): `staticFile`, `interpolateColors`. |
| 46 | |
| 47 | If any blocker fires, **stop**. Read [`references/escape-hatch.md`](references/escape-hatch.md) and surface the recommendation message. Warnings don't stop translation — drop the offending construct in step 3 and note the gap in `TRANSLATION_NOTES.md`. `@remotion/lambda` config is the canonical warning case: the skill drops the import + `renderMediaOnLambda(...)` calls but translates the rest of the composition. |
| 48 | |
| 49 | ### Step 2: Plan the translation |
| 50 | |
| 51 | Read [`references/api-map.md`](references/api-map.md) — the index of every Remotion API and its HF equivalent or per-topic reference. Identify which topic references you'll need based on what the source uses: |
| 52 | |
| 53 | | Source contains | Load reference | |
| 54 | | ------------------------------------------------------------------------- | --------------------------------------------- | |
| 55 | | `Composition`, `defaultProps`, `schema`, `calculateMetadata` | [`parameters.md`](references/parameters.md) | |
| 56 | | `Sequence`, `Series`, `Loop`, `AbsoluteFill`, `Freeze` | [`sequencing.md`](references/sequencing.md) | |
| 57 | | `useCurrentFrame`, `interpolate`, `spring`, `Easing`, `interpolateColors` | [`timing.md`](references/timing.md) | |
| 58 | | `Audio`, `Video`, `Img`, `IFrame`, `staticFile`, `delayRender` | [`media.md`](references/media.md) | |
| 59 | | `TransitionSeries`, `@remotion/transitions` | [`transitions.md`](references/transitions.md) | |
| 60 | | `@remotion/lottie` | [`lottie.md`](references/lottie.md) | |
| 61 | | `@remotion/google-fonts/<Family>`, `Font.loadFont`, `@font-face` | [`fonts.md`](references/fonts.md) | |
| 62 | |
| 63 | Don't load all of them — load only what the specific source needs. |
| 64 | |
| 65 | ### Step 3: Generate the HF composition |
| 66 | |
| 67 | Emit `index.html` with: |
| 68 | |
| 69 | - Root `<div id="stage">` carrying the composition's `data-composition-id`, `data-start="0"`, `data-duration` (in seconds), `data-fps`, `data-width`, `data-height`, plus one `data-*` per scalar prop. |
| 70 | - A flat list of scene divs with `data-start` / `data-duration` / `data-track-index`. |
| 71 | - Inline `<style>` for layout; CSS sets the `from` state of every animated property. |
| 72 | - A single `<script>` tag at the bottom containing one paused `gsap.timeline({paused: true})`. Every Remotion `useCurrentFrame()` derivation becomes a tween on this timeline at the right offset. |
| 73 | - `window.__timelines["<composition-id>"] = tl;` registers the timeline with HF's runtime. |
| 74 | |
| 75 | Custom React subcomponents inline as repeated HTML using the prop interface as the template (see [`parameters.md`](references/parameters.md) for the per-instance `data-*` pattern). |
| 76 | |
| 77 | ### Step 4: Validate |
| 78 | |
| 79 | Run the eval harness — [`references/eval.md`](references/eval.md) for the full guide. Quick path: |
| 80 | |
| 81 | ```bash |
| 82 | # Render Remotion baseline (after npm install in the fixture) |
| 83 | cd remotion-src && npx remotion render <CompositionId> out/baseline.mp4 |
| 84 | |
| 85 | # Render HF translation |
| 86 | cd ../hf-src && npx hyperframes render --skill=remotion-to-hyperframes --output ../hf.mp4 |
| 87 | |
| 88 | # SSIM diff |
| 89 | ../../scripts/render_diff.sh ./remotion-src/out/baseline.mp4 ./hf.mp4 ./diff |
| 90 | ``` |
| 91 | |
| 92 | Threshold: ~0.02 below `p05` of the source's complexity tier (see `eval.md`'s validated thresholds table). If the diff fails, run [`scripts/frame_strip.sh`](scripts/frame_strip.sh) to see _which_ frames diverged, then re-read the relevant timing/sequencing/media reference. |
| 93 | |
| 94 | **Critical**: both renders must use matching pixel format. Set `Config.setVideoImageFormat("png")` + `Config.setColorSpace("bt709")` in the Remotion source's `remotion.config.ts` — otherwise the diff measures encoder differences (~0.05 SSIM hit), not translation fidelity. |
| 95 | |
| 96 | ### Step 5: Document gaps |
| 97 | |
| 98 | Anything that didn't translate cleanly (volume ramps dropped, custom presentations approximated, fonts substituted) gets a `TRANSLATION_NOTES.md` written next to the HF output. See [`references/limitations.md`](references/limitations.md) for the format. |
| 99 | |
| 100 | ## What this skill explicitly does NOT do |
| 101 | |
| 102 | - **Translate React state machines.** Compositions that drive animation via `useState` + `useEffect` are not deterministic frame-capture targets in HyperFrames' seek-driven model. Recommend the runtime interop pattern. |
| 103 | - **Run Remotion's render pipeline alongside HyperFrames.** That's the runtime interop pattern from [PR #214](https://github.com/heygen-com/hyperframes/pull/214) — a separate solution for compositions that fail this skill's lint. |
| 104 | |
| 105 | (`@remotion/lambda` is _not_ a blocker — Lambda config is deployment, not animation. The skill drops it as a warning and translates the rest. See [`references/escape-hatch.md`](references/escape-hatch.md).) |
| 106 | |
| 107 | ## How to grade your own translation |
| 108 | |
| 109 | Run the test corpus orchestrator: |
| 110 | |
| 111 | ```bash |
| 112 | ./assets/test-corpus/run.sh |
| 113 | ``` |
| 114 | |
| 115 | It runs T1, T2, T3 (render + diff) and T4 (lint validation), prints a per-tier pass/fail table, and emits an aggregate JSON report. Use this to verify the skill is working end-to-end on a clean checkout — and as a regression check after editing any reference. |
| 116 | |
| 117 | Validated baseline (as of 2026-04-27): |
| 118 | |
| 119 | | Tier | Composition shape | Mean SSIM | Threshold | |
| 120 | | ---- | ------------------------------------------- | --------- | --------- | |
| 121 | | T1 | single-element fade-in | 0.974 | 0.95 | |
| 122 | | T2 | multi-scene + spring + audio + image | 0.985 | 0.95 | |
| 123 | | T3 | data-driven, custom subcomponents, count-up | 0.953 | 0.90 | |
| 124 | | T4 | escape-hatch (8 lint cases) | 8/8 pass | n/a | |