class FFMPEG::Movie
Attributes
audio_bitrate[R]
audio_channels[R]
audio_codec[R]
audio_sample_rate[R]
audio_stream[R]
bitrate[R]
colorspace[R]
container[R]
creation_time[R]
dar[R]
duration[R]
frame_rate[R]
height[R]
path[R]
rotation[R]
sar[R]
time[R]
video_bitrate[R]
video_codec[R]
video_stream[R]
width[R]
Public Class Methods
new(path)
click to toggle source
# File lib/ffmpeg/movie.rb, line 11 def initialize(path) raise Errno::ENOENT, "the file '#{path}' does not exist" unless File.exist?(path) @path = path # ffmpeg will output to stderr command = "#{FFMPEG.ffprobe_binary} -i #{Shellwords.escape(path)} -print_format json -show_format -show_streams -show_error" std_output = '' std_error = '' Open3.popen3(command) do |stdin, stdout, stderr| std_output = stdout.read unless stdout.nil? std_error = stderr.read unless stderr.nil? end fix_encoding(std_output) metadata = MultiJson.load(std_output, symbolize_keys: true) if metadata.key?(:error) @duration = 0 else video_streams = metadata[:streams].select { |stream| stream.key?(:codec_type) and stream[:codec_type] === 'video' } audio_streams = metadata[:streams].select { |stream| stream.key?(:codec_type) and stream[:codec_type] === 'audio' } @container = metadata[:format][:format_name] @duration = metadata[:format][:duration].to_f @time = metadata[:format][:start_time].to_f @creation_time = if metadata[:format].key?(:tags) and metadata[:format][:tags].key?(:creation_time) Time.parse(metadata[:format][:tags][:creation_time]) else nil end @bitrate = metadata[:format][:bit_rate].to_i unless video_streams.empty? # TODO: Handle multiple video codecs (is that possible?) video_stream = video_streams.first @video_codec = video_stream[:codec_name] @colorspace = video_stream[:pix_fmt] @width = video_stream[:width] @height = video_stream[:height] @video_bitrate = video_stream[:bit_rate].to_i @sar = video_stream[:sample_aspect_ratio] @dar = video_stream[:display_aspect_ratio] @frame_rate = unless video_stream[:avg_frame_rate] == '0/0' Rational(video_stream[:avg_frame_rate]) else nil end @video_stream = "#{video_stream[:codec_name]} (#{video_stream[:profile]}) (#{video_stream[:codec_tag_string]} / #{video_stream[:codec_tag]}), #{colorspace}, #{resolution} [SAR #{sar} DAR #{dar}]" @rotation = if video_stream.key?(:tags) and video_stream[:tags].key?(:rotate) video_stream[:tags][:rotate].to_i else nil end end unless audio_streams.empty? # TODO: Handle multiple audio codecs audio_stream = audio_streams.first @audio_channels = audio_stream[:channels].to_i @audio_codec = audio_stream[:codec_name] @audio_sample_rate = audio_stream[:sample_rate].to_i @audio_bitrate = audio_stream[:bit_rate].to_i @audio_channel_layout = audio_stream[:channel_layout] @audio_stream = "#{audio_codec} (#{audio_stream[:codec_tag_string]} / #{audio_stream[:codec_tag]}), #{audio_sample_rate} Hz, #{audio_channel_layout}, #{audio_stream[:sample_fmt]}, #{audio_bitrate} bit/s" end end @invalid = true if metadata.key?(:error) @invalid = true if std_error.include?("Unsupported codec") @invalid = true if std_error.include?("is not supported") @invalid = true if std_error.include?("could not find codec parameters") end
Public Instance Methods
audio_channel_layout()
click to toggle source
# File lib/ffmpeg/movie.rb, line 128 def audio_channel_layout # TODO Whenever support for ffmpeg/ffprobe 1.2.1 is dropped this is no longer needed @audio_channel_layout || case(audio_channels) when 1 'stereo' when 2 'stereo' when 6 '5.1' else 'unknown' end end
calculated_aspect_ratio()
click to toggle source
# File lib/ffmpeg/movie.rb, line 116 def calculated_aspect_ratio aspect_from_dar || aspect_from_dimensions end
calculated_pixel_aspect_ratio()
click to toggle source
# File lib/ffmpeg/movie.rb, line 120 def calculated_pixel_aspect_ratio aspect_from_sar || 1 end
resolution()
click to toggle source
# File lib/ffmpeg/movie.rb, line 110 def resolution unless width.nil? or height.nil? "#{width}x#{height}" end end
screenshot(output_file, options = EncodingOptions.new, transcoder_options = {}, &block)
click to toggle source
# File lib/ffmpeg/movie.rb, line 146 def screenshot(output_file, options = EncodingOptions.new, transcoder_options = {}, &block) Transcoder.new(self, output_file, options.merge(screenshot: true), transcoder_options).run &block end
size()
click to toggle source
# File lib/ffmpeg/movie.rb, line 124 def size File.size(@path) end
transcode(output_file, options = EncodingOptions.new, transcoder_options = {}, &block)
click to toggle source
# File lib/ffmpeg/movie.rb, line 142 def transcode(output_file, options = EncodingOptions.new, transcoder_options = {}, &block) Transcoder.new(self, output_file, options, transcoder_options).run &block end
valid?()
click to toggle source
# File lib/ffmpeg/movie.rb, line 98 def valid? not @invalid end
Protected Instance Methods
aspect_from_dar()
click to toggle source
# File lib/ffmpeg/movie.rb, line 151 def aspect_from_dar return nil unless dar w, h = dar.split(":") aspect = w.to_f / h.to_f aspect.zero? ? nil : aspect end
aspect_from_dimensions()
click to toggle source
# File lib/ffmpeg/movie.rb, line 165 def aspect_from_dimensions aspect = width.to_f / height.to_f aspect.nan? ? nil : aspect end
aspect_from_sar()
click to toggle source
# File lib/ffmpeg/movie.rb, line 158 def aspect_from_sar return nil unless sar w, h = sar.split(":") aspect = w.to_f / h.to_f aspect.zero? ? nil : aspect end
fix_encoding(output)
click to toggle source
# File lib/ffmpeg/movie.rb, line 170 def fix_encoding(output) output[/test/] # Running a regexp on the string throws error if it's not UTF-8 rescue ArgumentError output.force_encoding("ISO-8859-1") end