Created
February 17, 2010 10:38
-
-
Save divineforest/306497 to your computer and use it in GitHub Desktop.
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
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