Last active
December 16, 2015 18:48
-
-
Save waseem/5479964 to your computer and use it in GitHub Desktop.
Integrating Zencoder API with Carrierwave in Rails
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class CreateVideos < ActiveRecord::Migration | |
def change | |
create_table :videos do |t| | |
t.string :video | |
t.text :meta_info | |
t.timestamps | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
resource :zencoder, :controller => :zencoer, :only => :create |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@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, likehttp://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.