An In-Depth Guide for Deploying Ruby App to AWS Lambda

4 steps to deploy Ruby app to AWS Lambda: 1. Create a role for lambda; 2. Create the Lambda FFmpeg layer; 3. Create Lambda Function; 4. Extracting image code.

Deploying Ruby App to AWS Lambda

In this post, we will discuss implementing the AWS lambda function for processing uploaded content on S3. Suppose that we want to extract the images from video automatically every time the video is uploaded. We can implement the lambda function to do it.

We will use FFmpeg to process the video and use Ruby code for the lambda function. We will need two S3 buckets, one is the bucket where the videos are uploaded to. The other one is the bucket to store the extracted images.

>> Read more:

Step 1: Create A Role for Lambda

Lambda function will need access to the buckets to get the videos and upload the images after extracting them. So we create a role for it:

  • Open the Roles page in the IAM console.

  • Choose Create role.

  • Under Use case, choose Lambda.

  • Choose Next.

  • Select the AWS managed policies AmazonS3FullAccess, AWSLambdaBasicExecutionRole and AWSXRayDaemonWriteAccess.

  • Choose Next.

  • Enter a Role name and then choose Create role.

Step 2: Create the Lambda FFmpeg Layer

To use FFmpeg we will add a layer for the lambda. To do it you can make a zip package containing the FFmpeg library. 

On your local machine download and make a zip file of FFmpeg:

ruby
wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz.md5
md5sum -c ffmpeg-release-amd64-static.tar.xz.md5
tar xvf ffmpeg-release-amd64-static.tar.xz

The FFmpeg binary is located in the folder “ffmpeg-6.0-amd64-static” (It depend on the latest version, in this case it’s version 6.0).

Create a ZIP package for the Lambda layer as follows:

ruby
mkdir -p ffmpeg/bin
cp ffmpeg-6.0-amd64-static/ffmpeg ffmpeg/bin/
cd ffmpeg
zip -r ../ffmpeg.zip .

Upload the ffmpeg.zip to Amazon S3. We will create a new Layer in the Lambda console pointing to the package.

create-layer.png
Create a new Layer in the Lambda console pointing to the package. 

Step 3: Create Lambda Function

You can now create a new Lambda function in the console: choose the Author from Scratch option, fill in the Basic information, and choose Create function. Note: choose the role that we have created at the beginning of this post.

create-function.png
Choose Create function.

Once the Lambda function is created, on the function detail screen, you will see the Layers block at the bottom, choose Add a layer. Choose Custom layers.  Select “ffmpeg” from the drop-down list under Custom layers and the Version, then select Add.

add-layer.png
Choose Add a layer.

Back to the top of the function details screen, click + Add Trigger button to create an event.

Adding an Amazon S3 trigger from the source bucket to the Lambda function in the console: under Bucket, select the source bucket. Select “All object create events” for Event type. Input “.mp4” as Suffix. Read the Recursive invocation section, and acknowledge by checking the box, then choose Add.

trigger-configuration.png
Adding an Amazon S3 trigger from the source bucket to the Lambda function.

Back to detail screen, choose the tab Configuration. On the left menu bar, choose General configuration and click Edit button. Select 1024 MB for memory and Ephemeral storage and 1 minute timeout. You can modify them depending on how large your video's length. 

edit-basic-settings.png
Select 1024 MB for memory and Ephemeral storage and 1 minute timeout.

Step 4: Implement Extracting Image Code for The Lambda Function

All the setting is ready now, we will do the last step is to add ruby code to processing the video. Every time an .mp4 video is uploaded to the source bucket, this code will be triggered.

Choose the first tab Code

On the build in code editor, copy this ruby code:

ruby
require 'json'
require 'aws-sdk-s3'
require "open3"

DEST_BUCKET = "dest-bucket" #this is the bucket to store images

def lambda_handler(event:, context:)
    s3_source_key = event['Records'][0]['s3']['object']['key']
    base_path = "#{File.dirname(s3_source_key)}/#{File.basename(s3_source_key, ".*")}/"
    s3 = Aws::S3::Client.new(region: 'ap-south-1')
    path = "https://aishit-test-bucket.s3.ap-south-1.amazonaws.com/#{s3_source_key}" #path of uploaded video, change the source bucket to your source bucket
    duration = get_video_length(path)
    #extract one frame every one second and upload the image to destination bucket
    duration.times do |i|
        dur = sec_to_duration(i)
        stdout, exit_code = Open3.capture2("/opt/bin/ffmpeg -ss #{dur} -i #{path} -f image2 -vframes 1 -")
        key = "#{base_path}image#{add_zeros(i,4)}.png"
        s3.put_object(bucket: DEST_BUCKET, key: key, body: stdout)
    end
end

def add_zeros(num, len=2)
  zero_count = len - "#{num}".length
  return num unless zero_count.positive?
  "#{'0' * zero_count}#{num}"
end

def sec_to_duration(sec)
    h = sec / 3600
    m = (sec % 3600) / 60
    s = sec % 60
    
    "#{add_zeros(h)}:#{add_zeros(m)}:#{add_zeros(s)}"
end

#input: the video url, output: video length in seconds.
def get_video_length(path)
  stdin, stderr, stdout, wait_thr = Open3.popen3("/opt/bin/ffmpeg -i #{path}")
  output = stdout.gets(nil)
  idx = output.index('Duration') + 10
  duration = output[idx..idx+7]
  arr = duration.split(':').map(&:to_i)
  secs = arr[0] * 3600 + arr[1] * 60 + arr[2]
  secs
End
code-source.png
Choose the first tab Code.

Choose Deploy to save and deploy the change. 

Everything is done now, you can test by uploading a .mp4 video to the source bucket, and see it will create a folder in the destination bucket containing the extracted images.

>> Read more:

Conclusion

Relia Software is here to assist you if you are having trouble constructing a Ruby on Rails application. We are a top full-stack development company and can help you create a high-quality application that is both sturdy and scalable. 

>>> Follow and Contact Relia Software for more information!

  • coding