Skip to content

Instantly share code, notes, and snippets.

@divineforest
Created February 17, 2010 10:38
Show Gist options
  • Save divineforest/306497 to your computer and use it in GitHub Desktop.
Save divineforest/306497 to your computer and use it in GitHub Desktop.
require 'rvideo'
class Video < MediaFile
after_create :process
FLV_WIDTH = 400
FLV_HEIGHT = 316
CLIP_SIZE_LIMIT_MEGABYTES = 50
# Paperclip Video
has_attached_file :clip
validates_attachment_size :clip, :less_then => CLIP_SIZE_LIMIT_MEGABYTES.megabytes
# Paperclip Video FLV
has_attached_file :clip_flv
# Paperclip Image
has_attached_file :image
:styles => IMAGE_SIZE_STYLES,
:convert_options => {:preview_photostream => '-background white -gravity center -extent 88x66'}
state_machine :state, :initial => :new do
# :new
# :processing
# :failed
# :moderating
# :banned
# :ok
event :set_processing do
transition [:new, :moderating, :ok, :failed] => :processing
end
event :set_failed do
transition [:processing] => :failed
end
event :set_moderating do
transition [:processing] => :moderating
end
event :set_banned do
transition [:moderating] => :banned
end
event :set_ok do
transition [:moderating] => :ok
end
end
CONTENT_TYPES = ['application/x-mp4',
'video/mpeg',
'video/quicktime',
'video/x-la-asf',
'video/x-ms-asf',
'video/x-msvideo',
'video/x-sgi-movie',
'video/x-flv',
'flv-application/octet-stream',
'video/3gpp',
'video/3gpp2',
'video/3gpp-tt',
'video/BMPEG',
'video/BT656',
'video/CelB',
'video/DV',
'video/H261',
'video/H263',
'video/H263-1998',
'video/H263-2000',
'video/H264',
'video/JPEG',
'video/MJ2',
'video/MP1S',
'video/MP2P',
'video/MP2T',
'video/mp4',
'video/MP4V-ES',
'video/MPV',
'video/mpeg4',
'video/mpeg4-generic',
'video/nv',
'video/parityfec',
'video/pointer',
'video/raw',
'video/rtx'
]
# options:
# uploaded_file
def self.build_default(options = {})
video = Video.new
video.image = File.open(Rails.root.join("public", "images", "video_icon_big.png"))
video.clip = options[:uploaded_file]
video
end
def process
set_processing!
self.send_later(:process_perform)
true
end
def process_perform
image_success = make_image
convert_success = convert_video if image_success
if image_success && convert_success
set_moderating!
Notifier.deliver_video_converted(self.id)
true
else
set_failed!
self.image = File.open(Rails.root.join("public", "images", "video_icon_error_big.png"))
save!
Notifier.deliver_video_failed(self.id)
false
end
end
private
def make_image
video_filename = clip.path
return false if video_filename.empty?
image_filename = "#{temp_file_name}.jpg"
cmd = "ffmpeg -i #{video_filename} -an -ss 00:00:10 -an -r 1 -vframes 1 -y -f mjpeg #{image_filename} 2>&1"
cmd_result = `#{cmd}`
if File.exists?(image_filename)
self.image = File.open(image_filename)
self.error = ""
save!
true
else
self.error = "Failed to make image"
save!
false
end
end
def convert_video
video_filename = clip.path
return if video_filename.empty?
flv_filename = "#{temp_file_name}.flv"
transcoder = RVideo::Transcoder.new
recipe = "ffmpeg -i $input_file$ -ab 48000 -ar 22050 -s $resolution$ -vcodec flv -qscale 8 -f flv -y $output_file$"
logger.debug("[debug] Video making flv: #{recipe}")
begin
transcoder.execute(recipe, {:input_file => video_filename, :output_file => flv_filename, :resolution => "#{FLV_WIDTH}x#{FLV_HEIGHT}"})
self.clip_flv = File.open(flv_filename)
self.error = ""
save!
true
rescue RVideo::TranscoderError => e
self.error = "#{e.class} - #{e.message}"
save!
false
end
end
def temp_file_name
tempdir = Dir::tmpdir || '/tmp'
t = Time.now.strftime("%Y%m%d")
path = "clip#{t}-#{$$}-#{rand(0x100000000).to_s(36)}"
File.join(tempdir, path)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment