Skip to main content

Custom Layers

The Lambda function includes FFMPEG, Chrome and base fonts by default.

In some advanced use cases, you want to replace certain parts of the stack:

  • Use another Chrome version (binaries can be obtained from chromiumforlambda.com)
  • Replace default fonts or emojis (such as Apple Emoji font)

Before you create a custom stack, feel free to contact us to see if Remotion can provide the changes upstream.

Also consider that the AWS Lambda layers may not exceed 250MB extracted, so you need to sacrifice an equal amount of other files.

If you just want to add fonts, we recommend to use Web fonts instead.

Ensure Remotion version

Customizing Remotion Lambda Layers is possible from v3.0.17.
Lambda binaries might change in minor Remotion versions, it is your responsibility to keep your versions up to date.

Creating a custom binary

Go to the remotion-dev/lambda-binaries repository and clone it.

The folders chromium, ffmpeg and fonts contain the binaries for the ARM version.
The folders chromium-x64, ffmpeg-x64 and fonts-x64 contain the binaries for the x86_64 version of Lambda. The default and recommended version is the ARM one.

Put the files that you want in the corresponding folders - for example, add the Apple Emoji Font AppleColorEmoji.ttf into the fonts/.fonts/NotoSans/ folder.

Since the AWS Lambda layers may not exceed 250MB extracted, we need to sacrifice an equal amount of other files - for example by removing fonts/.fonts/NotoColorEmoji.ttf and fonts/.fonts/NotoSansCJKjp-Regular.otf.

You can see the size of the folders by running:

bash
sh size.sh
bash
sh size.sh

If you are done with your changes, run:

bash
sh make.sh
bash
sh make.sh

This will zip the layers and put them as artifacts in the out directory.

Creating a Lambda layer

  • Go to your AWS console, select the Lambda product, then select "Layers":
  • Select "Create layer" and fill out the name. Upload the created layer from the out folder into the form. The fields "Compatible architectures", "Compatible runtimes" and "License" are optional.

  • Once the layer is created, you will get a version ARN (example: arn:aws:lambda:us-east-1:123456789012:layer:apple-emoji:1). Copy it.

note

You need to do this for every AWS region you want to use Remotion Lambda in.

Update the Lambda function

Before you continue, make sure a Remotion Lambda function is deployed.

To switch out the layer of a deployed Lambda function, you can either do it via the AWS console or use a Node.JS script that you can run after every function deploy.

Before you can update a function via the Node.JS APIs, you need to add another rule to your user role:

json
[
{
"Sid": "UpdateFunction",
"Effect": "Allow",
"Action": [
"lambda:GetFunctionConfiguration",
"lambda:UpdateFunctionConfiguration"
],
"Resource": ["arn:aws:lambda:*:*:function:remotion-render-*"]
},
{
"Sid": "GetOwnLayerVersion",
"Effect": "Allow",
"Action": ["lambda:GetLayerVersion"],
"Resource": ["*"]
}
]
json
[
{
"Sid": "UpdateFunction",
"Effect": "Allow",
"Action": [
"lambda:GetFunctionConfiguration",
"lambda:UpdateFunctionConfiguration"
],
"Resource": ["arn:aws:lambda:*:*:function:remotion-render-*"]
},
{
"Sid": "GetOwnLayerVersion",
"Effect": "Allow",
"Action": ["lambda:GetLayerVersion"],
"Resource": ["*"]
}
]

Given a region, function name, layer to remove and layer to add, you can use the following snippet to update a function with custom layers

ts
import { AwsRegion, getAwsClient } from "@remotion/lambda";
// Customize these parameters
const REGION: AwsRegion = "us-east-1";
const FUNCTION_NAME = "remotion-render-2022-06-02-mem3000mb-disk2048mb-120sec";
const LAYER_TO_REMOVE = /fonts/;
const LAYER_TO_ADD = "arn:aws:lambda:us-east-1:1234567891:layer:apple-emoji:1";
const { client, sdk } = getAwsClient({
region: REGION,
service: "lambda",
});
const fnConfig = await client.send(
new sdk.GetFunctionConfigurationCommand({
FunctionName: FUNCTION_NAME,
})
);
if (!fnConfig) {
throw new Error(`Function ${FUNCTION_NAME} not deployed`);
}
await client.send(
new sdk.UpdateFunctionConfigurationCommand({
FunctionName: FUNCTION_NAME,
Layers: [
...(fnConfig.Layers ?? [])
.filter((l) => !l.Arn?.match(LAYER_TO_REMOVE))
.map((l) => l.Arn as string),
LAYER_TO_ADD,
],
})
);
ts
import { AwsRegion, getAwsClient } from "@remotion/lambda";
// Customize these parameters
const REGION: AwsRegion = "us-east-1";
const FUNCTION_NAME = "remotion-render-2022-06-02-mem3000mb-disk2048mb-120sec";
const LAYER_TO_REMOVE = /fonts/;
const LAYER_TO_ADD = "arn:aws:lambda:us-east-1:1234567891:layer:apple-emoji:1";
const { client, sdk } = getAwsClient({
region: REGION,
service: "lambda",
});
const fnConfig = await client.send(
new sdk.GetFunctionConfigurationCommand({
FunctionName: FUNCTION_NAME,
})
);
if (!fnConfig) {
throw new Error(`Function ${FUNCTION_NAME} not deployed`);
}
await client.send(
new sdk.UpdateFunctionConfigurationCommand({
FunctionName: FUNCTION_NAME,
Layers: [
...(fnConfig.Layers ?? [])
.filter((l) => !l.Arn?.match(LAYER_TO_REMOVE))
.map((l) => l.Arn as string),
LAYER_TO_ADD,
],
})
);

See also