Skip to main content

v4.0 Migration

When upgrading from Remotion 3 to Remotion 4, note the following changes and apply them to your project.

How to upgrade

See the changelog to find the latest version. Upgrade remotion and all packages starting with @remotion to the latest version, e.g. 4.0.0:

diff
- "remotion": "^3.3.43"
- "@remotion/bundler": "^3.3.43"
- "@remotion/eslint-config": "^3.3.43"
- "@remotion/eslint-plugin": "^3.3.43"
- "@remotion/cli": "^3.3.43"
- "@remotion/renderer": "^3.3.43"
+ "remotion": "4.0.0"
+ "@remotion/bundler": "4.0.0"
+ "@remotion/eslint-config": "4.0.0"
+ "@remotion/eslint-plugin": "4.0.0"
+ "@remotion/cli": "4.0.0"
+ "@remotion/renderer": "4.0.0"
diff
- "remotion": "^3.3.43"
- "@remotion/bundler": "^3.3.43"
- "@remotion/eslint-config": "^3.3.43"
- "@remotion/eslint-plugin": "^3.3.43"
- "@remotion/cli": "^3.3.43"
- "@remotion/renderer": "^3.3.43"
+ "remotion": "4.0.0"
+ "@remotion/bundler": "4.0.0"
+ "@remotion/eslint-config": "4.0.0"
+ "@remotion/eslint-plugin": "4.0.0"
+ "@remotion/cli": "4.0.0"
+ "@remotion/renderer": "4.0.0"

Run npm i , yarn or pnpm i respectively afterwards.

System requirements

The minimum Node version is now 16.0.0.

Only the following platforms are supported: Windows (x64 only), macOS, Linux.

Linux distros with glibc need to have at least version 2.35. See here for more information.

Config file changes

The CLI configuration file has been moved out from the core Remotion package to @remotion/cli/config. Update your imports like this:

diff
- import {Config} from 'remotion';
+ import {Config} from '@remotion/cli/config';
diff
- import {Config} from 'remotion';
+ import {Config} from '@remotion/cli/config';

The options have been flattened. For example, instead of Config.Bundling.overrideWebpackConfig, you now use Config.overrideWebpackConfig.

diff
- Config.Bundling.overrideWebpackConfig()
+ Config.overrideWebpackConfig()
- Config.Output.setOverwriteOutput(true);
+ Config.setOverwriteOutput(true);
diff
- Config.Bundling.overrideWebpackConfig()
+ Config.overrideWebpackConfig()
- Config.Output.setOverwriteOutput(true);
+ Config.setOverwriteOutput(true);

Apply this to all configuration calls.

Separating ImageFormat

Previously, the imageFormat option would be used for both stills and videos. While for stills, PNG is often preferrable, for videos it is overall faster to use JPEG as a default. In Remotion 4.0, the image formats are being separated so you can set defaults for videos and stills separately.

diff
- Config.setImageFormat('jpeg');
+ Config.setVideoImageFormat('jpeg');
diff
- Config.setImageFormat('jpeg');
+ Config.setVideoImageFormat('jpeg');
  • The CLI option is still --image-format for all commands.
  • The Node.JS API name is still imageFormat.
  • The TypeScript type ImageFormat has been separated into StillImageFormat and VideoImageFormat.
  • StillImageFormat now also supports webp and pdf!

Streamlined logging

For getCompositions(), renderMedia(), renderStill(), getCompositionsOnLambda(), renderMediaOnLambda() and renderStillOnLambda():

verbose and dumpBrowserLogs have been deprecated in favor of "logLevel": "verbose". This makes the options equivalent to the CLI options.

Dropped support for Lambda architecture

When deploying a Lambda, you were previously able to choose between the arm64 and x86_64 architecture.
From v4.0 on, only arm64 is supported. It should be faster, cheaper and not have any different behavior than x86_64.

How to upgrade:

  • Remove the architecture option from estimatePrice() and deployFunction().

Rich timeline removed

The option to use the "Rich timeline" has been removed due to performance problems.
The timeline is now always in simple mode, but supports more timeline layers at once.

ProRes videos now export uncompressed audio by default

Previously, the aac audio codec was the default for ProRes exports. The default is now pcm_s16le which stands for uncompressed 16-bit low-endian PCM audio.
This change was made since users export ProRes mainly for getting high-quality footage to be further used in video editing programs.

