Skip to main content

· 5 min read
Jonny Burger

With Remotion v4.0.130, Remotion Lambda renders now complete significantly faster!
The longer the video, the higher the speedup.

28.3s64.8s264.2s31.8s134.7s582.6s1 Minute video1 Minute video10 Minute video40 Minute videov4.0.129v4.0.126v4.0.129v4.0.129v4.0.126v4.0.126
Rendering a 1920x1080px video with an <OffthreadVideo> tag loading a 15MB Full HD video and looping it. The Lambda function has been given 3000MB of memory.

Thanks to an innovative audio concatenation strategy that we implemented with help from Max Schnur from Wistia, we can skip an audio re-encoding step at the end.

Audio is the slow part

Remotion Lambda renders portions of a video in parallel and concatenates them at the end.
The slow part is actually not the video, but the audio rendering!

While other codecs are possible, a .mp4 file usually contains AAC audio.

Concatenating the AAC chunks is usually not possible without creating some artifacts.

How AAC works

An AAC audio stream contains many packets. Each packet contains exactly 1024 samples.

0102420483072409651206144716881929216102401126412288

The duration of the audio must be divisible by 1024 samples. If your audio does not fit, you must pad the last packet with silence!

0102420483072409651206144716881929216102401126412288

When concatenating AAC audio, this padding of silence is noticeable and can be heard as a popping noise:



To avoid this artifact, the whole audio needs to be re-encoded at the end. The longer the audio, the worse the problem!

A packet has dependencies

Making the problem harder, an AAC packet is not self-contained. The waveform also depends on the previous and next packets!

0102420483072409651206144716881929216102401126412288

This means we cannot create packet-sized audio slices and concatenate them because we'd have to include their padding as well.

Who can solve this problem?

Online resources such as Stack Overflow were quickly exhausted.

I went to the RTC.on multimedia conference and talked about this problem in my talk.

A few listeners came up to me afterwards and gave me a few ideas. I did a session with Michał Śledź from Software Mansion, all of which helped me even understand the problem we are facing in the first place.

No immediate solution was found, but the problem was put aside when we realized that the libfdk-aac encoder is twice as fast as FFmpeg's native encoder, softened the problem for the moment.

An innovative way to concatenate AAC

Out of the blue, Max Schnur from Wistia appeared with a solution and posted it on the Remotion Discord!

To seamlessly concatenate AAC:

  • Each audio segment needs to have a sample count divisible by 1024
  • Each segment should have extra packets at the beginning and the end to not lose the keyframes.
  • The extra padding will be removed when concatenating them together.
010242048307240965120614471688192921610240112641228801024204830724096512061447168819292161024011264122880102420483072409651206144716881929216102401126412288

There are many tricky aspects to implementing this correctly:

  • Each audio segment needs to be a bit longer than previously and they need to be slightly overlapping. Extra frames need to be evaluated, but they don't need to be screenshotted.
  • Video chunks should not contain the padding, hence audio and video need to be separated.
  • Depending on the rounding and the position in the audio, between 1 and 3 extra packets are required.
  • The inpoint and outpoint FFmpeg filters need to be nano-second precise for correct trimming.
  • All audio layers should be resampled to be the same sample rate (we decided for 48000 Hz)
  • Our timeline positioning, volume curves, pitch correction, playback rate capabilities need to continue working.
  • Rendering only a portion of the timeline will shift the start timestamp, which changes the math for each chunk.
  • The video frame rate of (commonly 30fps) and the audio sample rate of (commonly 48000Hz) do seldomly align. By capturing extra frames, we get too much padding which needs to be trimmed off again for each chunk.
  • The FFmpeg atempo filter is imprecise: For example, speeding up 80.000 audio samples by 2x will lead to 40.014 audio samples. Tiny imperfections will lead to seamless concatenation not working at all. To fix this, we had to flip the order of trimming and speeding up audio.
  • Not pictured above, each AAC file has a silence of 512 samples at the beginning of the file. This delays all audio slightly, but by adding a negative offset to the MP4 container, this is usually balanced out.

If all of these factors are accounted for, concatenating AAC chunks will be completely seamless!

0102420483072409651206144716881929216102401126412288

Upgrade to Remotion 4.0.130 or later to benefit from the faster rendering on Lambda.
We look forward to engineer even more performance improvements in the future for lower costs and better user experience!

· 3 min read
Jonny Burger

We now make it possible to export the Remotion Studio as a static website and deploy it to any hosting provider.

You can share the resulting URLs with your team, clients or friends. They can preview the video, and change the parameters to customize the video.

You can also pass the URL to any Remotion rendering API, such as npx remotion render and renderMedia(), without having to clone the code.

watercolor-map.vercel.app (Template)

Deploy as a static website

Use npx remotion bundle to export the Remotion Studio as a static website. Enter this build command on Vercel, Netlify or another provider to continuously deploy the Studio.

Deploy a template to Vercel in 15 seconds

Render from a URL

You may use the URL to render:

bash
npx remotion render https://watercolor-map.vercel.app
bash
npx remotion render https://watercolor-map.vercel.app

You can use --props to parameterize the video.

All render APIs support this: renderMedia(), renderStill(), getCompositions(), renderMediaOnLambda(), renderFrames(), renderStillOnLambda(), getCompositionsOnLambda(), renderMediaOnCloudRun(), renderStillOnCloudRun(), npx remotion render, npx remotion still, npx remotion compositions, npx remotion lambda render, npx remotion lambda still, npx remotion lambda compositions, npx remotion cloudrun render and npx remotion cloudrun still.

Explore code visually

Sequences are mapped back to the original source code. Click on them in the deployed Studio to jump to the source code on GitHub.com!

