cyberangles blog

How to Generate Video in AWS Lambda Using MoviePy, SciPy, and NumPy: A Step-by-Step Setup Guide

AWS Lambda has revolutionized serverless computing, enabling developers to run code without provisioning or managing servers. While Lambda is ideal for lightweight, event-driven tasks (e.g., API endpoints, data processing), it’s often overlooked for video generation—a task traditionally requiring heavy compute resources.

In this guide, we’ll show you how to leverage Lambda’s flexibility to generate dynamic videos using three powerful Python libraries:

  • MoviePy: A video editing library for creating/modifying videos (e.g., trimming, adding text, combining clips).
  • NumPy: For numerical operations to generate video frames (e.g., gradients, patterns).
  • SciPy: For advanced scientific computations (e.g., applying filters, noise reduction).

By the end, you’ll deploy a Lambda function that generates a custom video and saves it to Amazon S3. We’ll tackle key challenges like packaging large dependencies (e.g., ffmpeg, required by MoviePy) and optimizing Lambda’s constraints (e.g., memory, timeout).

2026-02

Table of Contents#

  1. Prerequisites
  2. Understanding the Tools
  3. Step 1: Set Up Your AWS Lambda Environment
  4. Step 2: Handle Dependencies (The Tricky Part!)
  5. Step 3: Write the Video Generation Code
  6. Step 4: Deploy and Test the Lambda Function
  7. Step 5: Troubleshoot Common Issues
  8. Conclusion
  9. References

Prerequisites#

Before starting, ensure you have:

  • An AWS account.
  • Basic familiarity with AWS Lambda, IAM roles, and Amazon S3.
  • Python 3.8+ installed locally (for testing code).
  • AWS CLI configured with permissions to create Lambda functions, IAM roles, and S3 buckets.

1. Understanding the Tools#

Let’s briefly break down why we’re using these libraries:

MoviePy#

MoviePy simplifies video editing with a high-level API. It can generate videos from scratch (e.g., using NumPy arrays as frames) or modify existing clips. It relies on ffmpeg (a multimedia framework) for encoding/decoding videos, so we’ll need to package ffmpeg with our Lambda function.

NumPy#

NumPy is the backbone of scientific computing in Python. We’ll use it to generate raw video frames as numerical arrays (e.g., a gradient background or pixel patterns).

SciPy#

SciPy extends NumPy with advanced algorithms. For video generation, we’ll use it to apply effects like blurring, edge detection, or noise to frames, enhancing visual appeal.

2. Step 1: Set Up Your AWS Lambda Environment#

First, we’ll configure the Lambda function, IAM permissions, and S3 bucket (to store output videos).

Lambda’s local storage (/tmp/) is ephemeral, so save generated videos to S3.

  1. Go to the AWS S3 Console.
  2. Click Create bucket.
  3. Enter a unique bucket name (e.g., lambda-video-generation-demo) and select a region (match your Lambda region for lower latency).
  4. Keep default settings and click Create bucket.

2.2 Create an IAM Role for Lambda#

Lambda needs permissions to write to S3 and log to CloudWatch.

  1. Go to the AWS IAM Console.
  2. Navigate to Roles > Create role.
  3. Under Trusted entity type, select AWS service > Lambda, then click Next.
  4. Attach the following policies:
    • AmazonS3FullAccess (restrict to your bucket later for security).
    • CloudWatchLogsFullAccess (for debugging).
  5. Name the role LambdaVideoGenerationRole and click Create role.

2.3 Create the Lambda Function#

  1. Go to the AWS Lambda Console.
  2. Click Create function > Author from scratch.
  3. Configure:
    • Function name: VideoGenerator.
    • Runtime: Python 3.9 (or latest compatible version).
    • Architecture: x86_64 (most dependencies are built for x86).
    • Role: Use an existing role > Select LambdaVideoGenerationRole.
  4. Click Create function.

2.4 Configure Lambda Settings#

Video generation is compute-intensive. Update these settings:

  1. In your Lambda function, go to Configuration > General configuration > Edit.
  2. Set Memory: 2048 MB (minimum for video tasks; adjust based on complexity).
  3. Set Timeout: 5 minutes (video generation may take time).
  4. Click Save.

3. Step 2: Handle Dependencies#

Lambda has strict limits: deployment packages must be ≤50 MB (zipped) and ≤250 MB (unzipped). MoviePy, SciPy, NumPy, and ffmpeg (a MoviePy dependency) are large, so we’ll package them carefully.

3.1 Key Dependencies to Package#

  • MoviePy: pip install moviepy
  • NumPy: pip install numpy
  • SciPy: pip install scipy
  • ffmpeg: A binary required by MoviePy to encode/decode videos.

3.2 Build Dependencies for Amazon Linux#

Lambda runs on Amazon Linux 2, so dependencies must be compiled for this OS. We’ll use a Docker container to simulate the Lambda environment and build the packages.

Step 3.2.1 Set Up a Docker Container#

  1. Install Docker if not already installed.
  2. Run an Amazon Linux 2 container to build dependencies:
    docker run -v $(pwd):/app -it amazonlinux:2023 /bin/bash  
    This mounts your local directory ($(pwd)) to /app in the container, so you can access built files later.

Step 3.2.2 Install Dependencies in the Container#

Inside the Docker container:

  1. Install Python and tools:
    yum update -y  
    yum install -y python3.9 python3.9-pip zip  
  2. Navigate to the mounted directory:
    cd /app  
  3. Create a requirements.txt file (or use the one from your project):
    echo -e "moviepy==1.0.3\nnumpy==1.26.0\nscipy==1.11.3" > requirements.txt  
  4. Install dependencies to a package folder:
    python3.9 -m pip install -r requirements.txt -t package/  

Step 3.2.3 Add ffmpeg to the Package#

MoviePy requires ffmpeg to process videos. Download the Amazon Linux-compatible ffmpeg binary:

  1. Inside the container, download ffmpeg (static build for Linux):
    cd package  
    curl -L https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amazonlinux2-x86_64.tar.xz | tar xJ --strip-components=1  
    This extracts ffmpeg directly into the package folder.

Step 3.2.4 Zip the Deployment Package#

Still inside the container, zip the package folder:

cd /app  
zip -r deployment_package.zip package/  

Exit the container:

exit  

4. Step 3: Write the Video Generation Code#

Now, create a Python script to generate a video using MoviePy, NumPy, and SciPy. We’ll generate a 10-second video with:

  • A dynamic gradient background (via NumPy).
  • A text overlay.
  • A Gaussian blur effect (via SciPy).

4.1 Create the Lambda Handler Code#

Create a file named lambda_function.py in your local directory (mounted to /app in Docker):

import os  
import numpy as np  
from scipy.ndimage import gaussian_filter  
from moviepy.editor import VideoClip, TextClip, CompositeVideoClip, AudioFileClip  
import boto3  
from io import BytesIO  
 
# Configure ffmpeg path (required for MoviePy)  
os.environ["FFMPEG_BINARY"] = "/var/task/package/ffmpeg"  
 
s3 = boto3.client("s3")  
 
