Run FFmpeg in AWS Lambda for Video Transcoding
Running FFmpeg on AWS Lambda allows you to perform cost-effective, scalable, and serverless video transcoding without managing dedicated servers. This article provides a straight-to-the-point guide on how to run FFmpeg within AWS Lambda, covering binary preparation, deployment via Lambda Layers, and executing transcoding commands using Python.
Step 1: Obtain a Compatible FFmpeg Binary
AWS Lambda runs on Amazon Linux. You need a static FFmpeg binary compiled for the Lambda execution environment (typically x86_64 or ARM64).
- Download a trusted static Linux build of FFmpeg (such as the builds by John Van Sickle).
- Ensure you match the architecture of your Lambda function (e.g.,
amd64for x86_64 orarm64for Graviton2).
Step 2: Package FFmpeg as an AWS Lambda Layer
Lambda Layers are the easiest way to share binaries across multiple functions.
Create a directory structure locally:
mkdir -p ffmpeg-layer/binCopy your downloaded
ffmpegandffprobeexecutables into theffmpeg-layer/bin/directory.Ensure the binaries have execution permissions:
chmod +x ffmpeg-layer/bin/ffmpeg ffmpeg-layer/bin/ffprobeCompress the folder into a ZIP file:
cd ffmpeg-layer zip -r ../ffmpeg-layer.zip bin/Upload
ffmpeg-layer.zipto AWS Lambda as a Layer via the AWS Console or AWS CLI.
When the layer is attached to your Lambda function, the binaries will
be available at /opt/bin/ffmpeg.
Step 3: Write the Lambda Function Code
AWS Lambda’s root filesystem is read-only, except for the
/tmp directory. You must download the source video to
/tmp, perform the transcoding, and then upload the output
back to Amazon S3.
Here is an example Lambda function written in Python:
import os
import subprocess
import boto3
s3_client = boto3.client('s3')
def lambda_handler(event, context):
# Retrieve bucket and key from S3 trigger event
bucket = event['Records'][0]['s3']['bucket']['name']
key = event['Records'][0]['s3']['object']['key']
# Define local file paths in /tmp
input_path = f"/tmp/{os.path.basename(key)}"
output_filename = f"transcoded_{os.path.basename(key)}"
output_path = f"/tmp/{output_filename}"
# 1. Download file from S3
s3_client.download_file(bucket, key, input_path)
# 2. Run FFmpeg command
# Using /opt/bin/ffmpeg added by the Lambda Layer
ffmpeg_cmd = [
"/opt/bin/ffmpeg",
"-y", # Overwrite output files without asking
"-i", input_path, # Input file
"-vcodec", "h264", # Transcode to H.264
"-acodec", "aac", # Transcode audio to AAC
output_path # Output file
]
try:
subprocess.run(ffmpeg_cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e:
print(f"FFmpeg error: {e.stderr.decode('utf-8')}")
raise e
# 3. Upload transcoded file back to S3
destination_key = f"transcoded/{output_filename}"
s3_client.upload_file(output_path, bucket, destination_key)
# Cleanup /tmp to avoid storage overflow on warm starts
os.remove(input_path)
os.remove(output_path)
return {
'statusCode': 200,
'body': f"Successfully transcoded and uploaded to {destination_key}"
}Step 4: Configure Lambda Execution Settings
To handle video transcoding successfully, you must adjust the default AWS Lambda resource limits:
- Memory: Allocate at least 2048 MB. FFmpeg is CPU-intensive, and AWS scales CPU power proportionally to the allocated memory.
- Timeout: Increase the timeout to handle larger files (up to the maximum limit of 15 minutes).
- Ephemeral Storage (/tmp): By default, Lambda
provides 512 MB of
/tmpstorage. If you are transcoding large video files, increase this storage limit (up to 10 GB) in the Configuration tab. - Execution Role: Ensure the Lambda execution role
has
s3:GetObjectpermissions for the input bucket ands3:PutObjectpermissions for the destination bucket.