One problem when using a spring animation for transitions
is that you don't know the duration of the animation. This is why we added a new measureSpring() function!
Now you can adjust your timings in Remotion dynamically when changing spring configurations.
We invested time in making sure that if something goes wrong, you don't get stuck. Here are some things we did to improve your experience with Remotion:
If you encounter a timeout, you will now see a stacktrace of where the delayRender() handle was not cleared. We also now have a troubleshooting page for timeouts and link to the documentation if you encounter the error.
If you use Chromium and import an MP4 video, you get a more helpful error and we link to a help page.
We added a guide for improving performance while development and while rendering.
We are working on a Remotion player component that you can import into your React app. Today we are prereleasing the player for those who wish to experiment and provide us with feedback. Let us know what you think!
We now have over 450 tests, and the Remotion core has a test coverage of over 80% now. Thanks to Tobias Boner, Calvin Falter and Jonas Brunner for continuining their massive testign initiative!
We now also test across different node versions (12, 14 and 16), npm versions (v6 and v7) and FFMPEG versions (4.1 and 4.4) in addition to testing on 3 different operating systems so we can confidently release new features quickly.
We are happy to ship audio support with a flexible API!
You can import one or multiple audio tracks into your project, cut, trim and align them in your composition. The volume can be controlled for the entirety of a track, or you can control it frame by frame to create fade effects and much more. Apply your React mindset - Remotion doesn't care how you render the audio tag, just that it's there. The mechanic of how we tell FFMPEG to mix the audio just like you hear it in the browser preview is really complex and was challenging to build - we are very proud of the outcome!
You can now also completely omit the video from the output and only emit an audio file. Yes, Remotion can also be used as an audio editing program! Pass mp3, aac or wav as a codec using the --codec flag or in your config file.
All of them except the last one are completely independent from the ideas of Remotion, so they might be a great fit for your other non-Remotion projects as well! This package is MIT-licensed, so you everybody can use it without obtaining a company license.
With the normal timeline, you don't see the full picture of all the media that you have placed in your composition. The reason is that the visualization you see is based on what's currently rendered at the position of your playhead.
Introducing a new timeline mode: The rich timeline will render additional frames other than the current one to gather enough information to visualize a full timeline.
Sequences which are normally not rendered because the playback head is not within the time range of the sequence, will appear because Remotion is doing an additional render at a time where the sequence is visible.
By default the rich timeline feature is disabled, but will be enabled by default if the feedback is good. You may switch between the rich timeline and simple timeline by clicking the icon with the three lines. Try it out and let us know what you think!
The traditional transpilation of Javascript and Typescript using babel-loader has been replaced by the faster esbuild-loader by default.
This will speed up bundling by a lot - hopefully you won't notice any other differences! If you for some reason need to go back to the previous behavior, you may override the Webpack config - we are releasing a helper that makes it easy.
Even though transpilation is done using ESBuild now, Webpack is still being used for bundling. We rely on Webpack features such as Hot Module Replacement, asset importing, it's strong loader ecosystem and now it's caching features.
When you run npm run build for the first time, you will get a message that a cache is building. From the second time on, bundling will be much faster, even if you change your code. You shouldn't have to ever do it, but you can opt out of caching.
Want to render partial video or a still for thumbnail? You can do that with Remotion 2.0. We introduced a new CLI flag --frames to render a subset or a still of a video.
--frames=0-9 (To select the first 10 frames) or --frames=50 (To render a still of the 51st frame).
A new GIF component released in the @remotion/gif package is now available. The <Gif /> component allows to load a local or remote GIF and synchronizes it with Remotions useCurrentFrame(). For that it parses the GIF using WebAssembly - basically it's really cool tech! Thanks a lot to @jeetiss for contributing this new component.
interpolate() now supports arrays with lengths bigger than 2. Really useful for a lot of scenarios - for example you can create a combined fade in/fade out transition with one line.
While not strictly a new feature, this is definitely worth mentioning.
Calvin Falter, Jonas Brunner and Tobias Boner took Remotion as their project for their university seminar and contributed over 100 tests, strengthening the code and ironing out edge cases.
@cnnr contributed a really cool end-to-end test that tests the video seeking of Remotion and makes sure it is frame-accurate by matching the colors in each frame.
The remaining added tests are testing the tricky parts of audio rendering. Thanks to test-driven development, we've been able to catch regressions and ship really solid audio support.
The bottom line: In Remotion 1.5.4 we had total 43 tests, in Remotion 2.0 we added a total of 174 tests to come out at a total of 217.
<Video/> and <Audio/> have startFrom and endAt propsโ
These new props make it easier to cut the start or the end of the video. This is implemented using sequences, which was also possible before, but this is a convienient shorthand.
In Remotion 1.x, a <Video/> would not always perfectly synchronize with Remotions time during render. This is now fixed and validated by tests that scan the color of the output frames - however not in the most efficient way. Help on improving it further is still welcome.
Importing files into your webpack bundle that were of significant size (the problems started at around 40MB) led to slow renders and timeouts. This is now fixed by swapping out dependencies and making sure the whole stack supports the HTTP range header well. Now if you seek a video, only the necessary parts will be loaded from the filesystem rather than the whole file being read.
We've taken this opportunity of a major release to introduce some breaking changes that we think are beneficial for an awesome future of Remotion. Please take a moment to read through the 2.0 Migration guide and see if you are affected.
Most of the core functionality for making videos in React is now implemented.
This gives us time to focus on improving all the areas around it - we are talking better documentation, developer experience, examples, abstractions on top or Remotion, improving speed and reliability of Remotion.
Furthermore, we want to provide a way to embed Remotion compositions in traditional web apps and to make server-side rendering easier - stay tuned!
We got rid of the "Contact us for pricing" policy and have announced the pricing for Remotion publicly. Head over to companies.remotion.dev to see it!
This is a new platform where you can directly buy a Remotion license, get invoices, upgrade/downgrade or cancel without having to get in touch with us.
Needless to say, you can still email us if you like a consultation!
Until now, every time you ran yarn create video, a binary of Chromium was installed, which was slow and took a lot of space (between 170-280MB depending on the OS). Making matters even worse, these binaries would not include the codec required to play MP4 videos, meaning if you wanted to embed one, you had to convert it to WebM first.
Now Remotion will try to find an existing installation of Chrome on your machine and if it finds one, it will use it and skip the download. If it doesn't find one, you can specify the path using the setBrowserExecutable() option or the --browser-executable command line flag.
If you are running Remotion on a machine where neither Chrome nor Chromium is installed, Remotion will still download a version from the internet. However, the download only happens when you invoke npm run build for the first time, so you don't have to wait so long before you can start experimenting.
Apple Silicon support is another nice side-effect of the Puppeteer refactor, since previously the installation would fail because no Chromium binaries were available for the Apple Silicon architecture. Now that Remotion will try to use the local Chrome installation this is way less likely to happen.
On Windows Subsystem for Linux, a missing flag would lead to Remotion getting stuck during rendering. This is now fixed. Linux users also need to install some additional libraries, which is now documented.
Why would the timeline of your 30 FPS only play at 28.7FPS? Turns out it's a bug that was investigated and fixed by yuta0801! Now the playback during preview is smoother and the FPS counter is way more likely to display a number matching your desired FPS.
If a frame fails to render for some reason (such as calling delayRender() and never resolving the lock), this will now stop the rendering process. Previously you would get an error message but Remotion would keep trying and keep failing.
Previously during rendering, frames would be opened via file:// protocol and get screenshotted. Now the frames are being served on http://localhost:3000 (if port is not available, it will try 3001, 3002, etc.), which is the same behavior as in the preview.
Now APIs can now simply whitelist localhost domains in their CORS configurations, and you can more easily use those APIs to feed data into your video.
In case you missed it, I released a new tutorial showing the workflow of how to programmatically create Instagram Stories with dynamic content. You can watch it here.
Welcome to the release notes of Remotion 1.4! This is a big release adding support for more use cases and makes Remotion more stable, intuitive and robust.
Instead of just supporting H.264, you can now also encode a video in H.265 (HEVC), or as a WebM (in either VP8 or VP9 codec). These codecs will result in smaller file sizes, but have some trade-offs. To help you decide which codec to use, there is now an encoding guide in the docs. See also the
documentation for changing the codec in the config file
as well as in the CLI.
Did you know that Chrome and Firefox support video with alpha channels? Play the video and click the button below to dynamically change the background.
Remotion now has enough configurability to enable you to render transparent videos. There is a new documentation page for it, which also gives you guidance on how to render a fallback video for unsupported browsers.
Let's say you want to render 100 random particles in a video. A common mistake is to generate random values and store them in a state. The following is an anti-pattern in Remotion:
tsx
exportconstMyComp= () => {
// โ ๏ธ Bug! Random values will change during render
const [particles] =useState(() => {
returnnewArray(100).fill(true).map(() => ({
x: Math.random(),
y: Math.random(),
}));
});
};
tsx
exportconstMyComp= () => {
// โ ๏ธ Bug! Random values will change during render
const [particles] =useState(() => {
returnnewArray(100).fill(true).map(() => ({
x: Math.random(),
y: Math.random(),
}));
});
};
While this will work while previewing the video, during rendering, the random numbers will change during frames. This is because Remotion spins up multiple instances of Chrome and the random numbers will be different in each instance.
To help you avoid this mistake, there is now a new ESLint rule that will warn when you use Math.random(). Instead using it, you can use the new random() API. It will take a seed parameter and output a number between 0 and 1. The point of it is: As long as you pass the same seed, you get the same output! That way you don't get unintended effects while multithreaded rendering is performed.
tsx
import { useState } from"react";
import { random } from"remotion";
ย
exportconstMyComp= () => {
// โ Pseudo-random values that will be same across threads
const [particles] =useState(() => {
returnnewArray(100).fill(true).map((_, idx) => ({
x: random(`x-${idx}`),
y: random(`y-${idx}`),
}));
});
};
tsx
import { useState } from"react";
import { random } from"remotion";
ย
exportconstMyComp= () => {
// โ Pseudo-random values that will be same across threads
const [particles] =useState(() => {
returnnewArray(100).fill(true).map((_, idx) => ({
x: random(`x-${idx}`),
y: random(`y-${idx}`),
}));
});
};
Want to learn more? Read the new documentation page about using randomness.
Several new configuration options have been added as CLI flags, config file entries and to the SSR API:
setCrf() controls the tradeoff between quality and file size of the output file.
setQuality() allows you to control the JPEG quality of the frames rendered.
setCodec() allows you to select between 4 different codecs (as mentioned above).
setImageSequence() allows you to skip the stitching process and output only an image sequence
setImageFormat() allows you to explicitly select either PNG or JPEG as the format for the rendered frames.
setPixelFormat() has a new accepted value, yuva420p, which is necessary for transparent videos.
The addition of setImageSequence() and setImageFormat() as well as setCodec() makes the previous configuration options setOutputFormat() and --png obsolete. and they are therefore now deprecated. While they still work, we encourage you to use the new configuration options which are much more granular - for example now you can render a JPEG sequence if you wish to.
Thanks to an awesome pull request by Arthur Denner, keyboard navigation in the editor is much improved! Reading the PR is highly recommended because it's insightful and makes you realize that it's not hard to make a website keyboard-navigateable.
Don't be surprised if the newly added codecs are much slower than the default H.264. It's normal. But at least now you can always check the progress of the rendering!
Few people have rightly pointed out that the <Sequence> component will absolutely position it's children and there is no way to opt out of it. While we cannot change this now because of backwards-compatibility, you can now pass layout="none" as a prop to opt out of any layout influence that <Sequence> has.
There's a small breaking change in this release - delayRender works during the 'evaluation' phase. This is the phase where Remotion analyses your project and determines all compositions and does some validation. Watch out for delayRender() calls outside components, as they might block the evaluation phase now since no components are being rendered during that phase.
The benefit is that now your compositions can take in data that has been asynchronously fetched. For example the following is now possible:
While Remotion is primarily developed on macOS, other operating systems shouldn't have a sub-par experience or get bugs. While it does not replace manual testing, it helps that there are now some end-to-end tests for rendering videos and the test suite now runs on all 3 operating systems. Going forward, I will add more tests and contributors are also encouraged to do so.
In Remotion, you shouldn't specify the src as filepath string, but import the asset instead. To help you not make this mistake, there's a new ESLint rule:
tsx
import {Img} from'remotion';
import hi from'./hi.png';
// โ Correct: Using an import statement
<Imgsrc={hi} />
// โ ๏ธ Warning since 1.4: Import the asset instead
<Imgsrc="./hi.png"/>
tsx
import {Img} from'remotion';
import hi from'./hi.png';
// โ Correct: Using an import statement
<Imgsrc={hi} />
// โ ๏ธ Warning since 1.4: Import the asset instead
Since Remotion will make money by selling licenses to bigger companies, it's only fair to give contributors their share as well! I have made offers to two top contributors so far to compensate them for their time spent so far and for potential future work. Gladly, they both accepted!
Some awesome pull requests came in, the most notable one adds audio support! We are also working on allowing you to customize Puppeteer parameters and making the installation process much faster by not downloading a copy of Chromium. Keep your eyes open for more major improvements coming soon.
Only 1 week after the initial launch, here is Remotion 1.3! In just 7 days, we have merged over 40 pull requests - just amazing! Let's go over the changes in this release.
2 days ago, the rendering time was cut in half, and in this release, we managed to half it again! Check out this benchmark of the Spotify Wrapped example:
Remotion 1.1
hyperfine --min-runs 5 'npm run build -- --overwrite --concurrency=16'
Benchmark #1: npm run build -- --overwrite --concurrency=16
Time (mean ยฑ ฯ): 98.972 s ยฑ 0.650 s [User: 123.329 s, System: 10.103 s]
Range (min โฆ max): 97.951 s โฆ 99.540 s 5 runs
hyperfine --min-runs 5 'npm run build -- --overwrite --concurrency=16'
Benchmark #1: npm run build -- --overwrite --concurrency=16
Time (mean ยฑ ฯ): 98.972 s ยฑ 0.650 s [User: 123.329 s, System: 10.103 s]
Range (min โฆ max): 97.951 s โฆ 99.540 s 5 runs
Remotion 1.3
hyperfine --min-runs 5 'npm run build -- --overwrite --concurrency=16'
Benchmark #1: npm run build -- --overwrite --concurrency=16
Time (mean ยฑ ฯ): 17.921 s ยฑ 0.224 s [User: 36.492 s, System: 3.482 s]
Range (min โฆ max): 17.650 s โฆ 18.264 s 5 runs
hyperfine --min-runs 5 'npm run build -- --overwrite --concurrency=16'
Benchmark #1: npm run build -- --overwrite --concurrency=16
Time (mean ยฑ ฯ): 17.921 s ยฑ 0.224 s [User: 36.492 s, System: 3.482 s]
Range (min โฆ max): 17.650 s โฆ 18.264 s 5 runs
From 98 to 18 seconds - that's 5.5 times faster! At the same time, we have reached an important milestone: This 19-second long 720p video was rendered faster than realtime. Granted, my computer is faster than most (8-core Intel i9-9900K chip), but still very impressive!
We achieved this performance gain through various Puppeteer rendering pipeline optimizations. Big shoutout to jeetiss who implemented a sophisticated performance optimization that doesn't require a page reload for each frame anymore.
My goal was to force Typescript on everybody - but I failed. Support for plain Javascript is now added! See here how to enable it. Proceed carefully ๐
Many options which you could pass in via CLI flags, you can now also add by adding a remotion.config.ts file in the repo. For example, if you want to increase the concurrency to the amount of threads you have and never want to write --overwrite, you can add the following to the config file:
You can see all the options on this page. The goal of making a config file in Typescript is to provide autocomplete, to easily highlight deprecated options and making it easier to show how to migrate in case the options change in the future.
The exports of Remotion have been cleaned up and the internal stuff has been moved into Internals. You shouldn't rely on these APIs are you are at risk of them changing over time.
Another example was added - Spotify Wrapped! This is a fully dynamic example where you can replace all data with a command line flag. There's a 2 hour tutorial on YouTube and the source code is on GitHub.
It turns out rendering each frame as JPEG is much faster than rendering them in PNG and results in no visible quality difference. Using this trick, the time of the 'Rendering Frames...' of an example video went down from 14 seconds to 6.5 seconds! That's more than twice as fast.
Windows support is very important (just like PHP). All the bugs that prevented proper Windows installation have now been fixed. Plus I now have a proper Windows setup so from now on Remotion will be tested on Windows as well!
What an extraordinary launch! In less than 24 hours, the Remotion announcement video has gotten more than 100'000 views on Twitter. The feedback was absolutely overwhelming!
Now it's time to iterate and make Remotion better. This release contains two new features: Customizing the Webpack configuration and new <Img> and </IFrame> components!
People had wild ideas on what to do with Remotion like importing MDX files or using React Native components. Now it is possible!
When providing the possibility on how to configure Remotion, it was of big importance to provide both a high degree of flexibility and a good developer experience. This is how you update the webpack config:
There is a new Remotion config file, that you can write in Typescript. Updating the Webpack config uses the reducer pattern: You get the default configuration and it is your responsibility to return an updated Webpack config. You get type checking, auto completion and the flexibility to either only update a single property or pass in a completely new configuration. No black magic here - since this is just a pure function, the outcome will be very predictable.
The purpose of these new components is to help with something that is easy to overlook in Remotion: Images or Iframes are being rendered, but Remotion does not wait until the loading of these network resources are complete. The result: Flicker in the end result! The correct thing is to wait using the delayRender API, but this is not very obvious. Now Remotion comes with built-in components that will wait until assets are loaded.
To prevent shooting yourself into your foot, Remotion now comes with an ESLint rule that warns if you use the native <img>, <iframe>, <video> or <audio> tags. These tags work better when you use the Remotion-wrapped versions instead.
in your project and you'll get all the newest Remotion packages! Maybe you also noticed that there is a banner in the editor that notifies you when an upgrade is available.
I've been using After Effects for many years, but it's always been a dream of mine to code my videos instead. In the React ecosystem, I am used to being able to take advantage of powerful composition, reusability, to be able to customize the experience for every user. To use scripts, linters and external dependencies to make my life easier as a coder.
So as a proof of concept I tried to make a trailer for my AnySticker app1 in React, and to render each frame using Puppeteer and stitch them together using FFMPEG.
The final result was a video that I thought was the best one I created yet. And I realized there was something to the idea.
This is my attempt to create a tool for the community that allows you to write videos in React. Obviously this is a huge undertaking, so this is not a product with hundreds of different features built in. Rather, following the React philosophy, this is an attempt to create a minimal fundament for rendering videos in React. Basically, you get a blank canvas, and you create your motion graphics using existing web technologies built into the browser and your favorite external libraries. Remotion is so minimal in fact, it consists of only 5-6 APIs that you need to learn to get started.
To get started is super easy. Assuming you already have Yarn, run: