Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Integrating Zencoder API with Carrierwave in Rails
class CreateVideos < ActiveRecord::Migration
def change
create_table :videos do |t|
t.string :video
t.text :meta_info
t.timestamps
end
end
end
resource :zencoder, :controller => :zencoer, :only => :create
class Video < ActiveRecord::Base
mount_uploader :video, VideoUploader
serialize :meta_info, Hash
# To locally test the videos, aftetr zencoder has done
# transcoding it, do following in rails console
#
# >> v = Video.find(id) # id of the video models
# >> v.meta_info = v.meta_info.merge(:response => { :input => { :duration_in_ms => 3000 }, :job => { :state => 'finished' }})
# >> v.save!
def duration
((meta_info[:response].try(:[], :input).
try(:[], :duration_in_ms) || 0) / 1000.0).ceil
end
def transcode_complete?
meta_info[:response].try(:[], :job).
try(:[], :state) == 'finished'
end
end
class VideoUploader < CarrierWave::Uploader::Base
include Rails.application.routes.url_helpers
Rails.application.routes.default_url_options = ActionMailer::Base.default_url_options
after :store, :zencode
storage :fog
def store_dir
"videos/#{model.id}"
end
def extension_white_list
%w( avi mov mkv mpg mpeg mp4 m4v flv)
end
def thumbnail_url
@thubnail_url ||= url_for_format('thumbnail', 'png')
end
def mp4_url
@mp4_url ||= url_for_format('mp4')
end
def webm_url
@webm_url ||= url_for_format('webm')
end
def ogv_url
@ogv_url ||= url_for_format('ogv')
end
private
def zencode(*args)
params = {
:input => @model.video.url,
:test => true, # https://app.zencoder.com/docs/guides/getting-started/test-jobs-and-integration-mode
:notifications => [zencoder_url],
:pass_through => @model.id,
:outputs => [
{
:public => true,
:base_url => base_url,
:filename => 'mp4_' + filename_without_ext + '.mp4',
:label => 'webmp4',
:format => 'mp4',
:audio_codec => 'aac',
:video_codec => 'h264'
},
{
:public => true,
:base_url => base_url,
:filename => 'webm_' + filename_without_ext + '.webm',
:label => 'webwebm',
:format => 'webm',
:audio_codec => 'vorbis',
:video_codec => 'vp8'
},
{
:public => true,
:base_url => base_url,
:filename => 'ogv_' + filename_without_ext + '.ogv',
:label => 'webogv',
:format => 'ogv',
:audio_codec => 'vorbis',
:video_codec => 'theora'
},
{
:thumbnails => {
:public => true,
:base_url => base_url,
:filename => "thumbnail_" + filename_without_ext,
:times => [4],
:aspect_mode => 'preserve',
:width => '100',
:height => '100'
}
}
]
}
z_response = Zencoder::Job.create(params)
@model.meta_info[:request] = z_response.body
@model.save(:validate => false)
end
def filename_without_ext
@filename_without_ext ||= File.basename(@model.video.url, File.extname(@model.video.url))
end
def base_url
@base_url ||= File.dirname(@model.video.url)
end
def url_for_format(prefix, extension = nil)
extension ||= prefix
base_url + '/' + prefix + '_' + filename_without_ext + '.' + extension
end
end
class ZencoderController < ApplicationController
skip_before_filter :verify_authenticity_token, :authorize
def create
video = Video.find_by_id(params[:job][:pass_through])
if video && params[:job][:state] == 'finished'
video.meta_info[:response] = params[:zencoder]
video.save
end
render :nothing => true
end
end

@waseem Love this. Thanks for this. It really saved me a lot of time. A few thoughts, there is a typo on this line: https://gist.github.com/waseem/5479964#file-video_uploader-rb-L18

Also, you should mention that this implementation doesn't work locally in development, largely because Zencoder API requires a 'notification' URL to post back to after the processing is done - which would trigger the Zencoder#Create action you created.

The reason that doesn't work is because the value for zencoder_url which is on this line: https://gist.github.com/waseem/5479964#file-video_uploader-rb-L39 generates a localhost URL, like http://localhost:3000/zencoder. So that doesn't work as a valid URL for ZC to post back to.

That being said, there is a workaround that ZC created called Zencoder Fetcher, which you can read about here: https://app.zencoder.com/docs/guides/advanced-integration/getting-zencoder-notifications-while-developing-locally

All you simply have to do is, replace that notifications line with something like this:
notifications: 'http://zencoderfetcher'

Then, once you upload a file from your local app and it seems like the operation has been complete, then you just run this at your command-line:

zencoder_fetcher your-zencoder-account-api-key --count 1 --url http://localhost:3000/zencoder/

That is a bit clunky, and you have to do it manually...but it sure does work.

I created a fork of this gist, that includes my modifications if anyone is interested: https://gist.github.com/marcamillion/7019428cbc7c253f5a9a

I hope that helps someone else in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment