chore: import upstream snapshot with attribution
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docs / Validate docs (push) Has been cancelled
Sync skills to ClawHub / Publish changed skills (push) Has been cancelled
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docs / Validate docs (push) Has been cancelled
Sync skills to ClawHub / Publish changed skills (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
# Timing translation: interpolate, spring, easing
|
||||
|
||||
The single highest-leverage reference. Easings and timings are what readers
|
||||
notice; getting them wrong costs more SSIM than any other translation choice.
|
||||
Empirically validated against tiers T1–T3.
|
||||
|
||||
## Conversion: frames → seconds
|
||||
|
||||
HF's timeline is in seconds. Remotion is frame-based. Always:
|
||||
|
||||
```
|
||||
time_seconds = frame / fps
|
||||
```
|
||||
|
||||
So at fps=30:
|
||||
|
||||
- frame 15 → 0.5 s
|
||||
- frame 30 → 1.0 s
|
||||
- frame 90 → 3.0 s
|
||||
|
||||
Do this conversion once when translating, not at runtime.
|
||||
|
||||
## interpolate — linear
|
||||
|
||||
```tsx
|
||||
const opacity = interpolate(frame, [0, 30], [0, 1], { extrapolateRight: "clamp" });
|
||||
```
|
||||
|
||||
Translates to:
|
||||
|
||||
```js
|
||||
gsap.to(target, { opacity: 1, duration: 1.0, ease: "none" }, 0);
|
||||
// fromTo if the property starts at 0 and CSS doesn't already set it
|
||||
gsap.fromTo(target, { opacity: 0 }, { opacity: 1, duration: 1.0, ease: "none" }, 0);
|
||||
```
|
||||
|
||||
`ease: "none"` matches Remotion's default linear interpolation. CSS sets the
|
||||
`from` value if your initial state is in CSS; otherwise use `fromTo`.
|
||||
|
||||
`extrapolateLeft`/`extrapolateRight` defaults to `"extend"` in Remotion but
|
||||
`"clamp"` is what the agent will see most often. GSAP doesn't extend — values
|
||||
hold at the start and end of the tween. So for `clamp`, GSAP matches; for
|
||||
`extend`, you'd need to extend the input range manually before emitting.
|
||||
|
||||
## interpolate — multi-segment
|
||||
|
||||
```tsx
|
||||
const opacity = interpolate(frame, [0, 15, 75, 90], [0, 1, 1, 0]);
|
||||
```
|
||||
|
||||
Three keyframed tweens at offsets `[0]/fps`, `[1]/fps`, `[2]/fps`:
|
||||
|
||||
```js
|
||||
const tl = gsap.timeline({ paused: true });
|
||||
tl.to(target, { opacity: 1, duration: 0.5, ease: "none" }, 0);
|
||||
tl.to(target, { opacity: 1, duration: 2.0, ease: "none" }, 0.5);
|
||||
tl.to(target, { opacity: 0, duration: 0.5, ease: "none" }, 2.5);
|
||||
```
|
||||
|
||||
Validated in T1 — mean SSIM 0.974 against Remotion baseline.
|
||||
|
||||
## spring → GSAP back.out
|
||||
|
||||
Remotion's `spring()` is the most lossy translation. The mapping is approximate
|
||||
but close enough that real-world compositions hold ≥ 0.92 SSIM (T2: 0.985, T3: 0.953).
|
||||
|
||||
| Remotion `spring` config | GSAP equivalent | Validated in |
|
||||
| ------------------------------------------------- | ---------------------------------------------------- | -------------------------------- |
|
||||
| `{damping: 12, stiffness: 100, mass: 1}` (snappy) | `back.out(1.4)` over ~0.7 s | T2, T3 (TitleScene) |
|
||||
| `{damping: 14, stiffness: 90, mass: 1}` (calmer) | `back.out(1.2)` over ~0.7 s | T3 (StatCard) |
|
||||
| `{damping: 8, stiffness: 200}` (very bouncy) | `back.out(2.0)` or `elastic.out(1, 0.5)` over ~0.6 s | not validated; budget ~0.05 SSIM |
|
||||
| `{overshootClamping: true}` | `power3.out` over ~0.6 s (no overshoot) | not validated |
|
||||
|
||||
**Rule of thumb**: `back.out(N)` overshoot ratio ≈ `(stiffness / damping^2) * 1.4`. For
|
||||
`damping:12, stiffness:100` that gives `1.4 * 100/144 = 0.97`, which is close to
|
||||
the validated 1.4 (the formula is rough; tune by visual). Default duration is
|
||||
~0.7 s for the typical config.
|
||||
|
||||
When the spring's `delay`/`from`/`to` are non-default, scale the duration
|
||||
proportionally.
|
||||
|
||||
## interpolate with custom easing
|
||||
|
||||
```tsx
|
||||
import { Easing } from "remotion";
|
||||
interpolate(frame, [0, 30], [0, 1], { easing: Easing.out(Easing.cubic) });
|
||||
```
|
||||
|
||||
| Remotion | GSAP |
|
||||
| ---------------------------- | -------------------------------------------------------------------------------------- |
|
||||
| `Easing.in(Easing.linear)` | `ease: "none"` |
|
||||
| `Easing.out(Easing.cubic)` | `ease: "power3.out"` |
|
||||
| `Easing.inOut(Easing.cubic)` | `ease: "power3.inOut"` |
|
||||
| `Easing.out(Easing.poly(N))` | `ease: "power<N>.out"` (N=2 quad, 3 cubic, 4 quart, 5 quint) |
|
||||
| `Easing.bezier(a,b,c,d)` | `CustomEase.create("c", "M0,0 C${a},${b} ${c},${d} 1,1")` (requires CustomEase plugin) |
|
||||
| `Easing.elastic(bounciness)` | `ease: "elastic.out(${bounciness}, 0.3)"` |
|
||||
| `Easing.bounce` | `ease: "bounce.out"` |
|
||||
| `Easing.back(overshoot)` | `ease: "back.out(${overshoot * 1.7})"` (Remotion's overshoot scale differs) |
|
||||
|
||||
## interpolate driving non-numeric properties
|
||||
|
||||
```tsx
|
||||
const color = interpolateColors(frame, [0, 30], ["#ff0000", "#0000ff"]);
|
||||
```
|
||||
|
||||
GSAP does color tweens natively:
|
||||
|
||||
```js
|
||||
gsap.to(target, { color: "#0000ff", duration: 1.0, ease: "none" }, 0);
|
||||
```
|
||||
|
||||
Same for `backgroundColor`, `borderColor`. The `from` value is read from CSS
|
||||
or the inline style.
|
||||
|
||||
## Custom count-up / number tweens
|
||||
|
||||
When Remotion uses a frame-driven number ramp (`Math.round(value * eased)`):
|
||||
|
||||
```tsx
|
||||
const t = interpolate(frame, [0, 45], [0, 1]);
|
||||
const eased = 1 - (1 - t) ** 3; // cubic ease-out
|
||||
const value = Math.round(target * eased);
|
||||
return <div>{value.toLocaleString()}</div>;
|
||||
```
|
||||
|
||||
GSAP equivalent — tween a counter object, write `textContent` on update:
|
||||
|
||||
```js
|
||||
const counter = { v: 0 };
|
||||
tl.to(
|
||||
counter,
|
||||
{
|
||||
v: target,
|
||||
duration: 1.5,
|
||||
ease: "power3.out",
|
||||
onUpdate: () => {
|
||||
el.textContent = Math.round(counter.v).toLocaleString();
|
||||
},
|
||||
},
|
||||
0,
|
||||
);
|
||||
```
|
||||
|
||||
`power3.out` matches `1 - (1-t)^3` exactly. Validated in T3 (mean SSIM 0.953).
|
||||
Per-frame digit mismatches occur on sub-frame timing offsets but final values
|
||||
converge — no SSIM impact above the noise floor.
|
||||
|
||||
## Stagger via per-instance prop
|
||||
|
||||
When custom subcomponents take a `delayInFrames` prop:
|
||||
|
||||
```tsx
|
||||
<StatCard delayInFrames={i * 12} value={...} />
|
||||
```
|
||||
|
||||
Translate to GSAP timeline offsets:
|
||||
|
||||
```js
|
||||
cards.forEach((card, i) => {
|
||||
const start = base + i * (12 / fps); // i * 0.4s at fps=30
|
||||
tl.to(card, { ... }, start);
|
||||
});
|
||||
```
|
||||
|
||||
Validated in T3 — three StatCards staggered at 0.0/0.4/0.8 s.
|
||||
Reference in New Issue
Block a user