I am attempting to use an AWS Lambda FFMPEG layer to build a timelapse of static images in an S3 bucket. To begin, I am basing my project off of the tutorial located here.
I can replicate the steps in the tutorial, so I know the FFMPEG layer is working in Lambda. I have replicated the FFMPEG commands on a standalone server, so I know they are correct.
Here is my setup: I have two S3 buckets, lambda-source-bucket and lambda-destination-bucket. The contents of lambda-source-bucket are:
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
files.txt
The files.txt contains this:
file 'https://lambda-source-bucket.s3.us-west-2.amazonaws.com/1.jpg'
file 'https://lambda-source-bucket.s3.us-west-2.amazonaws.com/2.jpg'
file 'https://lambda-source-bucket.s3.us-west-2.amazonaws.com/3.jpg'
file 'https://lambda-source-bucket.s3.us-west-2.amazonaws.com/4.jpg'
file 'https://lambda-source-bucket.s3.us-west-2.amazonaws.com/5.jpg'
file 'https://lambda-source-bucket.s3.us-west-2.amazonaws.com/6.jpg'
file 'https://lambda-source-bucket.s3.us-west-2.amazonaws.com/7.jpg'
This is my Lambda function code (in Python):
import json
import os
import subprocess
import shlex
import boto3
S3_DESTINATION_BUCKET = "lambda-destination-bucket"
SIGNED_URL_TIMEOUT = 60
def lambda_handler(event, context):
s3_source_bucket = event['Records'][0]['s3']['bucket']['name']
s3_source_key = event['Records'][0]['s3']['object']['key']
s3_source_basename = os.path.splitext(os.path.basename(s3_source_key))[0]
s3_destination_filename = "timelapse.mp4"
s3_client = boto3.client('s3')
s3_source_signed_url = s3_client.generate_presigned_url('get_object',
Params={'Bucket': s3_source_bucket, 'Key': s3_source_key},
ExpiresIn=SIGNED_URL_TIMEOUT)
ffmpeg_cmd = "/opt/bin/ffmpeg -y -r 24 -f concat -safe 0 -protocol_whitelist file,http,tcp,https,tls -I ""https://lambda-source-bucket.s3.us-west-2.amazonaws.com/files.txt"" -c copy -s 1024x576 -vcodec libx264 -"
command1 = shlex.split(ffmpeg_cmd)
p1 = subprocess.run(command1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
resp = s3_client.put_object(Body=p1.stdout, Bucket=S3_DESTINATION_BUCKET, Key=s3_destination_filename)
return {
'statusCode': 200,
'body': json.dumps('Processing complete successfully')
}
The trigger for the Lambda function is when a new files.txt file is added to lambda-source-bucket.
So far I have been able to get the trigger to fire, the function supposedly runs without errors (in Cloudwatch), and the function creates a new timelapse.mp4 in the lambda-destination-bucket. But this file is 0 bytes. I see no FFMPEG errors in the Cloudwatch console, though I am not sure I know how to configure my Lambda function code to log FFMPEG errors.
Also: if I'm going about this in a totally wrong way, I'd love to hear feedback. I'm guessing that the concat and files.txt method of looping through https:// is not the most efficient way to do this, but it's the only way I can figure this out so far.
Any help is most sincerely and humbly appreciated.