watercolor-map.vercel.app (Template)

Deployed templates

Our templates and examples are deployed as a Studio:

Deployed examples

Deploy the Studio to a server

You may also deploy the Remotion Studio as a long-running server, for example on Fly.io or Render.com.
The advantage is that the Render Button stays active, meaning you can render and download videos!

Read here how to deploy the Remotion Studio to a server.

· 6 min read
Jonny Burger

Welcome to the biggest Remotion update ever!
With Remotion 4.0, we offer significant improvements to every workflow.



Discover the new features of Remotion 4.0 in a new video every day.

Introducing the Remotion Studio

We added handy features to the Remotion Preview - as a result, it's more than just a preview! Therefore, we renamed it: Say hello to the Remotion Studio.

Interactive editing of props

The props of a composition can now be defined as a Zod schema.
Doing this will not only make your defaultProps typesafe, but also allow you to edit them in the Remotion Studio.

Edit numbers, strings, arrays, objects, enums and dates directly using a graphical interface. Even nested data structures can be visualized and edited.

Once you are happy with the changes you've made, you can even save the props back to your project. This works with arbitrary JSON data.

Read more: Visual editing

Render Button

Instead of typing in a CLI command, you can now simply press a button to render an asset.

A graphical interface allows you to discover and tweak all options of a render. You can follow the progress of a render in the Remotion Studio, queue multiple renders, and reveal the output in the file explorer.

Every render triggered through the UI is also trackable in the CLI as usual and synchronizes to other instances of the Remotion Studio.
Failed renders show the stack trace and allow for retries with the same configuration.

Edited props in the Remotion Studio can be used to render a video using the Render Button as well - which means you can now render a parameterized video by filling out a form and not having to touch any code.

Learn more on July 5th: Render Button

Rust-powered architecture

Remotion 4.0 ships with a Rust binary that speeds up current and future features.

FFmpeg is baked in

Installing FFmpeg is now superfluous, as each Remotion project comes with a tiny version of FFmpeg baked into it.

We eliminate the our burden of having to support multiple versions of FFmpeg, and you don't have to worry about installing it anymore.

We ship a custom build of FFmpeg 6.0, which is much smaller than a version that you would download. On Lambda, it decreases the cold start time of your functions.

We also get access to the low-level C API that allows us to do things that were not possible before.

Faster <OffthreadVideo>

The <OffthreadVideo> component is the preferred way to embed an existing video into a Remotion project.

While previously, frames were extracted using the FFmpeg CLI, we now use the FFmpeg C API to extract frames. Because we can keep the video open between extractions, this is much faster than before

Unnecessary redundant decoding work can now be skipped, which makes the component up to twice as fast during rendering!

Support for WebP and PDF generation

Previously you could generate PNGs and JPEGs using Remotion - now we support WebP and PDF as well!

There are plenty of ways you can render stills: the new Render button, the npx remotion still command, the renderStill() Node.JS API, render on Lambda with renderStillOnLambda() or on Google Cloud Run using renderStillOnCloudrun()!

Easier data-driven videos

We are introducing a new calculateMetadata() API for the <Composition> component. It helps if you want to:

1
Adjust the duration or resolution based on the props of the React component
2
Perform data fetching before the video renders
3
Precalculate props before mounting the React component

To demonstrate the possibilities of the new API, we made a new section in the docs entirely dedicated to data-driven videos. See: Parameterized rendering.

Upgraded templates

All of our templates have been upgraded to use Remotion 4.0. Many of them make use of the new features, for example the popular Text-to-speech template allows you to customize the text and voice, and the template will automatically adjust the duration of the video to match.

We also introduce two new templates: Text-to-speech (Google) which is an alternative to the Azure TTS template, as well as [https://www.remotion.dev/templates/stargazer] which is a popular template for celebrating GitHub star milestones and can now be initialized using npm init video.

More features

These features added inbetween v3.3 and v4.0 are worth highlighting:

@remotion/rive package

Rive is a faster and smaller alternative to Lottie.
With the new @remotion/rive package, you can include Rive animations in your project.

@remotion/shapes package

@remotion/shapes is a handy package for including geometric shapes like <Triangle>, <Star> or <Pie> in your components!

Those components are easy to animate, pure, dependency-free and work well with @remotion/paths.

Each shape can be used as a React component <Star> or as a pure function that returns an SVG path makeStar().

@remotion/tailwind package

The new Tailwind package allows you to install Tailwind more easily in any Remotion project.

Finetuned Audio codec

Instead of the audio codec being tied to the video codec, you can now choose the audio codec independently.

Lambda improvements

Player improvements

ES Module support

All APIs that can be imported in the browser now have an ES Module version.

Font Picker

In your apps, you can now display a font picker and load fonts dynamically only when they are needed.

New Core APIs

The remotion package has had the following improvements:

Join the Cloud Run Alpha

As a counterpart for Lambda, we are developing a Google Cloud Run package.
The alpha is now available, help us test it by becoming an early adopter.

Full Changelog

See the GitHub release to see the full changelog.

Breaking changes

See the Migration Guide for a full list of breaking changes.

· 12 min read
Jonny Burger

No more FFmpeg installation!

Now, when you are rendering a video and don't have FFmpeg installed, Remotion will download a copy for you. Previously, installing FFmpeg required 7 steps on Windows and took several minutes when using Homebrew on macOS.

When deploying Remotion on a server, you can now also let Remotion install FFmpeg for you using the ensureFfmpeg() API or the npx remotion install ffmpeg command. Learn more about FFmpeg auto-install here.

New @remotion/google-fonts package

It is now easy to import Google Fonts into Remotion! @remotion/google-fonts takes care of correct loading, and is fully type-safe!

New @remotion/motion-blur package

This package contains two components: <Trail> and <CameraMotionBlur>, assisting you with achieving awesome motion blur effects!

A quick demo of what is now called <Trail>:

New @remotion/noise package

This package offers easy, type-safe, pure functions for getting creative with noise. Check out our playground to see what you can do with it!

A video demo of how you can create interesting effects with noise:

New @remotion/paths package

This package offers utilities for animating and manipulating SVG paths! With 9 pure, type-safe functions, we cover many common needs while working with SVG paths:

Quick Switcher

By pressing Cmd+K, you can trigger a new Quick Switcher. It has three functions:

  • Fuzzy-search for a composition to jump to that composition.
  • Type > followed by an item in the menu bar to trigger that action.
  • Type ? followed by a search term to query the docs.

Remotion Core

<Sequence> makes from optional, accepts style and ref

<Sequence from={0}> can now be shortened to <Sequence>. Our ESLint plugin was updated to suggest this refactor automatically.

You can now also style a sequence if you did not pass layout="none".

A ref can be attached to <Sequence> and <AbsoluteFill>.

Video and Audio support loop prop

The <Video> and <Audio> components now support the loop property.

Preview

New CLI output

When starting the Remotion Preview, it now shows on which URL the preview is running. The Webpack output is now also cleaner.

Pinch to Zoom

If your device supports multitouch, you can now pinch to zoom the composition. Alternatively, you can hold Ctrl/Cmd and use your scrollwheel to zoom.

Using two fingers, you can move the canvas around and pressing 0 will reset the canvas. For the latter, there is also a button in the top-right corner that you can click.

Search the docs from the Remotion Preview

Pressing ? to reveal the keyboard shortcuts now has a secondary function: You can type in any term to search the Remotion documentation!

Shorter commands

Previously, a Remotion CLI command looked like this:

bash
npx remotion render src/index.tsx my-comp output.mp4
bash
npx remotion render src/index.tsx my-comp output.mp4

We now allow you to skip the output name, in this case the render would land in out/my-comp.mp4 by default:

bash
npx remotion render src/index.tsx my-comp
bash
npx remotion render src/index.tsx my-comp

You can also omit the composition name and Remotion will ask which composition to render:

bash
npx remotion render src/index.tsx
bash
npx remotion render src/index.tsx
note

Experimental: We might change the behavior to rendering all compositions in the future.

Finally, you can also omit the entry point and Remotion will take an educated guess!

bash
npx remotion render
bash
npx remotion render

If you deviate from the defaults of our templates, you can set an entry point in your config file and leave it out from Remotion commands.

Auto-reload environment variables

If you change values in your .env file, the Remotion Preview will reload and pick them up without having to restart.

Signal that Remotion Preview disconnected

When quitting the Remotion Preview using Ctrl+C, for example to render a video, A new popup will signalize that Fast Refresh will not work anymore.

Rendering

--muted render

This new flag can be passed to a render to ignore the audio. If you know that your video has no audio, this can make your render faster.

--enforce-audio-track

When no audio was detected in your video, the audio will now be dropped (except on Lambda). With this new flag, you can enforce that a silent audio track is added.

--audio-bitrate and --video-bitrate

These flags allow you to set a target bitrate for audio or video. Those flags are not recommended though, use --crf instead.

--height and --width flags

Using these flags, you can ignore the width and height you have defined for your output, and override it. The difference to --scale is that the viewport and therefore the layout may actually change.

Obtain slowest frames

If you add --log=verbose, the slowest frames are shown in order, so you can optimize them. Slowest frames are also available for renderMedia() using the onSlowestFrames callback.

Negative numbers when rendering a still

When rendering a still, you may now pass a negative frame number to refer to frames from the back of the video. -1 is the last frame of a video, -2 the second last, and so on.

Override FFmpeg command

The FFmpeg command that Remotion executes under the hood can now be overriden reducer-style.

Server-side rendering

Resuming renders if they crash

If a render crashes due to being resource-intensive (see: Target closed), Remotion will now retry each failed frame once, to prevent long renders from failing on low-resource machines.

Getting the overall progress from renderMedia()

Previously, the progress for rendering and encoding was reported individually. There is a new field, simply named progress, in the onProgress callback that you can use to display progress without calculating it yourself.

Easier function signature for bundle()

Previously, bundle() accepted three arguments: entryPoint, onProgress and options.

Old bundle() signature
ts
import { bundle } from "@remotion/bundler";
 
bundle("./src/index.ts", (progress) => console.log(progress), {
publicDir: process.cwd() + "/public",
});
Old bundle() signature
ts
import { bundle } from "@remotion/bundler";
 
bundle("./src/index.ts", (progress) => console.log(progress), {
publicDir: process.cwd() + "/public",
});

Since getting the progress was less important than some of the options, bundle() now accepts an object with options, progress callback and entryPoint altogether:

New bundle() signature
ts
import { bundle } from "@remotion/bundler";
 
bundle({
entryPoint: "./src/index.ts",
onProgress: (progress) => console.log(progress),
publicDir: process.cwd() + "/public",
});
New bundle() signature
ts
import { bundle } from "@remotion/bundler";
 
bundle({
entryPoint: "./src/index.ts",
onProgress: (progress) => console.log(progress),
publicDir: process.cwd() + "/public",
});

The previous signature is still supported.

Player

<Thumbnail> component

The new <Thumbnail> component is like the <Player>, but for rendering a preview of a still. You can use it to display a specific frame of a video without having to render it.

tsx
import { Thumbnail } from "@remotion/player";
 
const MyApp: React.FC = () => {
return (
<Thumbnail
component={MyComp}
compositionWidth={1920}
compositionHeight={1080}
frameToDisplay={30}
durationInFrames={120}
fps={30}
style={{
width: 200,
}}
/>
);
};
tsx
import { Thumbnail } from "@remotion/player";
 
const MyApp: React.FC = () => {
return (
<Thumbnail
component={MyComp}
compositionWidth={1920}
compositionHeight={1080}
frameToDisplay={30}
durationInFrames={120}
fps={30}
style={{
width: 200,
}}
/>
);
};

Player frameupdate event

In addition to timeupdate, you can subscribe to frameupdate, which fires whenever the current frame changes. You can use it for example to render a custom frame-accurate time display.

Player volume slider is responsive

If the Player is displayed in a narrow container, the volume control now goes upwards instead of to the right, in order to save some space.

Get the scale of the Player

Using the imperative getScale() method, you can now see how big the displayed size is in comparison to the canvas width of the component.

Controls are initially shown

On YouTube, the video always starts with controls shown and then they fade out after a few seconds. We have made this the default behavior in Remotion as well, because users would often not realize that the Player is interactive otherwise. You can control the behavior using initiallyShowControls.

Play a section of a video

Using the inFrame and outFrame props, you can force the Remotion Player to only play a certain section of a video. The rest of the seek bar will be greyed out.

Customize Play button and Fullscreen button

Using renderPlayPauseButton and renderFullscreenButton, you can customize the appearance of the Player more granularly.

Start player from an offset

You can define the initialFrame on which your component gets mounted on. This will be the default position of the video, however, it will not clamp the playback range like the inFrame prop.

New prefetch() API

In addition to the Preload APIs, prefetch() presents another way of preloading an asset so it is ready to display when it is supposed to appear in the Remotion Player.

Prefetching API
tsx
import { prefetch } from "remotion";
 
const { free, waitUntilDone } = prefetch("https://example.com/video.mp4");
 
waitUntilDone().then(() => {
console.log("Video has finished loading");
free(); // Free up memory
});
Prefetching API
tsx
import { prefetch } from "remotion";
 
const { free, waitUntilDone } = prefetch("https://example.com/video.mp4");
 
waitUntilDone().then(() => {
console.log("Video has finished loading");
free(); // Free up memory
});

Video and audio tags will automatically use the prefetched asset if it is available. See @remotion/preload vs. prefetch() for a comparison.

Remix template

The Remix template is our first SaaS template! It includes the Remotion Preview, the Player and Remotion Lambda out of the box to jumpstart you with everything you need to create your app that offers customized video generation.



Get started by running:
bash
npx create-video --remix
bash
npx create-video --remix

Lambda improvements

Webhook support

You can now send and receive a webhook when a Lambda render is done or has failed. Examples for Next.js and Express apps have been added and our documentation page features a way to send a test webhook.

Payload limit lifted

Previously, the input props passed to a Lambda render could not be bigger than 256KB when serialized. Now, this limit is lifted, since if the payload is big, it will be stored to S3 instead being passed directly to the Lambda function.

Lambda artifact can be saved to another cloud

The output videos generated by Lambda can now be saved to other S3-compatible protocols such as DigitalOcean Spaces or Cloudflare R2.

Deleting a render from Lambda

The new deleteRender() API will delete the output video from the S3 bucket, which you previously had to do through the console or with the AWS SDK.

Make renderMediaOnLambda() params optional

The following options are now optional:

Benchmark command

The new npx remotion benchmark helps you compare different render configurations and find out which one is the fastest. Currently, you can compare different codecs, compositions and concurrency values. Each configuration is run multiple times in order to increase confidence in the results.

New guides

We have added new guides that document interesting workflows for Remotion:

We try to avoid jargon, but we have also created a Remotion Terminology page to define some commonly used terms. When using these terms, we will from now link to the terminology page for you to read about it.

Better structure and naming in templates

The file that was previously called src/Video.tsx in templates is now called src/Root.tsx, because it did not contain a video, but a list of compositions. That component was also renamed from RemotionVideo to RemotionRoot. The new naming makes more sense, because that component is passed into registerRoot().

Notable improvements

Get the duration of a GIF

The new function getGifDurationInSeconds() allows you to get the duration of a GIF.

Lottie animation direction

Using the new direction prop, you can play a Lottie animation backwards.

Lottie embedded images

Should a Lottie animation contain an embedded image, it will now be properly awaited.

Temporary directory Cleanup

The temporary directory that Remotion creates is now completely cleaned up after every render.

Parallel encoding turned off if memory is low

Parallel encoding will not be used when a machine has little free RAM. You can also force-disable it using disallowParallelEncoding.

Thank you

Thank you to these contributors that implemented these awesome features:

  • ayatko for implementing the @remotion/google-fonts package
  • Antoine Caron for implementing the <Thumbnail> component, for reloading the page when the environment variables change and implementing negative frame indices
  • Apoorv Kansal for implementing the documentation search in the Quick Switcher, the benchmark command and the option to customize Play button and fullscreen button in the Player
  • Akshit Tyagi for implementing the --height and --width CLI flags
  • Ilija Boshkov, Marcus Stenbeck and UmungoBongo for implementing the Motion Blur package
  • Ravi Jain for removing the need to pass the entry point to the CLI
  • Dhroov Makwana for writing a tutorial on how to import assets from Spline
  • Stefan Uzunov for implementing a composition selector if no composition is passed
  • Florent Pergoud for implementing the Remix template
  • Derryk Boyd for implementing the loop prop for Video and Audio
  • Paul Kuhle for implementing Lambda Webhooks
  • Dan Manastireau for implementing a warning when using an Intel version of Node.JS under Rosetta
  • Pompette for making the volume slider responsive
  • Logan Arnett for making the composition ID optional in the render command
  • Patric Salvisberg for making the FFmpeg auto-install feature
  • Arthur Denner for implementing the direction property for the Lottie component

Many of these contributions came during Hacktoberfest where we put bounties on GitHub issues. We also want to thank CodeChem for sponsoring a part of those bounties!

· 3 min read
Jonny Burger

We are delighted to announce that we have raised 180'000 Swiss Francs from Remotion users and customers!

With our first funding, we will make it easier for you to programmatically create videos and video apps. We'll introduce new components, templates and tools to help you build more with less code.

Our investors use Remotion

Our line-up of investors consists of companies and people that use Remotion for fun or to build their businesses.

We are so happy to partner with investors who understand our vision and can help us with relevant connections.

For One Red

Design Studio

Heiko Hubertz

Founder & CEO, Oxolo

Simon Schmid

Product, iubenda

William Candillon

Can it be done in React Native?

Sébastien Lorber

This Week in React, Docusaurus

Nick Dima

Senior Engineering Manager, Musixmatch

Stephen Sullivan

Founder, Middy.com

Dominic Monn

Founder, MentorCruise

Jeremy Toeman

Founder, augxlabs.com

Robbie Zhang-Smitheran

Cameo.com

Ilya Lyamkin

Senior Software Engineer, Spotify

Lucas Pelloni

Co-Founder, Axelra

Michiel Westerbeek

Co-Founder, Tella

David Salib

Co-Founder, Momento

Making Remotion easier for creatives

The number one feedback that we have heard is that being able to write videos in React is powerful, but simple things can be hard. Fortunately, almost any complexity in React can be abstracted, packaged up, released to NPM and shared with others.

While our low-level primitives will always be here, we will also develop higher-level components solving common needs that people face. This will allow more developers, not just React experts, to use Remotion.

We also encourage our community to create building blocks for Remotion and will sponsor developers as well as help them monetize their work.

Enabling new business opportunities

With the Remotion Player and Remotion Lambda, we provide APIs that allow you to build apps that produce videos for end users.

We have tons of opportunities to make it easier to build an app with Remotion. We are going to release UI elements, SaaS templates and even best practices for payment integration, so companies can realize Remotion solutions faster and with fewer resources.

Why did we "only" raise 180‘000 CHF?

We recognize that startups usually raise more money than we do at an earlier stage. At the same time, they are entering a high risk of failure due to running out of money.

With the amount we have raised, we are not only able to continue but accelerate our operation and grow our company license revenue to confidently stay here for a long time.

Remotion is a thriving community of business customers, creative coders, professional Remotion freelancers and indie hackers whose interest is our long-term success. Our aim is to grow in a healthy way together with our community!

Thank you…

To everybody who tried out Remotion, sent a pull request, tweeted about it or filed a bug. It is a huge thrill to see people believe in the ideas that we put out and we are very privileged to able to continue working on them.

· 5 min read
Jonny Burger

Up in this release: More ways to create videos and better workflow!

Lottie support

Announcing the official @remotion/lottie package, including a typesafe component and extensive documentation. With Lottie, you can import thousands of premade animations from LottieFiles and we even made a guide on how to import animations created in After Effects!

Animations from Lottiefiles embedded in Remotion: 1, 2, 3

To get started, install @remotion/lottie into your Remotion project and import the <Lottie> component:

bash
npm i @remotion/lottie
bash
npm i @remotion/lottie

Thanks to Arthur Denner for implementing this feature!

React Native Skia support

Using the @remotion/skia package, you can now use React Native Skia in Remotion! Thanks to our collaborators William Candillon and Christian Falch, Remotion is now a first-class target for React Native Skia.

Check out the epic announcement video, read the docs and make your first video using:

bash
npx create-video --skia
bash
npx create-video --skia

Zoomable timeline

Our timeline has some new features that make it behave more like traditional video editors. You can now zoom in and out of the timeline to better focus on a certain section of a video. When playing the video, the timeline moves along with the cursor. Scrubbing with the cursor or keyboard will also scroll the timeline so the cursor is always in the viewport.

The other new timeline feature is that there are now ticks that appear every second, and when zoomed in, smaller ticks that denote the positions of a single frame. This should help you orient yourself when you are asking yourselves at which point of the video you are at.

Improvements to audio-only and video-only rendering

You can now explicitly drop the audio of a video by passing --muted in the render. Videos that include no audio are now faster because we don't include a silent audio track anymore (use --enforce-audio-track to get the old behavior).

Renders that are audio only are now faster because Remotion will not wait for the video tags to seek.

Renders that are only video are now faster because no assets need to be downloaded to be included in the audio track.

Handy features

  • The back and forwards button now work in the preview.
  • Chrome 104 is now available on Remotion Lambda which means you can use the handy transform shorthands!
  • You can now render ProRes on Remotion Lambda.
  • Remotion Lambda now has a privacy: "no-acl" option if you are rendering into a bucket that has the ACL feature disabled.
  • Remotion Lambda now supports a downloadBehavior prop which makes it that when a output file link gets clicked in the browser, it will download instead of play in the browser.
  • Adding an output filename to the npx remotion render command is not necessary anymore, it will default to out/{composition-id}.{extension} now.
  • The <Player> has a new moveToBeginningWhenEnded prop that determines if the player moves back to the beginning when the video has reached the end and is not looping.
  • The <Player> has a new fullscreenchange event that allows you to
  • You can now assign a className to the <Player>.

Developer experience

  • New ESLint rule that warns you if you are passing a relative path or remote URL to staticFile: staticFile("../my-file.png") or staticFile("https://example.com")
  • Better error message on Remotion Lambda when the s3:ListBucket permission for the bucket you are rendering into is missing.
  • ESLint warning when passing a file ending in .gif to the <Img> component.
  • Better error message and help page when calling renderMediaOnLambda() inside another serverless function and AWS credentials are conflicting
  • Better error message and help page when rendering into a bucket that has ACL disabled but you are setting the privacy to public or private.

Notable bug fixes

  • The <Player> now works correctly in React 18 strict mode.
  • The preview server should not crash anymore in any scenario.
  • Remotion now cleans up any temporarily created files and does not pollute the hard drive.
  • Executing npx remotion commands outside of the project root now works.
  • Open in VS Code now works if the code command is not installed.
  • Remotion Lambda now uses less memory and is less prone to crashing when using <Video>'s.

Internals

  • The CLI configuration code has moved from remotion to @remotion/cli, which makes the remotion package 30% smaller.
  • We moved from jest to vitest for some packages.
  • puppeteer-core and chalk dependencies have been inlined.
  • We adopted Node.JS Corepack.

· 5 min read
Jonny Burger

This release brings support for GIF as an output format, official support for Tailwind and makes springs and sequences easier! Plus we recap the best features from v3.0.1 until v3.0.31! 🎉

Render as GIF

To render a GIF instead of a video, pass the --codec=gif flag during a render. We tweaked Remotion's rendering process to adapt for the speciality that are GIFs:

  • Commonly, a GIF has a framerate in the range of 10-15, and so that you don't have to refactor your video, you can use the --every-nth-frame flag.

  • GIFs are loopable - using the --number-of-gif-loops flag you have control over the GIFs looping behavior!

  • You can even render your GIF distributed across many small VMs using Remotion Lambda!

You can put <Gif>'s in your GIF!

TailwindCSS support

After being broken for a while, TailwindCSS support is now stable, and we even made a starter template for it! To get started, visit our homepage, generate a GitHub repo from a template, try it out online via StackBlitz, or type the following into your terminal:

bash
npx create-video --tailwind
bash
npx create-video --tailwind

Yes, you can write a GIF in Tailwind now.

Springs with durations

You can now do this:

tsx
const fps = 30;
 
const value = spring({
fps,
frame,
config: {
damping: 200,
},
durationInFrames: 300,
});
tsx
const fps = 30;
 
const value = spring({
fps,
frame,
config: {
damping: 200,
},
durationInFrames: 300,
});

The result will be a spring animation that will take 10 seconds!

Why is this such a game changer? Normally, a spring animation curve is not defined by timing, but by physical parameters. It complicates planning quite a bit, as the duration of a spring is not well-defined. Theoretically, a spring animation is never finished, it keeps on going forever (even though after some time the movement is barely noticeable).

We introduced measureSpring() a while ago which allows you to calculate the duration of a spring by allowing you to set a threshold.

But to change the duration of a spring, you had to change the physics parameters which then in turn change the animation curve!

Until now - if you pass a duration to a spring, we will detect the trajectory of the curve and stretch it so it fits your duration.

<OffthreadVideo> component

This component is an alternative to the <Video> component that extracts frames using FFMPEG and renders them inside an <Img> tag.

We made the <OffthreadVideo> component in order to counteract problems with seeking and throttling that users were reporting with the <Video> tag. The new way improves reliability but has it's tradeoffs - read <OffthreadVideo> vs <Video> or check out our visual explanation on Instagram!

Follow us on Instagram where we explain concepts visually!

renderMedia() returns a buffer

Previously you could only save your video to a file when using the renderMedia() and stitchFramesToVideo() APIs. Now it can also return a Node.JS Buffer!

@remotion/preload package

This new package offers three APIs that are handy for preloading assets before they appear in the <Player>: resolveRedirect(), preloadAudio() and preloadVideo().

We first announce and explain new features on Twitter!

If your screen real estate is tight, you may also hide the left sidebar now!

Built-in color picker

In the preview, go to Tools -> Color picker to trigger an eye dropper that allows you to pick any color from the screen! Only Chrome has this feature enabled for now.

For power users

  • Previously you could not wrap your <Composition>'s in a React context (e.g. Redux), but this is supported now!
  • If you add --log=verbose to a Lambda render, you'll see which frames took the longest to render.
  • If you provide a file for --props during the preview, it will now reload the preview if the props have changed.
  • Pressing A in the preview goes to the beginning of the video, pressing E goes to the end.
  • Pressing play in the preview, then pressing Enter pauses the video and goes back to the point where the video started playing.
  • <Sequence>'s can now have a style prop if the layout="none" is not set!
  • You can customize the binaries for Remotion Lambda renders, for example to switch out the Emoji font used.
  • The registerRoot() call can now be deferred using delayRender(), so asynchronous loading tasks can be completed first.

Behind the scenes

We welcome Patric as our intern! As you can see on our new team page, we are now a team of three and are in the preparations of our first fundraising round.

Patric's first Remotion video!

Remotion won the "Most Exciting use of Technology Award" at React Summit - we owe it all to you!

Going forward, we want to make Remotion even easier to use through new tools, templates and tips!

And wouldn't it be nice if Remotion was faster - I'm exploring multiple options from an alternative concurrency model to a C++ based rendering solution - stay tuned for what's about to come 🚀

· 5 min read
Jonny Burger

After more than 10 months in development and 1400 commits, it feels so good to announce Remotion 3.0!

I am convinced that Remotion Lambda is the best piece of software that I have ever written. It is the final puzzle piece needed to complete our vision: A full stack for developing video apps! Enjoy the changelog, and if you haven't, check out the Remotion 3.0 Trailer.

Announcing Remotion Lambda

Remotion Lambda is a distributed video renderer based on AWS Lambda. It is made for self-hosting, so you deploy it to your AWS account. Once your Lambda function is up, you can give it rendering tasks, which it will split up into many small units of work that get processed in parallel by spawning itself many times.

Lambda is the best of all worlds:

  • Fast: Lambda can render a video up to many times faster than the fastest consumer computers. The longer the video, the higher the speed gain. The Remotion Lambda trailer was rendered in 15 seconds instead of 60 seconds, and a 2 hour video was rendered in just 12 minutes[1].

  • Cheap: You only pay for when you are rendering. The Lambda functions use ARM architecture for best price-performance efficiency.

  • Scalable: You can render many multiple videos at the same time. Lambda concurrency limits apply, but can be increased.

  • Easy: Chromium and FFMPEG are already pre-installed, and we handled all the edge cases. You only need to code your video, follow the steps to deploy a function and invoke a render.

All functionality is available via CLI commands and Node.JS functions. We've written 45 pages of documentation, released over 50 alpha versions to testers, and written many tests from unit to end-to-end. Lambda is mature and used in production by companies like Combo and Jupitrr.

Parallel rendering and encoding

Previously, rendering frames, and stitching them together to a video has been a sequential process where one step can start once the other has finished. In Remotion 3.0, stitching can start while rendering is still in progress! This will result on average in a 10-15% speedup.

Additionally, downloading audio assets now happens earlier in the rendering pipeline and if you rely on remote audio, you should see a handsome speedup as well.

New renderMedia() API

A new function has been added to @remotion/renderer called renderMedia(). It combines already existing functions renderFrames() and stitchFramesToVideo() but takes advantage of the new parallel rendering pipeline. It can render videos as well as audio and requires fewer arguments, so it's a win for speed and ease of use!

New openBrowser() API

Since opening and closing a browser instance can take time, we introduce a new API called openBrowser() for opening an instance of Puppeteer that you can use across the SSR APIs: renderMedia(), renderStill(), getCompositions(), and renderFrames().

Better error reporting

We are taking an initiative to make error easier to understand. While much of error handling has been handled by third-party libraries until now, we've inlined the logic, allowing us to streamline it. Minified errors are being symbolicated, we've implemented a new error overlay, and timeout errors are more descriptive. Let us know what you think!

A minified error that happened inside a Chrome browser inside a remote Lambda function displays a proper stacktrace!

Our custom error overlay has the ability to open the troublesome file in your default editor, and look for similar GitHub issues.

Config file can now import other files.

In the remotion.config.ts file, you can now import other files. Under the hood, we use ESBuild instead of Typescript to read the file. This was a paint point before: Node.JS APIs don't read from the config file and require you to specify the options explicitly. Configuration such as a Webpack config override could not be shared in a good way between CLI and Node.JS renders so far, which we address with this change.

React 18 supported

React 18 is now supported and we recommend that you upgrade to it. See our React 18 upgrade guide on how to do it!

Node 14, ESLint 8

Keeping our stack modern allows us to move faster and also, eliminate dependencies.

With Remotion 3.0, support for Node 12 is dropped, and we officially support Node 18. Our ESLint config has been updated to take advantage of ESLint 8, which is now also officially supported.

How to update

Read the migration guide to update to Remotion 3.0. The most severe breaking changes revolve around server-side rendering in an attempt to make it faster and simpler. Other than SSR changes and the Node 14 requirement, nothing should break.


[1] See the trailer repository for instructions on how to reproduce.

[2] Rendering the composition 2hrvideo in the example folder in the Remotion repository with --frames-per-lambda=1080, a Lambda function running on the arm64 architecture with 2048MB RAM, on warm Lambdas in the us-east-1 region.

· 3 min read
Jonny Burger

The biggest announcement of this release is that the @remotion/player package is now generally available - but not just that, we have some other sweet new features too!

<Player/> is now stable



With the <Player/> component, you can embed a Remotion Video inside a React app without rendering the video. The API is modeled after the native HTML <video> tag that many developers are already familiar with.

The API allows you to use our predefined controls, or build your own. Familiar UI patterns like volume slider, fullscreen button, as well as gesture mechanics such as click to play/pause are supported.

You can dynamically update the props of the video at runtime, which creates an experience that stuns user: videos that react to their user input!

On mobile, restrictive policies prevent auto-play of audio content. We help you architect your player so it can play audio in as many cases as possible while still respecting the browser policies. This includes the option to mount silent audio tags, activate them while the user interacts with the page and use them later to play audio.

In this release, we added a new renderLoading prop and wrote docs for how to scale your player, code-sharing between Remotion and Create React App/Next.JS and preloading assets.

See the landing page for @remotion/player
Demo and Documentation

New error overlay

Recently, we broke the error overlay that pops up when your code contains an error. This is now fixed and we went deeper than ever before!



The Fast Refresh and error overlay is now inlined in our codebase and allows for customization that makes sense for Remotion. The overlay now matches the dark theme of the Remotion Preview and includes handy links such as opening a file in the editor, looking for the error in our GitHub issues and our Discord community.

Support for /public folder

You can now put static files inside a /public folder in your Remotion project and load it using the new staticFile() API. If you include the new <Player /> component in a Create React App or Next.JS project, the folder can be shared across Remotion and the framework you are using.

<Audio /> or <Video /> now support data: URLs

Data URLs are now valid sources for <Audio /> and <Video /> tags. This is useful for example for tones that are programmatically generated. To help with development of such projects, a new API was added to the @remotion/media-utils project: audioBufferToDataUrl(). See our festive Tone.js sample project for an example!

New audiogram template

When running npm init video, there's a new template to choose from: "Audiogram"! This one allows you to convert podcast clips to clean visualizations that you can post on social media.

getCompositions() now returns defaultProps

The getCompositions() API has been updated to return a new field for each composition: The defaultProps that you have specified for that composition.

Miscellaneous

  • Fixed videos playing in the <Player /> after they should have ended.
  • Fixed ended event in the <Player /> not firing correctly.
  • Fixed certain vulnerability messages that would show up during installation.
  • Updated @remotion/three to use React Three Fiber v7.

What's next

The next release is finally going to be our new major new release containing a refactor of our rendering pipeline and serverless rendering support. Look out as we release the missing puzzle piece in our vision of programmatic video!

· 6 min read
Jonny Burger

We are excited to announce a packed October release! We did work in many areas and these improvements will surely boost your productivity!

In/Out markers

You may know this feature from programs like After Effects and Davinci Resolve already. It is as simple as it is useful: You can set an “In” mark and an “Out” mark and the preview will only play whatever is in-between those timestamps. This makes it much easier to visually “debug” a section of the video without having to watch the whole thing.

Thanks to Ankesh for implementing this feature!

<Loop> component

Previously, in order to repeat content, you had to manually create a bunch of sequences and calculate the timestamps yourself. We added a helper called <Loop /> which will repeat it’s children either indefinitely or for a fixed number of times. Another benefit is that we display the loop component cleanly in our timeline.

Thanks to Brian Pederson for implementing this feature!

Support for different playback rates

You can now change the playback rate in the editor and play a video in slow-motion, in fast-forward, and even in reverse! We support speeds between -4x and 4x. This makes debugging animations that don’t look clean much easier.

It also works in the <Player />! See the new playbackRate prop and we also added a ratechange event - just like the native HTML5 Video element.

Thanks to Brian Pederson for implementing this feature!

Support for J, K, L keyboard shortcuts

These new shortcuts are super handy for navigating through a timeline. With the L key, you play the video as normal. Pressing the L key again will increase the speed to 2x, and pressing L three times in total will play the video in 4x.

The J key works the same, but plays the video backwards. Now you can reach any point in the video easily with just those two keys, even if the video is playing, without using the mouse.

Once you have reached the point where you want to pause the video and continue to code it, the K key will reset the playback rate to 1x and pause the video.

Once you learn how to navigate using JKL keys, you'll never use your mouse for scrubbing again!

Thanks to Brian Pederson for implementing this feature!

tip

Press the ? button to learn about all keyboard shortcuts!

durationInFrames={Infinity} is now optional

If you wanted to delay an element but not cap it’s duration, you had to explicitly specify durationInFrames={Infinity} . Not anymore! This is now the default and may be omitted. If you upgrade the @remotion/eslint-config package as well, we will even automatically remove the prop when you have autofix enabled!

Thanks to Khalid Ansari for implementing this feature!

Fig autocomplete

In case you don’t know Fig, it is a free macOS application that provides autocomplete for the terminal. What sounds like a gimmick, actually works surprisingly well and I personally would miss it a lot if I didn’t have it! The Remotion CLI that you can invoke using npx remotion now has full autocomplete support in Fig! You have to do nothing except install Fig.

Thanks to Mattèo Gauthier for implementing this feature!

Node.JS 17 support

This version came out recently and broke almost every Webpack project because legacy crypto functions were removed.

We added the necessary modifications to our default Webpack config, and even contributed a pull request to Webpack to fix the last remaining bug that would break Remotion with Node 17! If you are upgrading Node, definitely make sure get this new version of Remotion.

Monorepo migrated to pnpm

Contributors to Remotion would previously often struggle to correctly set up our monorepo. Indeed it was hard to correctly link all the packages and too easy to mess it up and run into error messages.

This is why we are happy to have migrated to pnpm, which gets rid of the linking problems and also speeds up installation significantly. In your CI systems, we saw build times go down by 40%, which allows to iterate much more faster.

Thanks to Sergio Moreno for implementing this migration!

“Empty” template

A new template has been added to npm init video / yarn create video: The blank template. This template contains only the bare minimum Remotion boilerplate and a completely empty canvas. It is especially useful for people already familiar with Remotion who would like to skip deleting the Hello World project every time.

Thanks to Aneesh Relan for creating this template!

Render video to out folder

Previously by default, a video would be rendered to out.mp4 in the root directory of your project. This also meant that in order to ignore it from Git, we had a complicated .gitignore by default that would ignore video files in the root but inverse-ignore other video files. Time to simplify: From now on, we render a file into an out folder by default and simply ignore that folder.

Thanks to ahmadrosid for implementing this feature!

Updates to @remotion/three

A few interesting updates for users of @remotion/three:

  • The Three Canvas is now wrapped in <Suspense> and the render is delayed until the content has been loaded (unsuspended). This works better with the React Three.JS ecosystem and now components such as drei’s <Environment /> component will work out of the box.
  • We now default to the angle OpenGL engine for Google Chrome, which we, through empirical testing, have found to have the best overall support for Three.JS content across platforms.

More updates

  • Added support for OTF fonts - Thanks William Candillon!
  • Added possibility to customize <Player> error message - Thanks AudreyKj!
  • Windows Node.JS 14 cleanup bug fixed - Thanks Raznov!
  • Upgraded Docusaurus to the newest version, obtaining the newest features and layouts

Hacktoberfest Roundup

We opted into participating in Hacktoberfest, and put $100 bounties on 11 issues as an extra incentive! Every single of those issue has been picked up and solved! Every contributor did a great job, many greatly surpassing our expectations!

Thank you everybody who participated and contributed to this release!