Class: Paperclip::Ffmpeg
- Inherits:
-
Processor
- Object
- Processor
- Paperclip::Ffmpeg
- Defined in:
- lib/paperclip-ffmpeg.rb
Instance Attribute Summary collapse
-
#convert_options ⇒ Object
Returns the value of attribute convert_options.
-
#format ⇒ Object
Returns the value of attribute format.
-
#geometry ⇒ Object
Returns the value of attribute geometry.
-
#whiny ⇒ Object
Returns the value of attribute whiny.
Instance Method Summary collapse
- #identify ⇒ Object
-
#initialize(file, options = {}, attachment = nil) ⇒ Ffmpeg
constructor
Creates a Video object set to work on the
file
given. -
#make ⇒ Object
Performs the transcoding of the
file
into a thumbnail/video.
Constructor Details
#initialize(file, options = {}, attachment = nil) ⇒ Ffmpeg
Creates a Video object set to work on the file
given. It will attempt to transcode the video into one defined by target_geometry
which is a “WxH”-style string. format
should be specified. Video transcoding will raise no errors unless whiny
is true (which it is, by default. If convert_options
is set, the options will be appended to the convert command upon video transcoding
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/paperclip-ffmpeg.rb', line 12 def initialize file, = {}, = nil @convert_options = { :ab => '64k', :ac => 2, :ar => 44100, :b => '1200k', :deinterlace => nil, :r => 25, :y => nil, } @convert_options.reverse_merge! [:convert_options] unless [:convert_options].nil? || [:convert_options].class != Hash @geometry = [:geometry] @file = file @keep_aspect = !@geometry.nil? && @geometry[-1,1] != '!' @pad_only = @keep_aspect && @geometry[-1,1] == '#' @enlarge_only = @keep_aspect && @geometry[-1,1] == '<' @shrink_only = @keep_aspect && @geometry[-1,1] == '>' @whiny = [:whiny].nil? ? true : [:whiny] @format = [:format] @time = [:time].nil? ? 3 : [:time] @current_format = File.extname(@file.path) @basename = File.basename(@file.path, @current_format) @meta = identify .instance_write(:meta, @meta) end |
Instance Attribute Details
#convert_options ⇒ Object
Returns the value of attribute convert_options.
4 5 6 |
# File 'lib/paperclip-ffmpeg.rb', line 4 def @convert_options end |
#format ⇒ Object
Returns the value of attribute format.
4 5 6 |
# File 'lib/paperclip-ffmpeg.rb', line 4 def format @format end |
#geometry ⇒ Object
Returns the value of attribute geometry.
4 5 6 |
# File 'lib/paperclip-ffmpeg.rb', line 4 def geometry @geometry end |
#whiny ⇒ Object
Returns the value of attribute whiny.
4 5 6 |
# File 'lib/paperclip-ffmpeg.rb', line 4 def whiny @whiny end |
Instance Method Details
#identify ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/paperclip-ffmpeg.rb', line 124 def identify = {} command = "ffmpeg -i #{File.(@file.path)} 2>&1" Paperclip.log(command) ffmpeg = IO.popen(command) ffmpeg.each("\r") do |line| if line =~ /((\d*)\s.?)fps,/ [:fps] = $1.to_i end # Matching lines like: # Video: h264, yuvj420p, 640x480 [PAR 72:72 DAR 4:3], 10301 kb/s, 30 fps, 30 tbr, 600 tbn, 600 tbc if line =~ /Video:(.*)/ v = $1.to_s.split(',') size = v[2].strip!.split(' ').first [:size] = size.to_s [:aspect] = size.split('x').first.to_f / size.split('x').last.to_f end # Matching Duration: 00:01:31.66, start: 0.000000, bitrate: 10404 kb/s if line =~ /Duration:(\s.?(\d*):(\d*):(\d*\.\d*))/ [:length] = $2.to_s + ":" + $3.to_s + ":" + $4.to_s end end end |
#make ⇒ Object
Performs the transcoding of the file
into a thumbnail/video. Returns the Tempfile that contains the new image/video.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/paperclip-ffmpeg.rb', line 40 def make src = @file dst = Tempfile.new([@basename, @format ? ".#{@format}" : '']) dst.binmode parameters = [] # Add geometry if @geometry # Extract target dimensions if @geometry =~ /(\d*)x(\d*)/ target_width = $1 target_height = $2 end # Only calculate target dimensions if we have current dimensions unless @meta[:size].nil? current_geometry = @meta[:size].split('x') # Current width and height current_width = current_geometry[0] current_height = current_geometry[1] if @keep_aspect if @enlarge_only if current_width.to_i < target_width.to_i # Keep aspect ratio width = target_width.to_i height = (width.to_f / (@meta[:aspect].to_f)).to_i @convert_options[:s] = "#{width.to_i}x#{height.to_i}" else return nil end elsif @shrink_only if current_width.to_i > target_width.to_i # Keep aspect ratio width = target_width.to_i height = (width.to_f / (@meta[:aspect].to_f)).to_i @convert_options[:s] = "#{width.to_i}x#{height.to_i}" else return nil end elsif @pad_only # Keep aspect ratio width = target_width.to_i height = (width.to_f / (@meta[:aspect].to_f)).to_i # We should add half the delta as a padding offset Y pad_y = (target_height.to_f - height.to_f) / 2 if pad_y > 0 @convert_options[:vf] = "scale=#{width}:-1,pad=#{width.to_i}:#{target_height.to_i}:0:#{pad_y}:black" else @convert_options[:vf] = "scale=#{width}:-1,crop=#{width.to_i}:#{height.to_i}" end else # Keep aspect ratio width = target_width.to_i height = (width.to_f / (@meta[:aspect].to_f)).to_i @convert_options[:s] = "#{width.to_i}x#{height.to_i}" end else # Do not keep aspect ratio @convert_options[:s] = "#{target_width.to_i}x#{target_height.to_i}" end end end # Add format case @format when 'jpg', 'jpeg', 'png', 'gif' # Images @convert_options[:f] = 'image2' @convert_options[:ss] = @time @convert_options[:vframes] = 1 end parameters << @convert_options.map { |k,v| "-#{k.to_s} #{v} "} parameters << '-i :source' parameters << ":dest" parameters = parameters.flatten.compact.join(" ").strip.squeeze(" ") begin success = Paperclip.run("ffmpeg", parameters, :source => "#{File.(src.path)}", :dest => File.(dst.path)) rescue Cocaine::ExitStatusError => e raise PaperclipError, "error while processing video for #{@basename}." if @whiny end dst end |