Skill Tracer
Skills › HyperFrames › remotion-to-hyperframes › limitations.md

limitations.md

136 lines · skills/remotion-to-hyperframes/references/limitations.md at a595755

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# Translation limitations
2
3What the skill explicitly cannot translate, separated from the
4blocker-list (which is enforced by `lint_source.py`). These are
5_known_ gaps — surface them to the user as translation notes
6when translating the surrounding composition.
7

Translation limitations

What the skill explicitly cannot translate, separated from the blocker-list (which is enforced by lint_source.py). These are known gaps — surface them to the user as translation notes when translating the surrounding composition.

Raw lines 1 to 7
8## React patterns the skill refuses
9
10See [escape-hatch.md](escape-hatch.md). Any of these triggers
11a bow-out:
13- `useState`, `useReducer` driving animation
14- `useEffect` / `useLayoutEffect` with non-empty deps (side effects)
15- async `calculateMetadata`
16- Third-party React UI libraries (MUI, Chakra, Mantine, antd, shadcn, Radix, NextUI)
18`@remotion/lambda` is no longer in this list — it's a warning, not a
19blocker, because Lambda config is orthogonal to composition rendering.
20The skill drops the imports and `renderMediaOnLambda(...)` calls and
21writes a `TRANSLATION_NOTES.md` entry. See
22[escape-hatch.md](escape-hatch.md).

React patterns the skill refuses

See escape-hatch.md. Any of these triggers a bow-out:

  • useState, useReducer driving animation
  • useEffect / useLayoutEffect with non-empty deps (side effects)
  • async calculateMetadata
  • Third-party React UI libraries (MUI, Chakra, Mantine, antd, shadcn, Radix, NextUI)

@remotion/lambda is no longer in this list — it's a warning, not a blocker, because Lambda config is orthogonal to composition rendering. The skill drops the imports and renderMediaOnLambda(...) calls and writes a TRANSLATION_NOTES.md entry. See escape-hatch.md.

Raw lines 8 to 23
24## Patterns that work with caveats

Patterns that work with caveats

Raw lines 24 to 25
26### Volume ramps on `<Audio>`
28Remotion accepts a function for `volume`:
30```tsx
31<Audio src={...} volume={(f) => interpolate(f, [0, 30], [0, 1])} />
32```
34HF ramps volume with a `data-automation` volume lane on the `<audio>`
35(form in `/media-use` → `references/mixing.md`).
36Translation: write the lane from the `interpolate` points, OR bake the ramp
37into the audio file with `ffmpeg afade`. The dropped-ramp path produces audibly different
38output but visually-identical video, so SSIM passes — just flag it.

Volume ramps on <Audio>

Remotion accepts a function for volume:

<Audio src={...} volume={(f) => interpolate(f, [0, 30], [0, 1])} />

HF ramps volume with a data-automation volume lane on the <audio> (form in /media-use → references/mixing.md). Translation: write the lane from the interpolate points, OR bake the ramp into the audio file with ffmpeg afade. The dropped-ramp path produces audibly different output but visually-identical video, so SSIM passes — just flag it.

Raw lines 26 to 39
Names a skill media-use :35
40### `<Loop>` with stateful children
42```tsx
43<Loop durationInFrames={30}>
44 <CounterThatIncrementsViaUseRef />
45</Loop>
46```
48A bounded GSAP repeat can reproduce _visual_ repetition when its finite count is derived
49from the visible duration. If the looped child has cross-iteration state (a counter, a
50randomness seed), HF won't reproduce it identically per iteration. Bow out unless the child
51is fully deterministic per-iteration; use `repeat: -1` only when the root declares a finite `data-duration`.

<Loop> with stateful children

<Loop durationInFrames={30}>
  <CounterThatIncrementsViaUseRef />
</Loop>

A bounded GSAP repeat can reproduce visual repetition when its finite count is derived from the visible duration. If the looped child has cross-iteration state (a counter, a randomness seed), HF won't reproduce it identically per iteration. Bow out unless the child is fully deterministic per-iteration; use repeat: -1 only when the root declares a finite data-duration.

Raw lines 40 to 52
53### Remotion's `<Img>` with crossOrigin
55```tsx
56<Img src="https://other-domain.com/x.png" crossOrigin="anonymous" />
57```
59HF's renderer doesn't enforce CORS the same way Remotion does. Most
60public images work; private images served with auth headers won't.
61If the source uses `crossOrigin="use-credentials"`, the asset needs
62to be downloaded and inlined at translation time.

Remotion's <Img> with crossOrigin

<Img src="https://other-domain.com/x.png" crossOrigin="anonymous" />

HF's renderer doesn't enforce CORS the same way Remotion does. Most public images work; private images served with auth headers won't. If the source uses crossOrigin="use-credentials", the asset needs to be downloaded and inlined at translation time.

Raw lines 53 to 63
64### Custom `presentation` in `<TransitionSeries>`
66```tsx
67const customPresentation: PresentationComponent = ({ children, presentationProgress }) => {
68 return <div style={{ filter: `blur(${(1 - presentationProgress) * 20}px)` }}>{children}</div>;
69};
70```
72Pure presentations (transform/filter/opacity computed from progress)
73translate to GSAP tweens cleanly. Presentations that read
74`useCurrentFrame()` internally or have stateful children don't —
75bow out.

