lib/ffmpeg/transcoder.rb in streamio-ffmpeg-2.0.0 vs lib/ffmpeg/transcoder.rb in streamio-ffmpeg-2.1.0

- old
+ new

@@ -1,25 +1,25 @@ require 'open3' -require 'shellwords' module FFMPEG class Transcoder + attr_reader :command, :input + @@timeout = 30 - def self.timeout=(time) - @@timeout = time + class << self + attr_accessor :timeout end - def self.timeout - @@timeout - end - - def initialize(movie, output_file, options = EncodingOptions.new, transcoder_options = {}) - @movie = movie + def initialize(input, output_file, options = EncodingOptions.new, transcoder_options = {}) + if input.is_a?(FFMPEG::Movie) + @movie = input + @input = input.path + end @output_file = output_file - if options.is_a?(String) || options.is_a?(EncodingOptions) + if options.is_a?(Array) || options.is_a?(EncodingOptions) @raw_options = options elsif options.is_a?(Hash) @raw_options = EncodingOptions.new(options) else raise ArgumentError, "Unknown options format '#{options.class}', should be either EncodingOptions, Hash or String." @@ -27,10 +27,18 @@ @transcoder_options = transcoder_options @errors = [] apply_transcoder_options + + @input = @transcoder_options[:input] unless @transcoder_options[:input].nil? + + input_options = @transcoder_options[:input_options] || [] + iopts = [] + input_options.each { |k, v| iopts += ['-' + k.to_s, v] } + + @command = [FFMPEG.ffmpeg_binary, '-y', *iopts, '-i', @input, *@raw_options.to_a, @output_file] end def run(&block) transcode_movie(&block) if @transcoder_options[:validate] @@ -49,18 +57,21 @@ def encoded @encoded ||= Movie.new(@output_file) end + def timeout + self.class.timeout + end + private # frame= 4855 fps= 46 q=31.0 size= 45306kB time=00:02:42.28 bitrate=2287.0kbits/ def transcode_movie - @command = "#{FFMPEG.ffmpeg_binary} -y -i #{Shellwords.escape(@movie.path)} #{@raw_options} #{Shellwords.escape(@output_file)}" - FFMPEG.logger.info("Running transcoding...\n#{@command}\n") + FFMPEG.logger.info("Running transcoding...\n#{command}\n") @output = "" - Open3.popen3(@command) do |_stdin, _stdout, stderr, wait_thr| + Open3.popen3(*command) do |_stdin, _stdout, stderr, wait_thr| begin yield(0.0) if block_given? next_line = Proc.new do |line| fix_encoding(line) @output << line @@ -73,38 +84,38 @@ progress = time / @movie.duration yield(progress) if block_given? end end - if @@timeout - stderr.each_with_timeout(wait_thr.pid, @@timeout, 'size=', &next_line) + if timeout + stderr.each_with_timeout(wait_thr.pid, timeout, 'size=', &next_line) else stderr.each('size=', &next_line) end rescue Timeout::Error => e - FFMPEG.logger.error "Process hung...\n@command\n#{@command}\nOutput\n#{@output}\n" + FFMPEG.logger.error "Process hung...\n@command\n#{command}\nOutput\n#{@output}\n" raise Error, "Process hung. Full output: #{@output}" end end end def validate_output_file(&block) if encoding_succeeded? yield(1.0) if block_given? - FFMPEG.logger.info "Transcoding of #{@movie.path} to #{@output_file} succeeded\n" + FFMPEG.logger.info "Transcoding of #{input} to #{@output_file} succeeded\n" else errors = "Errors: #{@errors.join(", ")}. " - FFMPEG.logger.error "Failed encoding...\n#{@command}\n\n#{@output}\n#{errors}\n" + FFMPEG.logger.error "Failed encoding...\n#{command}\n\n#{@output}\n#{errors}\n" raise Error, "Failed encoding.#{errors}Full output: #{@output}" end end def apply_transcoder_options # if true runs #validate_output_file @transcoder_options[:validate] = @transcoder_options.fetch(:validate) { true } - return if @movie.calculated_aspect_ratio.nil? + return if @movie.nil? || @movie.calculated_aspect_ratio.nil? case @transcoder_options[:preserve_aspect_ratio].to_s when "width" new_height = @raw_options.width / @movie.calculated_aspect_ratio new_height = new_height.ceil.even? ? new_height.ceil : new_height.floor new_height += 1 if new_height.odd? # needed if new_height ended up with no decimals in the first place