Renamed quality option to jpegQuality

To clarify the meaning of this option, it is now universally called "JPEG Quality". Adjust the following options:

No more FFmpeg install, ffmpegExecutable option removed

FFmpeg is now baked into the @remotion/renderer package. Therefore, the ffmpegExecutable and ffprobeExecutable options have been removed.

Furthermore, the npx remotion install ffmpeg and npx remotion install ffprobe commands no longer exist.

How to upgrade:

Added npx remotion ffmpeg and npx remotion ffprobe

Since FFmpeg and FFprobe no longer have to be installed, the ffmpeg and ffprobe commands might also not be in your environment anymore. In order to still be able to use some of FFmpeg's handy commands, we introduced npx remotion ffmpeg and npx remotion ffprobe. Note that in order to keep the binary size small, those FFmpeg binaries only understand the codecs that Remotion itself supports: H.264, H.265, VP8, VP9 and ProRes.

A binary from the 6.0 release line of FFmpeg is used.

Moved onSlowestFrames API

In V3, onSlowestFrames has been a callback function that you could pass to renderMedia().
In V4, this data has been moved to the return value.

ImageFormat removed

The @remotion/renderer ImageFormat Type got replaced by the more specific Types VideoImageFormat and StillImageFormat.

Removal of deprecated APIs

  • Config.setOutputFormat() was deprecated in v1.4 and has now been removed. Use setImageSequence(), setVideoImageFormat() and setCodec() in combination instead.

  • downloadVideo() alias has been removed, use downloadMedia() with the same API instead.

  • <MotionBlur> has been removed. Use <Trail> instead.

  • getParts() has been removed. Use getSubpaths() instead:

paths.ts
tsx
import {
getLength,
getPointAtLength,
getSubpaths,
getTangentAtLength,
} from "@remotion/paths";
 
const path = "M 0 0 L 100 100";
const parts = getSubpaths(path[0]);
const length = getLength(parts[0]);
const start = getPointAtLength(parts[0], 0);
const end = getPointAtLength(parts[0], length);
const tangent = getTangentAtLength(parts[0], length / 2);
paths.ts
tsx
import {
getLength,
getPointAtLength,
getSubpaths,
getTangentAtLength,
} from "@remotion/paths";
 
const path = "M 0 0 L 100 100";
const parts = getSubpaths(path[0]);
const length = getLength(parts[0]);
const start = getPointAtLength(parts[0], 0);
const end = getPointAtLength(parts[0], length);
const tangent = getTangentAtLength(parts[0], length / 2);
  • webpackBundle has been removed from renderFrames() and renderMedia() - rename it to serveUrl instead
  • parallelism has been removed from renderFrames() and renderMedia() - rename it to concurrency instead.
  • config has been removed from renderFrames() - rename it to composition instead.

onBucketEnsured option has been removed

The onBucketEnsured() option of getOrCreateBucket() has been removed because creating the bucket is the only operation of getOrCreateBucket(). Therefore, you can just await the function itself.

imageFormat removed from <OffthreadVideo>

Until now, you could optionally pass the imageFormat prop into <OffthreadVideo>. This option was introduced in order to make transparent videos possible.

Now, you can instead use the optional transparent prop.

Due to this this change, the OffthreadVideoImageFormat type is no longer neccessary and has therefore been removed.

OffthreadVideoImageFormat removed

<Img> will cancel the render if the image cannot be loaded

Before, <Img> would only log to the console if an image cannot be loaded and inevitably lead to a timeout if the error is not handled.

If this happens now and the error is not handled, the render will be aborted and the error reported.

crf is not allowed for GIFs anymore

Previously you were able to set a value for crf when rendering a GIF. This was a mistake and GIF does not support them.

staticFile() URI-unsafe characters handling

Previously, staticFile() did not handle URI-unsafe characters contained in the provided path:

Before v4
tsx
staticFile("my-image#portrait.png"); //output: "my-image#portrait.png"
Before v4
tsx
staticFile("my-image#portrait.png"); //output: "my-image#portrait.png"

This could lead to problems, when unsafe characters such as #, ? and & were part of the filename.

Now, staticFile() encodes the filename using encodeURIComponent:

Since v4.0.0
tsx
staticFile("my-image#portrait.png"); // "my-image%23portrait.png"
Since v4.0.0
tsx
staticFile("my-image#portrait.png"); // "my-image%23portrait.png"