Custom presentation in <TransitionSeries>

const customPresentation: PresentationComponent = ({ children, presentationProgress }) => {
  return <div style={{ filter: `blur(${(1 - presentationProgress) * 20}px)` }}>{children}</div>;
};

Pure presentations (transform/filter/opacity computed from progress) translate to GSAP tweens cleanly. Presentations that read useCurrentFrame() internally or have stateful children don't — bow out.

Raw lines 64 to 76
77### Code-split components (`React.lazy`)
79```tsx
80const HeavyChart = React.lazy(() => import("./HeavyChart"));
81```
83`React.lazy` is async and doesn't fit the deterministic-render model.
84Translate to a regular import; the resulting HF composition will
85just include all the code upfront.

Code-split components (React.lazy)

const HeavyChart = React.lazy(() => import("./HeavyChart"));

React.lazy is async and doesn't fit the deterministic-render model. Translate to a regular import; the resulting HF composition will just include all the code upfront.

Raw lines 77 to 86
87## Patterns that always work
89- `<AbsoluteFill>` and `<Sequence>` (any nesting)
90- `useCurrentFrame()` derivations: `interpolate`, `spring`, `Easing`,
91 `interpolateColors`, manual math
92- `<Audio>`, `<Video>`, `<Img>`, `<IFrame>` with simple props
93- `staticFile()` references
94- Custom React subcomponents that are pure functions of props
95- Custom hooks that are pure derivations of `useCurrentFrame`
96- `@remotion/lottie` (translates to HF's Lottie adapter)
97- `@remotion/google-fonts/<Family>` (translates to `<link>` or `@font-face`)
98- Sync `calculateMetadata` (resolved at translation time)
99- `<TransitionSeries>` with built-in presentations (`fade`, `slide`,
100 `wipe`, `clockWipe`, `flip`, `iris`)

Patterns that always work

  • <AbsoluteFill> and <Sequence> (any nesting)
  • useCurrentFrame() derivations: interpolate, spring, Easing, interpolateColors, manual math
  • <Audio>, <Video>, <Img>, <IFrame> with simple props
  • staticFile() references
  • Custom React subcomponents that are pure functions of props
  • Custom hooks that are pure derivations of useCurrentFrame
  • @remotion/lottie (translates to HF's Lottie adapter)
  • @remotion/google-fonts/<Family> (translates to <link> or @font-face)
  • Sync calculateMetadata (resolved at translation time)
  • <TransitionSeries> with built-in presentations (fade, slide, wipe, clockWipe, flip, iris)
Raw lines 87 to 101
102## What the skill never tries to translate
104These are out-of-scope by design:
106- **HDR rendering** — HF supports HDR but Remotion doesn't, so there's
107 nothing to translate from.
108- **Variable frame rate** — both tools assume constant fps.
109- **Multi-composition `<Composition>` lists** — translate one at a
110 time. The skill prompts the user to choose which composition.
111- **Remotion Studio props panel** — visual prop editing in HF Studio
112 needs different infrastructure; out of scope.

What the skill never tries to translate

These are out-of-scope by design:

  • HDR rendering — HF supports HDR but Remotion doesn't, so there's nothing to translate from.
  • Variable frame rate — both tools assume constant fps.
  • **Multi-composition <Composition> lists** — translate one at a time. The skill prompts the user to choose which composition.
  • Remotion Studio props panel — visual prop editing in HF Studio needs different infrastructure; out of scope.
Raw lines 102 to 113
114## Reporting gaps to the user
116When translation produces _something_ but the something has gaps, write
117a `TRANSLATION_NOTES.md` next to the output:
119```markdown
120# Translation notes
122The following Remotion patterns were translated with caveats:
124- `<Audio volume={(f) => ...}>` (line 15): volume ramp written as a
125 `data-automation` volume lane (see the media-use skill's mixing reference); the
126 ffmpeg `afade` bake-in is the alternative.
127- `<HeavyChart>` (line 30): translated as inline HTML. The original
128 React.lazy boundary was dropped — bundle size unchanged because HF
129 serves a single HTML file.
131If any of these caveats matter, consider the runtime interop pattern
132instead.
133```
135This file is also generated by the skill alongside the HF output, not
136held in the corpus.

Reporting gaps to the user

When translation produces something but the something has gaps, write a TRANSLATION_NOTES.md next to the output:

# Translation notes

The following Remotion patterns were translated with caveats:

- `<Audio volume={(f) => ...}>` (line 15): volume ramp written as a
  `data-automation` volume lane (see the media-use skill's mixing reference); the
  ffmpeg `afade` bake-in is the alternative.
- `<HeavyChart>` (line 30): translated as inline HTML. The original
  React.lazy boundary was dropped — bundle size unchanged because HF
  serves a single HTML file.

If any of these caveats matter, consider the runtime interop pattern
instead.

This file is also generated by the skill alongside the HF output, not held in the corpus.

Raw lines 114 to 136
Names a skill media-use :125