Falcon

Video encoding tool.

Install

gem 'falcon'

rails generate falcon:install

rake db:migrate

Usage

Create profiles

By default avariable two profiles “web_mp4” and “web_ogg”:

Falcon::Profile.new("web_mp4", {:player => 'flash', :container => "mp4", :extname => 'mp4',
  :width => 480, :height => 320, :video_codec => "libx264",
  :video_bitrate => 500, :fps => 29.97, :audio_codec => "libfaac",
  :command => "-vpre medium",
  :audio_bitrate => 128, :audio_sample_rate => 48000})

Falcon::Profile.new("web_ogg", {:player => 'html5', :container => "ogg", :extname => 'ogv',
  :width => 480, :height => 320, :video_codec => "libtheora",
  :video_bitrate => 500, :fps => 29.97, :audio_codec => "libvorbis",
  :audio_bitrate => 128, :audio_sample_rate => 48000})

Update profiles

Falcon::Profile['web_mp4'].update({:width => 800, :height => 600})

Model

Model has attachment file, we declare “falcon_encode” method and pass :source and :profiles options:

class VideoFile
  has_attached_file :data,
                    :url => "/assets/video_files/:id/:filename",
                    :path => ":rails_root/public/assets/video_files/:id/:filename"

  validates_attachment_presence :data
  validates_attachment_size :data, :less_than => 200.megabytes
  validates_attachment_content_type :data, :content_type => Falcon::CONTENT_TYPES

  attr_accessible :data

  falcon_encode 'media', :source => lambda { |file| file.data.path }, 
                :profiles => ['web_mp4', 'web_ogg']
end

Metadata options

You can provide metadata options in your model, just set option “metadata”:

class VideoFile

  ...

  falcon_encode 'media', :source => lambda { |file| file.data.path }, 
                :metadata => :media_metadata_options,
                :profiles => ['web_mp4', 'web_ogg']

  # A hash of metadatas for video:
  # 
  # { :title => '', :author => '', :copyright => '', 
  #   :comment => '', :description => '', :language => ''}
  #
  def media_metadata_options
    { :title => title, :author => user.name, :language => 'rus' }
  end
end

Background processing

Video encoding take a long time, so you must use background process. I recomended “delayed_job” or “resque”. To send encoding in background, just set option method “encode”:

Resque example:

class VideoFile

  ...

  falcon_encode 'media', :source => lambda { |file| file.data.path }, 
                :metadata => :media_metadata_options,
                :encode => lambda { |encoding| Resque.enqueue(JobEncoding, encoding.id) },
                :profiles => ['web_mp4', 'web_ogg']
end

class JobEncoding
  @queue = :encoding_queue

  def self.perform(encoding_id)
    encoding = Falcon::Encoding.find(encoding_id)
    encoding.encode
  end
end

For delayed_job:

class VideoFile

  ...

  falcon_encode 'media', :source => lambda { |file| file.data.path },
              :metadata => :media_metadata_options,
              :encode => lambda { |encoding| encoding.delay.encode },
              :profiles => ['web_mp4', 'web_ogg']

end

Callbacks

class VideoFile

  ...

  falcon_encode 'media', :source => lambda { |file| file.data.path }

  before_encode       :method_name
  before_media_encode :method_name
  after_media_encode  :method_name
  after_encode        :method_name
end

Screenshots

class VideoFile
  has_many :screenshots, :dependent => :destroy

  ...

  falcon_encode 'media', :source => lambda { |file| file.data.path }

  after_media_encode :save_screenshots

  def save_screenshots
    media.screenshots do |filepath|
      self.screenshots.create(:data => File.new(filepath))
    end
  end
end

Path and url

class VideoFile
  falcon_encode 'media', :source => lambda { |file| file.data.path }

  def media_url(profile_name)
    media.url(profile_name)
  end

  def media_path(profile_name)
    media.path(profile_name)
  end
end