Type WebpackOverrideFn moved

The WebpackOverrideFn type useful for overriding the Webpack config in the config file and in bundle() has moved from the remotion to the @remotion/bundler package.

How to upgrade:

If you encoded the path by yourself until now, don't do so anymore to avoid double encoding.

react-native no longer aliases to react-native-web

Remotion no longer aliases react-native automatically to react-native-web.
If you are using react-native-web, override the Webpack config like this to restore the previous behavior:

remotion.config.ts
ts
import { Config } from "@remotion/cli/config";
 
Config.overrideWebpackConfig((config) => {
return {
...config,
resolve: {
...config.resolve,
alias: {
...config.resolve?.alias,
"react-native$": "react-native-web",
},
},
};
});
remotion.config.ts
ts
import { Config } from "@remotion/cli/config";
 
Config.overrideWebpackConfig((config) => {
return {
...config,
resolve: {
...config.resolve,
alias: {
...config.resolve?.alias,
"react-native$": "react-native-web",
},
},
};
});

The @remotion/skia package does not require react-native or react-native-web anymore.

The TComposition type now includes a Zod schema

The TComposition type now has two generic arguments:

ts
export type TComposition<Schema extends AnyZodObject, Props> = {};
ts
export type TComposition<Schema extends AnyZodObject, Props> = {};

If you need a type for a generic composition, you can use the new AnyComposition type:

ts
import { AnyComposition } from "remotion";
const composition: AnyComposition = {
width: 1920,
height: 1080,
// ...
};
ts
import { AnyComposition } from "remotion";
const composition: AnyComposition = {
width: 1920,
height: 1080,
// ...
};

getCanExtractFramesFast() function has been removed

The getCanExtractFramesFast() function has been removed, since frames can always be extracted fast now using <OffthreadVideo>.

How to upgrade:

You can now remove your re-encoding logic!

Input props must be an object

Since the input props are passed to a React component, they must not explicitly be objects ({}). You can still use other data structures such as arrays, but they must be wrapped in an object.

Cannot use an interface for props

The following code now gives a type error:

tsx
interface MyProps {
title: string;
}
const Hi = (props: MyProps) => {
return <div>{props.title}</div>;
};
<Still
component={Hi}
id="interface-props"
defaultProps={{ title: "hi" }}
height={1080}
width={1080}
/>;
tsx
interface MyProps {
title: string;
}
const Hi = (props: MyProps) => {
return <div>{props.title}</div>;
};
<Still
component={Hi}
id="interface-props"
defaultProps={{ title: "hi" }}
height={1080}
width={1080}
/>;

This is because props must now be an object and satisfy the shape Record<string, unknown>.
interface's do not satisfy this shape, so you must use a type instead:

tsx
type MyProps = {
title: string;
};
tsx
type MyProps = {
title: string;
};

See also: Input props must be an object

defaultProps is required if the component has props

If you register a composition with a component that requires some props, you now are required to provide a defaultProps object.

inputProps option of renderMedia() now works differently

renderMedia() accepts a VideoConfig object for the composition option, which now has a props field:

tsx
await renderMedia({
...options,
composition: {
...composition,
props: {
title: "Hello world",
},
},
inputProps: {
title: "Hi there",
},
});
tsx
await renderMedia({
...options,
composition: {
...composition,
props: {
title: "Hello world",
},
},
inputProps: {
title: "Hi there",
},
});

The composition.props are now the effective props that get passed to the component, while inputProps are what can be retrieved using getInputProps().

Previously, inputProps would override the default props and be passed to the component.

The recommended way is to get the composition object using selectComposition() or getCompositions(). However, for the purpose of starting renders faster, the composition object may be constructed manually.

