Skip to content

@remotion/gif: Integrate effect system with <Gif>#7480

Merged
JonnyBurger merged 5 commits into
mainfrom
gif/effects-7477
May 20, 2026
Merged

@remotion/gif: Integrate effect system with <Gif>#7480
JonnyBurger merged 5 commits into
mainfrom
gif/effects-7477

Conversation

@JonnyBurger
Copy link
Copy Markdown
Member

Summary

  • Adds _experimentalEffects to <Gif> with useMemoizedEffectDefinitions / useMemoizedEffects, and passes effect definitions to <Sequence> for Studio controls.
  • Updates canvas.tsx to run runEffectChain at the GIF's intrinsic pixel dimensions (with delayRender / continueRender), then composites the result onto the layout canvas with the existing fit logic. Short-circuits to the previous draw path when no effects are set.
  • Adds a gif-effects-testbed composition in packages/example (mirrors the Rive effects testbed).

Fixes #7477

Test plan

  • Open Studio → Rive folder → gif-effects-testbed and verify baseline, tint, halftone, blur, wave, and stacked effects render correctly
  • Confirm animated blur radius updates each frame (effect param redraw)
  • Render gif-effects-testbed with npx remotion render and compare output to preview

Made with Cursor

Adds `_experimentalEffects` support, runs the chain at intrinsic GIF dimensions, and adds a Studio testbed composition. Fixes #7477.

Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
bugs Ready Ready Preview, Comment May 20, 2026 2:01pm
remotion Ready Ready Preview, Comment May 20, 2026 2:01pm

Request Review

Copy link
Copy Markdown
Contributor

@pullfrog pullfrog Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

The runEffectChain rejection handler in canvas.tsx re-throws inside .then, surfacing failures only as delayRender timeouts (and as unhandled promise rejections in dev). Worth aligning with the Solid / RemotionRiveCanvas pattern of cancelRender(err) before merge.

TL;DR — Wires @remotion/gif into the canvas effect system: <Gif> accepts _experimentalEffects, threads memoized definitions to <Sequence> for Studio controls, and runs the chain at the GIF's intrinsic pixel dimensions in canvas.tsx before compositing through the existing fit logic. Also adds a gif-effects-testbed composition mirroring RiveEffectsTestbed.

Key changes

  • Effect prop and memoization on <Gif> — adds _experimentalEffects?: EffectsProp, runs useMemoizedEffectDefinitions / useMemoizedEffects, and forwards the definitions to <Sequence> so Studio surfaces effect controls.
  • Two-stage compositing in canvas.tsx — when effects are set, draws the current GIF frame into a frame-sized sourceCanvas, runs runEffectChain into a frame-sized effectOutputCanvas, then composites onto the layout-sized output via calcArgs(fit, ...). The no-effects path short-circuits to the previous single drawImage.
  • delayRender integration — wraps each chain run in a delayRender('Rendering <Gif/> effect chain') handle so rendering blocks on chain completion; cleanup always releases the handle.
  • gif-effects-testbed — new composition in packages/example exercising baseline, tint, halftone, animated blur, animated wave, and a stacked tint+wave+blur chain, registered under the existing Rive folder in Root.tsx.

Summary | 6 files | 1 commit | base: maingif/effects-7477


Effect chain error path swallows failures

Before: runEffectChain rejections in <Solid> / <RemotionRiveCanvas> route through cancelRender(err) / setError, surfacing the original error to React/the renderer.
After: In <Gif>'s canvas.tsx, the .catch handler re-throws inside .then, producing an unhandled promise rejection and leaving the delayRender handle to be released only by effect cleanup.

Practically this means that on a real chain failure (e.g. WebGL context lost, shader compile failure), the renderer will hang the frame until the delayRender timeout fires with a generic timeout message rather than the underlying error. The fix is to destructure cancelRender from useDelayRender() and call cancelRender(err) in the .catch, mirroring packages/core/src/effects/Solid.tsx.

packages/gif/src/canvas.tsx


Effects run at GIF intrinsic resolution

Before: The single drawImage already used calcArgs(fit, imageData, {width: size.width, height: size.height}), compositing at element size in one step.
After: When effects are present, the chain runs at frameSize (the decoded GIF pixel dims) and the result is upscaled to layoutSize via calcArgs. The no-effects branch is preserved unchanged in behavior aside from now preferring the explicit width/height props over useElementSize for the layout size (a consistency fix with the canvas drawing buffer).

This is a sensible tradeoff — effects on a 480×270 GIF stay cheap regardless of composition resolution — but it does mean spatially-scaled effects (wave amplitude, halftone dotSize, blur radius) are expressed in source pixels and will be magnified by the fit upscale. Worth a brief note in the eventual docs page.

packages/gif/src/canvas.tsx · packages/example/src/Gif/GifEffects.tsx

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Claude Opus𝕏

Comment thread packages/gif/src/canvas.tsx
Comment thread packages/gif/src/canvas.tsx Outdated
Move Rive, Gif, AnimatedImage, and video effect compositions out of unrelated folders into a dedicated Effects folder.

Co-authored-by: Cursor <cursoragent@cursor.com>
Omit `_experimentalEffects` from inherited `SequenceProps` before re-adding it as `EffectsProp`, avoiding an intersection with `EffectDefinition[]` that broke effect factories in the example package.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Fixes react-hooks/exhaustive-deps lint failure in CI.

Co-authored-by: Cursor <cursoragent@cursor.com>
@JonnyBurger JonnyBurger merged commit e6957c1 into main May 20, 2026
16 checks passed
@JonnyBurger JonnyBurger deleted the gif/effects-7477 branch May 20, 2026 14:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Integrate effect system with <Gif> (@remotion/gif)

1 participant