Skip to content

@remotion/media: _experimentalInitiallyDrawCachedFrame prop#7022

Merged
JonnyBurger merged 3 commits intomainfrom
feat/seamless-video-transition
Apr 8, 2026
Merged

@remotion/media: _experimentalInitiallyDrawCachedFrame prop#7022
JonnyBurger merged 3 commits intomainfrom
feat/seamless-video-transition

Conversation

@JonnyBurger
Copy link
Copy Markdown
Member

@JonnyBurger JonnyBurger commented Apr 8, 2026

When mounting a new video tag, it first draws a frame from another video tag that had the same source and was last unmounted

…s between sliced video segments

When a video tag unmounts and a new one mounts (e.g. in sliced video compositions),
there is a black frame while the new tag initializes and decodes its first frame.

This adds an opt-in `seamlessTransition` prop that caches the last rendered frame
on unmount and draws it immediately on the new canvas before the MediaPlayer initializes.

Made-with: Cursor
@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Apr 8, 2026

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

Project Deployment Actions Updated (UTC)
bugs Ready Ready Preview, Comment Apr 8, 2026 9:14am
remotion Ready Ready Preview, Comment Apr 8, 2026 9:14am

Request Review

@JonnyBurger JonnyBurger changed the title @remotion/media: Add seamlessTransition prop to avoid black frames between sliced video segments @remotion/media: _experimentalInitiallyDrawCachedFrame prop Apr 8, 2026
@JonnyBurger JonnyBurger marked this pull request as ready for review April 8, 2026 09:35
@pullfrog
Copy link
Copy Markdown
Contributor

pullfrog bot commented Apr 8, 2026

Reviewed PR #7022. The PR was already merged, so posted a comment with two non-blocking observations: (1) the canvas width/height guard in video-iterator-manager.ts is a subtle but critical coupling to the caching feature and deserves a code comment, and (2) the video-frame-cache.ts map grows without bound, which is fine while _experimental but should be addressed before graduation.

Task list (4/4 completed)
  • Read the full diff and understand the feature
  • Read the changed source files in full for context
  • Analyze correctness, edge cases, and potential issues
  • Submit review

Pullfrog  | View workflow run | Triggered by Pullfrog | Using Big Pickle (free) | 𝕏

@JonnyBurger JonnyBurger merged commit 080c57a into main Apr 8, 2026
18 checks passed
@JonnyBurger JonnyBurger deleted the feat/seamless-video-transition branch April 8, 2026 09:35
@pullfrog
Copy link
Copy Markdown
Contributor

pullfrog bot commented Apr 8, 2026

Post-merge review

Clean implementation. The effect ordering is correct — useLayoutEffect for draw/cache runs synchronously before paint, ahead of the useEffect that creates the MediaPlayer. The canvas context attributes ({alpha: true, desynchronized: true}) match between the cached-frame draw and the MediaPlayer constructor, so getContext won't return null due to attribute mismatch.

Two observations:

  1. video-iterator-manager.ts — the width/height guard is load-bearing. Setting canvas.width (even to the same value) clears the canvas bitmap, which would wipe the cached frame drawn by useLayoutEffect before the first real frame arrives. This guard is the reason the cached frame survives until the MediaPlayer draws the real one. Worth adding a brief comment explaining why it exists — without it, the connection to the caching feature is non-obvious and someone could innocently revert to the simpler unconditional assignment.

  2. video-frame-cache.ts — unbounded cache. The Map<string, OffscreenCanvas> grows without bound; each unique src holds a bitmap in memory indefinitely. For the current sliced-video use case (single source, many slices) this is fine, but if users adopt it for compositions with many distinct sources it could leak. Not a concern while _experimental, but worth keeping in mind for graduation — a simple LRU cap or WeakRef-based eviction would address it.

Pullfrog  | View workflow run | Triggered by Pullfrog | Using Big Pickle (free) | 𝕏

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.

1 participant