Changelog

  • remotion: defaultProps of a <Composition> is now mandatory if the component accepts props
  • remotion: <Composition> now accepts a schema
  • remotion: <Composition> now accepts a calculateMetadata prop
  • remotion: The OffthreadVideoImageFormat type has been removed.
  • remotion: imageFormat has been removed from <OffthreadVideo>
  • remotion: transparent has been added to <OffthreadVideo>.
  • remotion: <Img> will cancel the render if the image cannot be loaded
  • remotion: If an <Audio> tag cannot be loaded, it will cancel the render.
  • remotion: The TComposition type now requires a Zod schema as a generic.
  • remotion: Type WebpackOverrideFn moved from remotion to @remotion/bundler
  • remotion: staticFile() now supports URI-unsafe characters by default
  • remotion: Types: src is required for an <Img> tag
  • @remotion/bundler: The development Webpack cache will not be removed anymore if setting --bundle-cache=false.
  • @remotion/bundler: react-native no longer aliases to react-native-web
  • @remotion/bundler: Webpack has been upgraded to 5.83.1
  • @remotion/cli: npx remotion preview is deprecated for npx remotion studio
  • @remotion/cli: New Props editor allows for editing props with schema
  • @remotion/cli: New Render button allows for rendering through the CLI
  • @remotion/cli: New npx remotion ffmpeg command
  • @remotion/cli: New npx remotion ffprobe command
  • @remotion/cli: Configuration logic has been moved to @remotion/cli/config
  • @remotion/cli: Rich timeline was removed.
  • @remotion/cli: Config.*.setOption() syntax has been removed.
  • @remotion/cli: Config.setOutputFormat() has now been removed.
  • @remotion/cli: Studio now has custom dark scrollbars
  • @remotion/cli: New logger for verbose mode: No more interlacing between logs and progress bars
  • @remotion/cli: New indicator whether a file has been overwritten () or newly created (+)
  • @remotion/cli: Printing server URL again to the console if all Studio instances have been closed
  • @remotion/cli: Less React re-renders across the Remotion Studio
  • @remotion/cli: Dropdowns cannot overflow anymore
  • @remotion/cli: New shortcut for collapsing left sidebar: Cmd/Ctrl+B
  • @remotion/cli Allow open of the project in editor from the Remotion Studio
  • @remotion/cli: Date objects now work properly in defaultProps
  • @remotion/cli: Remotion Studio is tested to work well offline.
  • @remotion/cli: "Remotion Preview" has been renamed to "Remotion Studio"
  • @remotion/eslint-config: eslint-plugin-react has been updated to 7.32.2
  • @remotion/eslint-config: eslint-plugin-react-hooks has been updated to 4.6.0
  • @remotion/eslint-plugin: New ESLint rule: Use the right import in the config file
  • @remotion/lambda: Lambda does not support the x86 architecture anymore
  • @remotion/lambda: Chrome on Lambda has been updated to 114
  • @remotion/lambda: downloadVideo() alias has been removed.
  • @remotion/lambda: estimatePrice() does not accept architecture anymore.
  • @remotion/lambda: Removed FFmpeg from the Lambda Layer.
  • @remotion/motion-blur: <MotionBlur> has been removed
  • @remotion/paths: getParts() has been removed
  • @remotion/renderer: New selectComposition() API
  • @remotion/renderer: getCanExtractFramesFast() has been removed
  • @remotion/renderer: FFmpeg is now included in Remotion (v6.0), no need to install it anymore
  • @remotion/renderer: ProRes now exports uncompressed audio by default.
  • @remotion/renderer: onSlowestFrames has been removed
  • @remotion/renderer: renderMedia() now returns an object instead of a Buffer.
  • @remotion/renderer: The ImageFormat type has been removed in favor of StillImageFormat and VideoImageFormat
  • @remotion/renderer: You can now export stills as PDF or WebP
  • @remotion/renderer: quality is now jpegQuality
  • @remotion/renderer: Removed ensureFfmpeg() and ensureFfprobe()
  • @remotion/renderer: <OffthreadVideo> now uses a Rust-based frame extractor
  • @remotion/renderer: Noisy Chrome messages are filtered out.
  • @remotion/renderer: console.log statements in your React app now get printed in a tidy format, contain location, use colors and object previews are printed out.
  • @remotion/zod-types: New package!
  • Only the following platforms are supported by Remotion now: macOS (x64 and arm64), Windows (x64), Linux (x64 and ARM, GNU Libc and MUSL)
  • All packages: The minimum Node version is now 16.0.0
  • All packages: ESLint has been upgraded to 8.42.0
  • All packages: TypeScript ESLint has been upgraded to 5.59.9
  • All packages: ESBuild has been updated to 0.18.6
  • For contributors: Updated pnpm to 8.5.1
  • For contributors: Doc snippets failing typechecks now show the failing code in CI
  • New Google TTS template!
  • Recommended Docker file does not install ffmpeg anymore