I asked two additional questions before this on Stack Overflow, but got very little help and I thought I would ask an open question for posterity. I have spent time parsing the AWS-SDK API docs and found very little direct answers to my needs. I have also posted on the AWS forums and haven't been able to get a good response there. A simple, comprehensive, step-by-step solution seems impossible to find.
What I have completed:
- Uploading with CarrierWave direct to s3. I followed Railscast #383 and adapted it to my needs.
- I am able to "retrieve" my files from my s3 bucket.
Details about what I've done so far:
I used Carrierwave-Direct to upload direct to s3(this utilizes fog to deal with uploading directly to s3). The upload is processed in a background job with Sidekiq. After the file is put in the bucket I just retrieve it by iterating through a users uploads and call the file by the upload's url from s3.
Here is where I'm lost:
- I need to transcode videos with the Elastic Transcoder provided by AWS.
- I need to recall the uploaded/converted videos from the output bucket. How do I link to the URL from the "output-bucket"? Is it a new URL reference or does the URL stay the same as the original "upload URL"?
- I need to integrate the transcoded videos from transcoder to Cloudfront and display them using JWPlayer.
- How do I integrate the API code into my uploading process in the background?
Here is my code so far:
My uploader:
class VideoUploader < CarrierWave::Uploader::Base
include CarrierWaveDirect::Uploader
end
My initializer that handles the s3 details:
CarrierWave.configure do |config|
config.fog_credentials = {
provider: 'AWS',
aws_access_key_id: 'AWS_ACCESS_KEY_ID',
aws_secret_access_key: 'AWS_SECRET_ACCESS_KEY',
region: 'us-west-1'}
config.fog_directory = 'video-input'
config.fog_public = false # optional, defaults to true
config.fog_attributes = { 'Cache-Control' => "max-age=#{365.day.to_i}" } # optional, defaults to {}
end
My Upload Model:
class Upload < ActiveRecord::Base
belongs_to :user
mount_uploader :video, VideoUploader
after_save :enqueue_video
def enqueue_video
VideoWorker.perform_async(id, key) if key.present?
end
class VideoWorker
include Sidekiq::Worker
def perform(id, key)
upload = Upload.find(id)
upload.key = key
video.remote_video_url = upload.video.direct_fog_url(with_path: true)
upload.save!
end
end
end
My view:
To show all user's uploads:
<% @user.uploads.each do |upload| %>
<%= link_to upload.title, upload_url(upload) %>
<% end %>
To show the upload (right now it is only a download link):
<h1><%= @upload.title %></h1>
<p><%= link_to @upload.video_url %></p>
I don't think my schema or forms are relevant.
A similar sample of how I think the code might work:
I would add this code into the Sidekiq worker, but I'm not sure if I'm doing this right. I'm also uncertain about how I'm going to connect my "upload" to the "converted upload".
upload.update_column 'converted_video',
File.basename(upload.video.path)
transcoder = AWS::ElasticTranscoder::Client.new
transcoder.create_job(
pipeline_id: APP_CONFIG[Rails.env][:pipeline_id],
input: {
key: upload.video.path,
frame_rate: 'auto',
resolution: 'auto',
aspect_ratio: 'auto',
interlaced: 'auto',
container: 'auto'
},
output: {
key: upload.converted_video.path,
preset_id: WEB_M4_PRESET_ID,
thumbnail_pattern: "",
rotate: '0'
}
)
Links to a helpful article and the docs about the Elastic Transcoder:
http://www.techdarkside.com/getting-started-with-the-aws-elastic-transcoder-api-in-rails
http://docs.aws.amazon.com/sdkforruby/api/Aws/ElasticTranscoder.html