def generate_video():  
    # Video parameters  
    duration = 10  # seconds  
    fps = 24  
    width, height = 1280, 720  
 
    # Generate gradient background with dynamic color shift  
    def make_frame(t):  
        # Create a vertical gradient (red to blue) with time-based color shift  
        gradient = np.linspace(0, 1, height)[:, None]  # Shape: (height, 1)  
        red = np.sin(t * 0.5) * 0.5 + 0.5  # Oscillate red channel over time  
        green = np.cos(t * 0.3) * 0.5 + 0.5  # Oscillate green channel  
        blue = gradient * 0.8  # Blue increases with height  
 
        # Combine into RGB frame (shape: height x width x 3)  
        frame = np.stack([  
            red * gradient * np.ones((height, width)),  
            green * (1 - gradient) * np.ones((height, width)),  
            blue * np.ones((height, width))  
        ], axis=2)  
 
        # Apply Gaussian blur (SciPy)  
        frame = gaussian_filter(frame, sigma=1)  
 
        # Normalize to 0-255 (8-bit)  
        frame = (frame * 255).astype(np.uint8)  
        return frame  
 
    # Create video clip from frame generator  
    video = VideoClip(make_frame, duration=duration)  
 
    # Add text overlay  
    text = TextClip(  
        "Lambda Video Generation",  
        fontsize=40,  
        color="white",  
        font="Arial-Bold"  
    ).set_position(("center", "center")).set_duration(duration)  
 
    # Combine video and text  
    final_video = CompositeVideoClip([video, text])  
 
    # Write video to /tmp (Lambda's only writable directory)  
    output_path = "/tmp/output.mp4"  
    final_video.write_videofile(  
        output_path,  
        fps=fps,  
        codec="libx264",  
        audio=False  # No audio for simplicity  
    )  
 
    # Upload to S3  
    s3.upload_file(  
        output_path,  
        "lambda-video-generation-demo",  # Replace with your bucket name  
        "generated_video.mp4"  
    )  
 
    return {"statusCode": 200, "body": "Video generated and saved to S3"}  
 
def lambda_handler(event, context):  
    return generate_video()  

4.2 Explanation of the Code#

  • Frame Generation: Uses NumPy to create a dynamic RGB gradient that shifts over time (t).
  • SciPy Blur: Applies gaussian_filter to smooth the frame.
  • MoviePy Pipeline: Combines the generated frames with a text overlay and encodes the video to MP4.
  • S3 Upload: Saves the video to your S3 bucket (Lambda’s /tmp is erased after execution).

5. Step 4: Deploy and Test the Lambda Function#

5.1 Package the Code with Dependencies#

Add lambda_function.py to the deployment package:

zip -g deployment_package.zip lambda_function.py  

5.2 Deploy the Package to Lambda#

  1. In the Lambda Console, go to your VideoGenerator function.
  2. Under Code > Code source > Upload from > .zip file, upload deployment_package.zip.

5.3 Test the Function#

  1. In the Lambda Console, click Test > Configure test event.
  2. Name the event TestEvent and use the default JSON (we don’t need input data).
  3. Click Test to run the function.

5.4 Verify the Output#

  • Check CloudWatch Logs: Go to Monitor > Logs to debug errors (e.g., missing dependencies, timeouts).
  • Check S3 Bucket: Navigate to your S3 bucket; you should see generated_video.mp4. Download it to confirm the video plays correctly.

6. Step 5: Troubleshooting Common Issues#

6.1 "ffmpeg Not Found" Error#

  • Cause: ffmpeg is missing or the path is incorrect.
  • Fix: Ensure ffmpeg is in the package folder and os.environ["FFMPEG_BINARY"] points to /var/task/package/ffmpeg.

6.2 Deployment Package Too Large#

  • Cause: Dependencies exceed Lambda’s 250 MB unzipped limit.
  • Fix: Use Lambda Layers to split dependencies (e.g., a layer for NumPy/SciPy, another for MoviePy/ffmpeg).

6.3 Timeout or Memory Errors#

  • Cause: Video generation is too slow or memory-intensive.
  • Fix: Increase Lambda memory (up to 10,240 MB) or timeout (up to 15 minutes). Simplify the video (lower resolution, shorter duration).

6.4 Missing Permissions#

  • Cause: Lambda role lacks S3 write access.
  • Fix: Update the IAM role to include s3:PutObject permissions for your bucket.

Conclusion#

You’ve successfully deployed an AWS Lambda function that generates videos using MoviePy, SciPy, and NumPy! This setup opens the door to dynamic video workflows: personalized marketing videos, data visualizations, or real-time video responses to events.

To scale further, consider:

  • Adding audio with AudioFileClip (MoviePy).
  • Using Lambda Layers for reusable dependencies.
  • Triggering the function via S3 events (e.g., generate a video when a CSV is uploaded).

References#