Created
August 4, 2010 07:46
-
-
Save Bertg/507804 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
These are some snips to help you converting video to flash and thumbnails using ruby and paperclip. | |
Needed: ffmpeg & flvtool, RVideo gem, paperclip | |
Converting the video is done using outside of paperclip, as this could take quite a while. Paperclip by default does it's conversions during the request, and the last thing you want is a request hanging for 10minutes while ffmpeg does it's thing. It is advised to do this conversion somewhere in the background using Resque or DelayedJob. (make sure not to run to many conversions at one time on your machine) | |
Most video thumbnailing solutions out there will create all thumbnails from the video. This solution (on paperclip 2.3.0) however will create one large "temp_thumbnail" once and all consequent thumbnails can use this temporary version. | |
VideoGeometry will make sure that the target dimensions for ffmpeg are always a multiple of 2 and as close as possible to the desired dimensions without breaking the aspect ratio of the original video. | |
The video.rb file is a cleaned up example of the video file we use. | |
Note that this code is "cleaned up". In reality you might want to have your binaries defined somewhat more dynamically and test if the conversion steps succeeded. system() will output false if not, or use $?.exitstatus. | |
This code is provided as is, and is free (as in beer and ideology) to use. If you explode your server or any other negative effect arises from using this code, I can not be held responsible for it. |
This file contains hidden or 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
module Paperclip | |
class VideoGeometry < Geometry | |
attr_accessor :video | |
cattr_accessor :ffmpeg_binary | |
@@ffmpeg_binary ||= '/usr/bin/ffmpeg' | |
def initialize file = nil | |
super(file.width, file.height) | |
@video = file | |
end | |
def self.from_file file | |
file = file.path if file.respond_to? "path" | |
begin | |
file = RVideo::Inspector.new(:file => file, :ffmpeg_binary => VideoGeometry.ffmpeg_binary) | |
rescue Exception => exc | |
raise "File could not be inspected #{exc.message}" | |
end | |
parse(file) | |
end | |
def self.parse file | |
VideoGeometry.new(file) | |
end | |
def transformation_to dst, crop = false | |
warn("Don't know how to crop videos") if crop | |
ratio = Geometry.new( dst.width / self.width, dst.height / self.height ) | |
scale_geometry, scale = scaling(dst, ratio) | |
scale_geometry | |
end | |
def scaling dst, ratio, force = false | |
ratio = if ratio.vertical? then ratio.width else ratio.height end | |
dimensions = if ratio < 1 || force | |
[(self.width * ratio), (self.height * ratio)] | |
else | |
[self.width, self.height] | |
end | |
dimensions.collect{|i| to_nearest_factor_of_two(i)}.join('x') | |
end | |
private | |
def to_nearest_factor_of_two(dimention) | |
a, b = dimention.ceil, dimention.floor | |
if b % 2 == 0 | |
b | |
elsif a % 2 == 0 | |
a | |
else | |
a + 1 | |
end | |
end | |
end | |
end |
This file contains hidden or 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 | |
has_attached_file :file, | |
:styles => Application.image_sizes, | |
:path => ":upload_path/videos/:model_id_attachment_path", | |
:url => ":owner_url/videos/:id/:style.:content_type_extension", | |
:processors => lambda { |a| Paperclip.content_types(:video).include?(a.file.content_type) ? [ :video_thumbnail ] : [ :thumbnail ] } | |
def self.default_dimension | |
'438x356' | |
end | |
def self.flvtool2_binary | |
'/usr/bin/flvtool2' | |
end | |
def convert! | |
flv_file_path = File.join(File.dirname(file.path) | |
dimentions = Paperclip::VideoGeometry.from_file(@original_file_path).transformation_to(Paperclip::Geometry.parse(Video.default_dimension)) | |
system(convert_command(file.path, flv_file_path, dimentions)) | |
system(flvtool_command(flv_file_path)) | |
end | |
def convert_command(original_file_path, flv_file_path, dimentions), "#{file_file_name.gsub(/#{File.extname(self.file.original_filename)}$/, "")}.sd.flv") | |
%(#{Paperclip::VideoGeometry.ffmpeg_binary} -i #{original_file_path} -b 1000000 -ar 22050 -ab 64 -f flv -y -s #{dimentions} | |
#{flv_file_path}).gsub!(/\s+/, " ") | |
end | |
def flvtool_command(flv_file_path) | |
%(#{Video.flvtool2_binary} -U '#{flv_file_path}').gsub!(/\s+/, " ") | |
end | |
end |
This file contains hidden or 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
module Paperclip | |
class VideoThumbnail < Thumbnail | |
attr_accessor :time_offset, :geometry, :whiny | |
def self.make file, options = {}, attachment = nil | |
if attachment.instance.try(:temp_thumbnail) && File.exists?(attachment.instance.temp_thumbnail.path) | |
Paperclip.log("Found temporary thumbnail form video") | |
else | |
Paperclip.log("Building temporary thumbnail form video") | |
time_offset = options[:time_offset] || '-4' | |
dst = Tempfile.new([ @basename, 'jpg' ].compact.join(".")) | |
dst.binmode | |
cmd = %Q[-itsoffset #{time_offset} -i "#{File.expand_path(file.path)}" -y -vcodec mjpeg -vframes 1 -an -f rawvideo ] | |
# | |
# Can not us the inspector on the video attachemnt. It is trying to access the saved path, but that could not be available! | |
# So let us use the file givven, and use our own inspector | |
# | |
inspector = RVideo::Inspector.new(:file => file.path, :ffmpeg_binary => aperclip::VideoGeometry.ffmpeg_binary) if !file.path.nil? | |
cmd << "-s #{inspector.resolution} " | |
cmd << %Q["#{File.expand_path(dst.path)}"] | |
begin | |
success = Paperclip.run('ffmpeg', cmd) | |
rescue PaperclipCommandLineError | |
whiny = options[:whiny].nil? ? true : options[:whiny] # copied form Thumbnail initializer | |
raise PaperclipError, "There was an error processing the thumbnail for #{@basename}" if whiny | |
end | |
attachment.instance.temp_thumbnail = dst | |
attachment.instance.temp_thumbnail.try(:close) | |
end | |
new(attachment.instance.temp_thumbnail, options, attachment).make | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment