Skip to main content


Also available as a 6min video
Avoid this common mistake in Remotion

If your video flickers or suffers from choppiness during rendering, it is an indication that:

there is a multi-threading issue or
the renderer does not wait for data or assets to be loaded.

Multi-threading issue

The rendering process of Remotion works as follows:

We open multiple tabs to render the video to speed up the process dramatically.
Tabs don't share state and animations that run independent of useCurrentFrame() will break.


Code your video in a way that animations run purely off the value of useCurrentFrame().
Think of your component as a function that transforms a frame number into an image.

Does your component satisfy the following criteria?

A component should always display the same visual when called multiple times.
A component should not rely on frames being rendered in order.
A component should not animate when the video is paused.
A component should not rely on randomness - Exception: random()

Bypass multithreading

If your animation will not break if the frames are rendered in order, users often use the --concurrency=1 flag. This will fix flickering / choppiness in many cases and is a viable path if the effort of refactoring is too big.

The drawback of this technique is that it is way slower and that the correct timing of the animations is still not guaranteed. It will also block rendering via Remotion Lambda.

Asset loading issue

Remotion needs to know that an asset is not loaded yet so it can block rendering.
Otherwise, it will take a screenshot of a loading state.


Use the <Img>, <Video>, <OffthreadVideo>, <Audio>, <Iframe> and <Gif> as they wait for the assets to be loaded.
When loading data, use the delayRender() function.
Ensure you correctly wait for fonts to load.
Only call fitText(), fillTextBox() and measureText() once fonts are loaded.
Avoid using the background-image and mask-image CSS properties.

Flickering <Video> tag

Adding many <Video> tags can lead to stutters.
If you are experiencing the problem, consider using the <OffthreadVideo> component for frame-perfect rendering.


See the list of third-party integrations to see if there is a solution for synchronizing your animation with useCurrentFrame().

Why Remotion works this way

  • Rendering speed is important, especially with server-side rendering.
    Rendering each frame sequentially would be detrimental for speed, a sacrifice that is not worth it when it's possible to write concurrency-safe videos.

  • Setting --concurrency=1 on a video that would be choppy otherwise does not fully fix the problem.
    Often the result looks okay only because of coincidence, because the rendering speed is approximately the same as the animation speed. There is no real timing synchronization and results will differ across machines.

  • Deterministic videos enable distributed video renders like Remotion Lambda, which can render a video much faster than real-time.

See Also