lib/bulldog/attachment/video.rb in bulldog-0.1.1 vs lib/bulldog/attachment/video.rb in bulldog-0.2.0
- old
+ new
@@ -1,22 +1,9 @@
module Bulldog
module Attachment
class Video < Base
handle :video
-
- #
- # Return the width and height of the named style, as a 2-element
- # array.
- #
- # This runs ffmpeg for, and only for, the original style.
- #
- # +style_name+ defaults to the attribute's #default_style.
- #
- def dimensions(style_name)
- video_tracks(style_name).first.dimensions
- end
-
include HasDimensions
#
# Return the duration of the named style, as an
# ActiveSupport::Duration.
@@ -24,45 +11,31 @@
# This runs ffmpeg for, and only for, the original style.
#
# +style_name+ defaults to the attribute's #default_style.
#
def duration(style_name)
- # TODO: support styles with different durations
- if stream.missing?
- 0
- else
- from_examination :original_duration
- end
+ from_examination :@original_duration
end
#
# Return the video tracks of the named style, as an array of
# VideoTrack objects.
#
# Each VideoTrack has:
#
- # * <tt>#dimension</tt> - the dimensions of the video track,
- # [width, height].
+ # * <tt>#duration</tt> - the duration of the video track.
+ # * <tt>#dimensions</tt> - the [width, height] of the video
+ # track.
#
def video_tracks(style_name=nil)
style_name ||= reflection.default_style
- if style_name == :original
- if stream.missing?
- [VideoTrack.new(:dimensions => [2, 2])]
- else
- examine unless @original_video_tracks
- if @original_video_tracks.empty?
- @original_video_tracks << VideoTrack.new(:dimensions => [2, 2])
- end
- @original_video_tracks
- end
+ if style_name.equal?(:original)
+ from_examination :@original_video_tracks
else
style = reflection.styles[style_name]
- target_dimensions = style[:size].split(/x/).map{|s| s.to_i}
video_tracks(:original).map do |video_track|
- dimensions = resized_dimensions(dimensions(:original), target_dimensions, style[:filled])
- dimensions.map!{|i| i &= -2} # some codecs require multiples of 2
+ dimensions = resize_dimensions(dimensions(:original), style)
VideoTrack.new(:dimensions => dimensions)
end
end
end
@@ -70,16 +43,16 @@
# Return the video tracks of the named style, as an array of
# AudioTrack objects.
#
# AudioTrack objects do not yet have any useful methods.
#
- def audio_tracks(style_name)
+ def audio_tracks(style_name=nil)
examine
@original_audio_tracks
end
- storable_attribute :duration , :per_style => true, :memoize => true
+ storable_attribute :duration, :per_style => true, :memoize => true
def unload
super
instance_variables.grep(/@original_/).each do |name|
instance_variable_set(name, nil)
@@ -93,50 +66,80 @@
#
def default_processor_type
:ffmpeg
end
+ #
+ # Overridden to round down to multiples of 2, as required by
+ # some codecs.
+ #
+ def resize_dimensions(original_dimensions, style)
+ dimensions = super
+ dimensions.map!{|i| i &= -2}
+ end
+
private # -----------------------------------------------------
#
# Read the original image metadata with ffmpeg.
#
def run_examination
- return false if stream.missing?
- output = `ffmpeg -i #{stream.path} 2>&1`
- parse_output(output)
+ if stream.missing?
+ set_defaults
+ false
+ else
+ output = `ffmpeg -i #{stream.path} 2>&1`
+ # ffmpeg exits nonzero - don't bother checking status.
+ parse_output(output)
+ true
+ end
end
- def parse_output(output)
- result = false
+ def set_defaults
@original_duration = 0
- @original_video_tracks = []
+ @original_width = 2
+ @original_height = 2
@original_audio_tracks = []
+ @original_video_tracks = []
+ end
+
+ def parse_output(output)
+ result = false
+ set_defaults
io = StringIO.new(output)
while (line = io.gets)
case line
when /^Input #0, (.*?), from '(?:.*)':$/
result = true
+ duration = nil
when /^ Duration: (\d+):(\d+):(\d+)\.(\d+)/
- @original_duration = $1.to_i.hours + $2.to_i.minutes + $3.to_i.seconds
+ duration = $1.to_i.hours + $2.to_i.minutes + $3.to_i.seconds
when /Stream #(?:.*?): Video: /
if $' =~ /(\d+)x(\d+)/
dimensions = [$1.to_i, $2.to_i]
end
- @original_video_tracks << VideoTrack.new(:dimensions => dimensions)
+ @original_video_tracks << VideoTrack.new(:dimensions => dimensions, :duration => duration)
when /Stream #(?:.*?): Audio: (.*?)/
- @original_audio_tracks << AudioTrack.new
+ @original_audio_tracks << AudioTrack.new(:duration => duration)
end
end
+ if (track = @original_video_tracks.first)
+ @original_width, @original_height = *track.dimensions
+ end
+ if (track = @original_video_tracks.first || @original_audio_tracks.first)
+ @original_duration = track.duration
+ end
result
end
class Track
def initialize(attributes={})
attributes.each do |name, value|
send("#{name}=", value)
end
end
+
+ attr_accessor :duration
end
class VideoTrack < Track
attr_accessor :dimensions
end