Skip to main content

Remotion 2.4

ยท 4 min read
Jonny Burger
Remotion Creator

In this release, we are revamping the Remotion Preview interface to make it easier on the eyes and add new features. While Remotion will always be about leveraging code instead of clicking buttons, we want to add complementary helpers to help you get your videos done faster!

New toolbarโ€‹

All the actions that can be performed in the editor are now organized in a toolbar at the top, plus we added quick links to resources such as Documentation, Changelog, GitHub, Support options and our social media accounts (follow us over there!).

"New composition" helperโ€‹

You can press N to bring up a modal that helps you generate code for creating a new <Composition /> or <Still />. Drag the sliders to quickly adjust the dimensions and duration of the video. Lock or unlock the aspect ratio. Click the numbers to enter an exact value. Receive warnings on invalid configuration. Once you are happy with the code, you can click the copy button and paste it in your src/Root.tsx file.

"Keyboard shortcuts" paneโ€‹

To get an overview of all keyboard shortcuts, you can now press ? to bring up a list of all shortcuts.

Improved keyboard navigationโ€‹

For those true hackers that don't use mouses, we optimized the whole new UI to be usable with just the keyboard. Use the Tab key to focus items, the arrow keys to navigate through menus. Press Enter or Space to click on items. Use Escape to quit modals and menus.

Built with 0 dependenciesโ€‹

