Information Technology Dark Side

Struggles of a Self-Taught Coder

Information Technology Dark Side header image 2

Getting Started with the AWS Elastic Transcoder API in Rails

January 31st, 2013 · 7 Comments

Elastic What?
Elastic Transcoder is a brand new product from Amazon that lets you transcode videos into your favorite formats. It comes with lots of awesome preset formats, so you can use it through the AWS console to transcode a hi-def video to a web-friendly or iPhone-friendly resolution. You can even use it to create thumbnails and rotate the video. I’m going to show you how I use it to transcode a video from its URL in a Ruby on Rails app.

Elastic Transcoder only works on AWS S3, so you have to get the video into S3 before you can transcode it.

The Set Up
I have a video at a location on the web. In this case, it’s in Dropbox and I have a signed URL for it, but it really could be anywhere. I’ve stored the URL on a model and set up a resque worker to save the video to S3 and then kick off the transcoder. I am using CarrierWave for uploading files.

Code
You will need to add aws-sdk 1.8.1.1 to your Gemfile first. Prior versions don’t include the transcoder.

require 'open-uri'

class VideoProcessorWorker
  WEB_MP4_PRESET_ID = '1351620000000-100070'
  @queue = :eo_video_queue
  def self.perform(lecture_segment_id)
    lecture_segment = LectureSegment.find(
      lecture_segment_id)
    lecture_segment.remote_video_url = 
      lecture_segment.video_dropbox_path
    lecture_segment.save!

    lecture_segment.update_column 'web_video', 
      File.basename(lecture_segment.video.path)

    transcoder = AWS::ElasticTranscoder::Client.new
    transcoder.create_job(
      pipeline_id: APP_CONFIG[Rails.env][:pipeline_id],
      input: {
        key: lecture_segment.video.path,
        frame_rate: 'auto',
        resolution: 'auto',
        aspect_ratio: 'auto',
        interlaced: 'auto',
        container: 'auto'
      },
      output: {
        key: lecture_segment.web_video.path,
        preset_id: WEB_MP4_PRESET_ID,
        thumbnail_pattern: "",
        rotate: '0'
      }
    )
    
  end
end

Enough code, let’s talk
CarrierWave makes this problem a lot easier because it lets you save files from the interwebs to S3. All you have to do is put the url in the remote_whatever_url field and save it. Lourve the carrierwave!

You might be wondering why I do this:

lecture_segment.update_column 'web_video', 
  File.basename(lecture_segment.video.path)

CarrierWave won’t let you set the file name directly, and “web_video” represents the file that AWS Elastic Transcoder is going to create for me, so it’s not there yet, but AWS still wants to know it’s key. So, I use the update_columm method to update it in the DB without any callbacks, etc to trick CarrierWave into thinking the file exists. Once that is done, I can get its key (S3 talk for path) when I define the output portion of my transcoding job.

There may be better ways to do this, I’m all ears.

Incidentally, the preset id is from Amazon. They have a lot of awesome presets and you can create your own. The one I’m using is for web videos, which is really kind of funny cuz it means…

Boom. Web video from an URL for a web video.

If you enjoyed this post, make sure you subscribe to my RSS feed!
Stumble it!

Tags: Uncategorized

7 responses so far ↓

  • 1 Christian // Feb 1, 2013 at 12:51 am

    Nice one, just what I was looking for. I couldnt find any AWS SDK docs for the transcoding so this is perfect – thanks!

    Btw – “Enough code, let’s talk” ? Should ALWAYS be “Enough talk, lets code!” :)

  • 2 M Ram // Apr 7, 2013 at 8:10 pm

    Do you have a working example on github somewhere? I have it worked for the most part but not all the way. Specifically, I’m trying to figure out how to refer to the transcoded version of the file after it’s been completed.

  • 3 Randy // Jun 26, 2013 at 5:31 pm

    How do you specify the region for this example? I cannot get my own Preset working because the region is not set (Oregon).

  • 4 Randy // Jun 26, 2013 at 5:43 pm

    Actually, I figured it out:

    transcoder = AWS::ElasticTranscoder::Client.new(elastic_transcoder_endpoint: ENV["AWS_REGION_ENDPOINT"])

  • 5 Frank // Jun 30, 2013 at 3:03 am

    Alternatively you can set the region as follows:

    transcoder = AWS::ElasticTranscoder.new(:region => ‘us-west-2′)

  • 6 Aj // Aug 2, 2014 at 1:42 am

    Hey, have you been able to specify the duration of the clip? cant seem to pass it in to the hash for some reason.
    Thanks!

  • 7 David Christiansen // Aug 2, 2014 at 7:29 am

    Sorry, I don’t remember. We were never able to get reliable playback on lower bandwidth and ended up switching to Vimeo. :(

Leave a Comment