We want to add new features to the Preview, but not bloat Remotion by adding tons of third-party packages that increase startup time and at some point will cause you to fight with your package manager. So we carefully crafted the editor with no dependencies except React and Remotion (which also only has react and react-dom as it's only dependencies).

Other improvementsโ€‹

  • New <Series /> component: Introduced in 2.3.2, we added a new <Series /> component that helps you layout many sequences in a row. See this post (Instagram | Twitter) for additional infographic explanation!

  • Better handling for browser autoplay policies: If you use the <Player /> and include audio in it, you might hit a browser limitation where audio cannot be played because of a browsers autoplay policy. Remotion can now avoid some of those scenarios by playing some silent audio when the user actively triggers a play on the Remotion Player. If you then later in the video want to play some audio, Remotion will route that audio to an <audio /> tag that was already playing silent audio and was already freed from the playback restrictions of the browser. You can control the amount of silent audio tags that Remotion should place using the numberOfSharedAudioTags prop.

  • Better handling of invalid dimensions: It turns out that MP4s can only have even dimensions. So while a 1000x1000px MP4 is completely fine, a 999x999px MP4 is not possible according to the spec. Instead of erroring out when rendering, we now warn you early using a new ESLint rule, and also when you use the "New composition" dialog.

  • Bug fixed when using frameRange: A one-off error would cause the wrong frames being rendered when using the frameRange option. If you specified a frame range of 0-20, the frames -1 until 19 would be rendered. This is now rectified, if you were reliant on this option, please make sure your video renders as intended after the update!

  • Component mounts directly at desired frame: During rendering, previously the browser would always mount the React component at frame 0, and then update the component with the initial frame that should be rendered. This is now changed, so if you are e.g. using the frameRange option to render frames 20-39, your component will now never mount at frame 0 after this update.

Up nextโ€‹

We are working on revamping the rendering pipeline and adding more ways to render a Remotion video and plan to release this as a major version bump (v3.0) with some breaking changes. Stay tuned for announcements on how we make Remotion much easier to scale.

Remotion 2.3

ยท 4 min read
Jonny Burger
Remotion Creator

Remotion 2.3 is out and features first-class support for still images!

So far we focused on streamlining the workflow for making videos. While it was always possible to render out a single image instead of an encoded video, we have optimized this use-case in this release.

New <Still /> componentโ€‹

This new component is the same as <Composition /> but is meant for defining a compositions that output a still image. Since it's already implied, you don't have to define the fps and durationInFrames properties.

tsx
<Still
id="Thumbnail"
component={Thumbnail}
width={1200}
height={627}
defaultProps={{
title: "Welcome to Remotion",
description: "Edit Video.tsx to change template",
slogan: "Write videos\nin React",
}}
/>;
tsx
<Still
id="Thumbnail"
component={Thumbnail}
width={1200}
height={627}
defaultProps={{
title: "Welcome to Remotion",
description: "Edit Video.tsx to change template",
slogan: "Write videos\nin React",
}}
/>;

Optimized editor for stillsโ€‹

There are now icons in the sidebar for compositions, and those who are stills have an image icon.


Now still images (compositions with a duration of 1 frame) are marked with a special icon.

For still images, you don't need the timeline, so it will hide itself and give you a bigger canvas.


New remotion still commandโ€‹

Rendering stills has become easier as well. The new remotion still command allows you to quickly generate a PNG or JPEG on the command line.

npx remotion still --props='{"custom": "data"}' my-comp out.png
npx remotion still --props='{"custom": "data"}' my-comp out.png

New renderStill() APIโ€‹

If you render using the Node.JS APIs, we have a new equivalent API for rendering stills as well.

ts
await renderStill({
composition,
serveUrl: bundleLocation,
output: "/tmp/still.png",
inputProps: {
custom: "data",
},
});
ts
await renderStill({
composition,
serveUrl: bundleLocation,
output: "/tmp/still.png",
inputProps: {
custom: "data",
},
});

New Stills template with server renderingโ€‹

We have made a new template that includes a social media preview card and a server that you can customize and easily deploy to the cloud. We have tested it on DigitalOcean and Heroku and have added instructions on how to deploy it.

We use this service to generate the social preview card for the blog post you are reading right now. Feel free to go to this URL and play around with the parameters:

https://remotion-still.herokuapp.com/PreviewCard.jpeg?title=Remotion%202.3&description=%3CStill%20/%3E%20component,%20renderStill()%20API,%20optimized%20editor%20and%20CLI,%20Server%20rendering%20template

The server includes different caching options, rate limiting and limits to 1 render at a time, so hopefully it's ready for production. We put the URL out there for you play around with it, should there be any unexpected problems, we'll fix the template.

๐Ÿ”œ Serverless in the worksโ€‹

We are also working on getting still image rendering working in a serverless environment and providing a framework for it. We aim to launch it this fall - if you are interested in testing an early version, write us a message in our Discord.

yarn create video now has multiple templatesโ€‹

When creating a new video, you now get to choose between different templates, that give you a great starting point for your usecase.


In addition to the default template and the previously announced Three.JS template, there now is also a plain-JS template, a text-to-speech template and the above mentioned Stills template.

Player now supports space key to play/pauseโ€‹

The <Player /> component now supports the new spaceKeyToPlayOrPause prop to toggle the video playback. We designed it with focus management in mind so it behaves well when multiple players are on the same page. This prop is by default true.

Remotion 2.2

ยท 9 min read
Jonny Burger
Remotion Creator

Welcome to the release notes of Remotion 2.2! It's been a while since v2.1, but in the meanwhile we had a dozen smaller releases inbetween. This post summarizes the highlights of the past 2 months ๐ŸŽ‰.

Environment variable supportโ€‹

We developers use environment variables extensively to manage configuration, secrets and other stuff you don't want to commit to a GitHub repo. If you write videos with code, environment variables are useful too!

We added support for environment variables from the CLI, using a .env file, and allowing you to pass environment variables via our Node.JS APIs too. Click here to learn more.

<Freeze /> componentโ€‹

This new core component will freeze all of it's children and make them think that the video is paused at a certain time.

You can use it for example to display a still frame from a video:

MyVideo.tsx
tsx
import { Freeze, Video } from "remotion";
import myVid from "./vid.mp4";
 
export const MyVideo = () => {
return (
<Freeze frame={30}>
<Video src={myVid} />
</Freeze>
);
};
MyVideo.tsx
tsx
import { Freeze, Video } from "remotion";
import myVid from "./vid.mp4";
 
export const MyVideo = () => {
return (
<Freeze frame={30}>
<Video src={myVid} />
</Freeze>
);
};

However, it works for any content. As you can see the API is dead simple! You can combine it with the <Sequence> API to make any content play, pause and then continue again.

Read the docs for the <Freeze /> component here.

Video + Audio playbackRateโ€‹

This prop allows you to slow down or speed up video and audio elements! Now you can import a video in normal speed and play it in slow motion or timelapse without re-rendering the video.

LightningSpeed.tsx
tsx
import { Video } from "remotion";
import myVid from "./vid.mp4";
 
export const MyVideo = () => {
return <Video src={myVid} playbackRate={4} />;
};
LightningSpeed.tsx
tsx
import { Video } from "remotion";
import myVid from "./vid.mp4";
 
export const MyVideo = () => {
return <Video src={myVid} playbackRate={4} />;
};

While previewing, we are using the HTML5 playbackRate API, and when rendering, we will calculate the correct FFMPEG command for any tempo.

Learn more about the playbackRate props for <Audio /> and <Video />.

@remotion/three packageโ€‹

In case you missed it, we released a new helper package for React Three Fiber!

0:00 / 0:10

Three.JS is admittedly not easy, but with the work that Poimandres is doing to make it more approachable and more integrated with React, this is changing rapidly. Creating 3D videos in React and rendering them to real MP4 videos, we are making it possible!

Learn more about @remotion/three and get started using our template.

ProRes support and MKV supportโ€‹

Creating MP4 videos with React, that's just our marketing tagline. We support a lot of other codecs too, like H265, WebM, and even transparent WebM!

We are adding two more codecs:

  • ProRes is a codec suitable for video editors using Final Cut Pro, Adobe Premiere or Davinci Resolve. Say you want to create an overlay animation using Remotion and use it in a traditional video cutting program, you can now use ProRes to export the video with an alpha channel and import it to many other programs losslessly.

  • The Matroska container format (which can be recognized using the .mkv extension) is a format that commonly also just contains the H.264 videos, the same codec used for MP4s. However it has more flexibility for audio and allows lossless audio streams to be contained by the format. MKV support will come in handy for an upcoming Remotion feature, and is the first step in allowing us to go to the moon.

Read the Encoding guide to see an overview of all options.

<Player /> updatesโ€‹

The @remotion/player, currently still experimental, allows Remotion videos to be played on the web without having to encode them. We've made the following progress towards getting it stable:

Audio controlsโ€‹

A player now has a volume slider, and a mute button to allow the user to control the video. You can decide whether you want to display these controls using the showVolumeControls prop.

Audio can also be controlled programmatically. We added the methods getVolume(), setVolume(), mute(), unmute() and isMuted() to allow you to implement your own solutions.

timeupdate eventโ€‹

Inspired by the HTML5 event with the same name, we added a timeupdate event to the Player. Unlike the seeked event, it does not fire on every frame, so if you want only periodic updates about the time being updated, you can use this event without having to throttle it.

clickToPlay propโ€‹

This prop allows you to control whether the user is allowed to click on the video to make it pause or play. It is true by default if the controls of the player are enabled.

doubleClickToFullscreen propโ€‹

This prop allows you to control whether the user is allowed to double click on the video to make it go fullscreen. If enabled, single-clicking to pause the video will have a short delay in order to wait for a potential second click.

Timeline scroll position gets persistedโ€‹

When coding a video, and refreshing the preview, the video would jump back to the first frame which was annoying. Not anymore - if you refresh you are back where you left off!

Remotion waits for fonts to be loadedโ€‹

If a Webfont gets loaded via Google Fonts, it would be loaded using font-display: swap, which means Remotion would sometimes render a frame before the font is loaded. Now we use the document.fonts.ready browser API to make loading webfonts completely seamless for you.

Specify a custom --portโ€‹

By default the Remotion Preview starts a server on port 3000. Should you want to have it start on a different port for any reason, you can now pass a CLI flag.

More helpful error handlingโ€‹

We want to help you out whenever you are facing a tricky issue. Here are some examples of scenarios where we now give you a helpful warning and linking to the documentation:

  • Multiple versions of Remotion are imported on a page (for example when using the <Player /> in your app)
  • A video is loaded that does not support seeking (for example when serving from Google Cloud Storage)
  • A video with an unsupported codec is loaded (for example an MP4 in the Chromium browser)
  • A delayRender() handle has been created but never cleared

Documentation upgradesโ€‹

We now have a search at the top right of the docs! Thanks to Algolia for hosting the widget and indexing the documentation.

Type hintsโ€‹

Did you notice it in the snippets above? You can now hover over any symbol and see it's type. It's powered by Typescript + Twoslash. A really nice side effect is that it's now impossible for us to make typos in the documentation since all snippets are type checked.

Troubleshooting guidesโ€‹

We now have help articles on various issues that you may face. Currently we have written about 6 common problems, and put them in a new section of the docs called Troubleshooting.

Page about third party integrationsโ€‹

A new page has been created listing some popular libraries and describing how well they work together with Remotion - or don't.

New landing pageโ€‹

Finally, the homepage of Remotion got a makeover! We hope to better communicate what Remotion is and why it's awesome.

Various Bugfixesโ€‹

  • Fixed a memory leak while calling getCompositions() #480
  • Add emoji support to Dockerfile #476
  • The preview now shows the current time within a sequence in a timeline #468
  • TTF fonts can now be loaded locally #462
  • Fix Remotion Player assuming it's in a rendering environment #460
  • Fix getAudioMetadata() and getAudioDuration() not returning an error in the onError event #459
  • Added documentation on how to use TailwindCSS 69b079e
  • Fixed documentation about how to use SASS/SCSS e92c917
  • If you are using a plain JS entry file, you can also use a remotion.config.js config file #475
  • You can customize how many timeline tracks should be shown at most using Config.Preview.setMaxTimelineTracks() #439
  • Fixed a bug where environment variables would not be immediately accessible #432
  • Input props flag can now also be passed for preview #430
  • Better input validation of the most common functions
  • Improve rendering of very long videos, using less memory and avoiding a maximum callstack exceeded error message. #398
  • Setting crf to 0 is not allowed anymore for H264 videos as it will lead to a video that does not play on all platforms. #379
  • The docs for <Sequence /> now have interactive examples. #378
  • A lot of tests have been added to the core functions. #376 etc.
  • The Typescript types have been improved to allow for more types of components to be passed to component. #372

Thank you to all the contributorsโ€‹

Most of these features were brought up and implemented by the community which is super awesome. Time for some shoutouts!

  • Thanks to Bjรถrn Zeutzheim for implementing the @remotion/three package!
  • Thanks to Frenco for making all documentation code snippets typesafe and adding hover preview. You even fixed a bug in Twoslash, the library powering this feature and executed this with so much care!
  • Thanks to cnnr for implementing environment variables support!
  • Thanks to Arthur Denner for discovering the document.fonts.ready feature!
  • Thanks to Ashik Meerankutty for implementing the timeupdate event for the Player!
  • Thanks to Soham Shah for adding GitHub Issue Templates and working on a Next.JS template!
  • Thanks to William Candillon for implementing ProRes support!
  • Thanks to Salvatore for implementing playbackRate support for Video and Audio components!
  • Thanks to ahgsql for improving how Sequences are displayed in the timeline!
  • Thanks to Mika Andrianarijaona for implementing the --port parameter!
  • Thanks to Jonas Brunner, Tobias Boner and Calvin Falter for vastly improving the test coverage!
  • Thanks to Tamรกs Sallai for filing and commenting many important issues and drafting accessibility features.

As well as many other contributing bugfixes and documentation improvements.

Business updateโ€‹

We start seeing people launching products and startups using Remotion, which is awesome. Stay tuned for posts that highlight how people are using Remotion for their business case! At the time of writing, five customers are currently in possession of a Company license.

In addition to Shankhadeep Dey, we are also welcoming Mehmet Ademi to the team as a project manager and business developer.

We are increasingly putting bounties on non-urgent issues and have rewarded $657 to Remotion contributors to far, in addition to multiple thousands of dollars being paid out to top contributors that were approached by us.

We are working on multiple fronts to make Remotion even better for businesses and Indie Hackers that want to integrate programmatic video into their product - stay tuned!

Remotion 2.1

ยท 3 min read
Jonny Burger
Indie Hacker

This releases features new utility functions, improved developer experience and an experimental release of the Remotion Player!

New interpolateColors() function ๐ŸŒˆโ€‹

Now you can easily animate between colors and mix colors to create interesting animations using interpolateColors().

I personally used it to recreate Apple's 'Spring Loaded' logo in Remotion using only <div> elements.

Thanks for Shankhadeep Dey for implementing this feature!

New measureSpring() function ๐ŸŒ€โ€‹

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.

Thanks to Samuel Rodriguez-Lozano for implementing this feature!

Documentation and developer experience updatesโ€‹

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.
  • The server-side rendering APIs bundle(), getCompositions(), renderFrames() and stitchFramesToVideo() with all their parameters are now more properly documented.
  • If an exception is thrown while rendering, the log output in the console is now better.

Alpha release of @remotion/playerโ€‹

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!

Read the documentation for @remotion/player

Hi there!Your favorite color is
0:00 / 0:11

Enter your name:

Select your favorite color:

Test coverage updatesโ€‹

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.

For contributors, we now have a TESTING.md file.

Miscellaneousโ€‹

  • You can now press Shift+Right Arrow to jump 1 second forward in the timeline and Shift+Left Arrow to jump 1 second back.
  • npm init video will now setup a Remotion project with NPM, yarn create video will setup a project with Yarn.
  • Node 16 and NPM 7 is now better supported, no warnings will be shown during installation and execution.
  • Fixed several audio rendering issues: [#292](https://github.com/remotion-dev/remotion/issues/292 #293 #320
  • When the update banner appears in the editor, you can now click to copy the command.
  • You can now pass a React ref to <Audio/> and <Video /> tags.
  • We revamped the CLI output! How do you like it?
  • The preview size option in the editor is now persisted, thanks Oluwatobiju Judah!
  • In the editor, the transparency toggle is now enabled by default.

Remotion 2.0

ยท 7 min read
Jonny Burger
Indie Hacker

This is our biggest and best release so far - today we are unloading a lot of awesome, highly requested features!

Audio supportโ€‹

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!

Audio visualizationโ€‹

With newly introduced audio visualization APIs, you can make your visuals react to the frequency of the audio.

What you need are the new getAudioData() and visualizeAudio() APIs that have been published in it's own package.

Read more about audio visualization in the docs or watch a sample video (the source can be found here).

Export as MP3, AAC, WAVโ€‹

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.

@remotion/media-utils packageโ€‹

This is a new helper package which includes functions useful for dealing with audio. Besides audio visualization, you can also for example measure the duration of an audio or video source, which is really useful for making a composition duration dynamic. The functions included are getAudioData(), getAudioDuration(), getVideoMetadata(), getWaveformPortion(), visualizeAudio() and useAudioData().

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.

Rich Timeline (experimental)โ€‹

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!

ESBuild loaderโ€‹

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.

Webpack cachingโ€‹

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.

Partial video rendering + Stillsโ€‹

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).

Learn more about the --frames CLI option.

@remotion/gif componentโ€‹

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.

Learn more about the GIF component here.

Resizable editor panelsโ€‹

In the editor, you can now resize the timeline as well as the left sidebar. Thanks a lot to Arthur Denner for this awesome contribution!

interpolate()โ€‹

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.

tsx
const opacity = interpolate(
frame,
[0, 10, durationInFrames - 10, durationInFrames],
[0, 1, 1, 0],
);
tsx
const opacity = interpolate(
frame,
[0, 10, durationInFrames - 10, durationInFrames],
[0, 1, 1, 0],
);

170+ tests addedโ€‹

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.

Fixed: Frame seekingโ€‹

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.

Fixed: Timeouts while importing large videosโ€‹

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.

Breaking changes and upgradeโ€‹

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.

The futureโ€‹

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!

Announcing pricing for company licenses

ยท One min read
Jonny Burger
Indie Hacker

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!

Remotion Pricing

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!

Remotion 1.5

ยท 3 min read
Jonny Burger
Indie Hacker

This release contains no big new features, but addresses some common problems.

No Chromium download necessaryโ€‹

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.

Improved Apple Silicon and WSL supportโ€‹

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.

Smoother timelineโ€‹

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.

Failing to render a frame fails hardโ€‹

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.

Rendering will happen on a localhost serverโ€‹

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.

New tutorial: Programmatic Instagram Storiesโ€‹

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.

Upgradeโ€‹

As always, you can upgrade to the newest version by running npm run upgrade in your Remotion project.

Remotion 1.4

ยท 6 min read
Jonny Burger
Indie Hacker

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.

Support for HEVC and WebM codecsโ€‹

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.

Transparent videosโ€‹

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.

New random() APIโ€‹

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
export const MyComp = () => {
// โš ๏ธ Bug! Random values will change during render
const [particles] = useState(() => {
return new Array(100).fill(true).map(() => ({
x: Math.random(),
y: Math.random(),
}));
});
};
tsx
export const MyComp = () => {
// โš ๏ธ Bug! Random values will change during render
const [particles] = useState(() => {
return new Array(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";
 
export const MyComp = () => {
// โœ… Pseudo-random values that will be same across threads
const [particles] = useState(() => {
return new Array(100).fill(true).map((_, idx) => ({
x: random(`x-${idx}`),
y: random(`y-${idx}`),
}));
});
};
tsx
import { useState } from "react";
import { random } from "remotion";
 
export const MyComp = () => {
// โœ… Pseudo-random values that will be same across threads
const [particles] = useState(() => {
return new Array(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.

More configuration optionsโ€‹

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.

Keyboard controls in the editorโ€‹

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.

keyboard-support.gif

Progress bar for stitching frames togetherโ€‹

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!

stitching-progress.png

New layout prop for <Sequence>โ€‹

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.

Asynchronously determining composition metadataโ€‹

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:

tsx
export const RemotionVideo: React.FC = () => {
const [videoLength, setVideoLength] = useState(null)
useEffect(() => {
const handle = delayRender();
determineVideoLength()
.then((duration) => {
setVideoLength(duration)
continueRender(handle)
})
.catch(err => /**/)
}, [])
if (videoLength === null) {
return null;
}
return (
<>
<Composition
id="HelloWorld"
component={HelloWorld}
durationInFrames={videoLength}
fps={30}
width={1920}
height={1080}
/>
</>
)
}
tsx
export const RemotionVideo: React.FC = () => {
const [videoLength, setVideoLength] = useState(null)
useEffect(() => {
const handle = delayRender();
determineVideoLength()
.then((duration) => {
setVideoLength(duration)
continueRender(handle)
})
.catch(err => /**/)
}, [])
if (videoLength === null) {
return null;
}
return (
<>
<Composition
id="HelloWorld"
component={HelloWorld}
durationInFrames={videoLength}
fps={30}
width={1920}
height={1080}
/>
</>
)
}

Stay tuned for a new API that will allow you to measure video and audio duration!

End to End tests for Windows, macOS and Ubuntuโ€‹

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.

ESLint rule for wrong asset importโ€‹

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
<Img src={hi} />
// โš ๏ธ Warning since 1.4: Import the asset instead
<Img src="./hi.png"/>
tsx
import {Img} from 'remotion';
import hi from './hi.png';
// โœ… Correct: Using an import statement
<Img src={hi} />
// โš ๏ธ Warning since 1.4: Import the asset instead
<Img src="./hi.png"/>

Paying top contributorsโ€‹

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!

Various improvementsโ€‹

Up next...โ€‹

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.

Remotion 1.3

ยท 4 min read
Jonny Burger
Indie Hacker

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.

2x faster - again!โ€‹

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.

Plain-Javascript supportโ€‹

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 ๐Ÿ™ˆ

Type-safe configuration fileโ€‹

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:

tsx
import os from "os";
import { Config } from "remotion";
Config.Rendering.setConcurrency(os.cpus().length);
Config.Output.setOverwriteOutput(true);
tsx
import os from "os";
import { Config } from "remotion";
Config.Rendering.setConcurrency(os.cpus().length);
Config.Output.setOverwriteOutput(true);

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.

Easing APIโ€‹

While there was an Easing API, it was undocumented. Learn which Easing methods are available and how to use it with interpolate()!

tsx
import { Easing, interpolate } from "remotion";
interpolate(frame, [0, 100], {
easing: Easing.bezier(0.8, 0.22, 0.96, 0.65),
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});
tsx
import { Easing, interpolate } from "remotion";
interpolate(frame, [0, 100], {
easing: Easing.bezier(0.8, 0.22, 0.96, 0.65),
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});

The small thingsโ€‹

In case you missed itโ€‹

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.

Remotion 1.2

ยท 2 min read
Jonny Burger
Indie Hacker

You have tested Remotion and provided an enormous amount of feedback! Thanks to it, this version of Remotion is vastly improved ๐ŸŽ‰

Rendering time cut in half!โ€‹

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.

Now that the rendering process is JPEG-based, a new flag --quality was added to command line. For server-side rendering, you may pass in a new imageFormat option. If you render a PNG sequence, Remotion will of course still deliver PNGs.

The goal is to make rendering even faster, finding further optimizations is going to be a very interesting task!

Windows supportโ€‹

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!

Discord communityโ€‹

We now have a Discord! Join now and chat about Remotion!

Licensing now availableโ€‹

The terms of the company license have now been worked out and a billing system with Stripe has been set up. Contact me for pricing!

Roadmapโ€‹

A GitHub Project board has been setup with the goal of indicating the next priorities. Check it out!

Miscellaneousโ€‹