Class: VideoConverter::Ffmpeg
Class Attribute Summary collapse
-
.aliases ⇒ Object
Returns the value of attribute aliases.
-
.bin ⇒ Object
Returns the value of attribute bin.
-
.concat_command ⇒ Object
Returns the value of attribute concat_command.
-
.ffprobe_bin ⇒ Object
Returns the value of attribute ffprobe_bin.
-
.first_pass_command ⇒ Object
Returns the value of attribute first_pass_command.
-
.keyframes_command ⇒ Object
Returns the value of attribute keyframes_command.
-
.mux_command ⇒ Object
Returns the value of attribute mux_command.
-
.one_pass_command ⇒ Object
Returns the value of attribute one_pass_command.
-
.second_pass_command ⇒ Object
Returns the value of attribute second_pass_command.
-
.split_command ⇒ Object
Returns the value of attribute split_command.
-
.volume_detect_command ⇒ Object
Returns the value of attribute volume_detect_command.
Instance Attribute Summary collapse
-
#input ⇒ Object
Returns the value of attribute input.
-
#outputs ⇒ Object
Returns the value of attribute outputs.
Class Method Summary collapse
- .concat(inputs, output, method = nil) ⇒ Object
- .mux(inputs, output) ⇒ Object
- .split(input, output) ⇒ Object
Instance Method Summary collapse
-
#initialize(input, outputs) ⇒ Ffmpeg
constructor
A new instance of Ffmpeg.
- #run ⇒ Object
Constructor Details
#initialize(input, outputs) ⇒ Ffmpeg
Returns a new instance of Ffmpeg.
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 |
# File 'lib/video_converter/ffmpeg.rb', line 57 def initialize input, outputs self.input = input self.outputs = input.select_outputs(outputs) self.outputs.each do |output| # autorotate if output.type != 'playlist' && [nil, true].include?(output.rotate) && input.[:rotate] output.rotate = 360 - input.[:rotate] end # autodeinterlace output.[:deinterlace] = input.[:interlaced] if output.[:deinterlace].nil? # volume output.[:audio_filter] = "volume=#{volume(output.volume)}" if output.volume # filter_complex filter_complex = [output.[:filter_complex]].compact filter_complex << "crop=#{output.crop}" if output.crop if output.width || output.height output.width = (output.height * aspect(input, output)).ceil / 2 * 2 if output.height && !output.width output.height = (output.width / aspect(input, output)).ceil / 2 * 2 if output.width && !output.height filter_complex << "scale=#{scale(output.width, :w)}:#{scale(output.height, :h)}" if output.[:aspect] filter_complex << "setdar=#{output..delete(:aspect)}" elsif input.video_stream[:dar_width] && input.video_stream[:dar_height] filter_complex << "setdar=#{input.video_stream[:dar_width]}:#{input.video_stream[:dar_height]}" end end if output.watermarks && (output.watermarks[:width] || output.watermarks[:height]) filter_complex = ["[0:v] #{filter_complex.join(',')} [main]"] filter_complex << "[1:v] scale=#{scale(output.watermarks[:width], :w, output.width)}:#{scale(output.watermarks[:height], :h, output.height)} [overlay]" filter_complex << "[main] [overlay] overlay=#{(output.watermarks[:x], :w)}:#{(output.watermarks[:y], :h)}" if output.rotate filter_complex[filter_complex.count-1] += ' [overlayed]' filter_complex << '[overlayed] ' + rotate(output.rotate) end output.[:filter_complex] = "'#{filter_complex.join(';')}'" else filter_complex << "overlay=#{(output.watermarks[:x], :w)}:#{(output.watermarks[:y], :h)}" if output.watermarks filter_complex << rotate(output.rotate) if output.rotate output.[:filter_complex] = filter_complex.join(',') if filter_complex.any? end output.[:format] ||= File.extname(output.filename).delete('.') output. = { :threads => 1, :video_codec => 'libx264', :audio_codec => 'libfaac', :pixel_format => 'yuv420p' }.merge(output.) unless output.type == 'playlist' end end |
Class Attribute Details
.aliases ⇒ Object
Returns the value of attribute aliases.
6 7 8 |
# File 'lib/video_converter/ffmpeg.rb', line 6 def aliases @aliases end |
.bin ⇒ Object
Returns the value of attribute bin.
6 7 8 |
# File 'lib/video_converter/ffmpeg.rb', line 6 def bin @bin end |
.concat_command ⇒ Object
Returns the value of attribute concat_command.
7 8 9 |
# File 'lib/video_converter/ffmpeg.rb', line 7 def concat_command @concat_command end |
.ffprobe_bin ⇒ Object
Returns the value of attribute ffprobe_bin.
6 7 8 |
# File 'lib/video_converter/ffmpeg.rb', line 6 def ffprobe_bin @ffprobe_bin end |
.first_pass_command ⇒ Object
Returns the value of attribute first_pass_command.
7 8 9 |
# File 'lib/video_converter/ffmpeg.rb', line 7 def first_pass_command @first_pass_command end |
.keyframes_command ⇒ Object
Returns the value of attribute keyframes_command.
7 8 9 |
# File 'lib/video_converter/ffmpeg.rb', line 7 def keyframes_command @keyframes_command end |
.mux_command ⇒ Object
Returns the value of attribute mux_command.
7 8 9 |
# File 'lib/video_converter/ffmpeg.rb', line 7 def mux_command @mux_command end |
.one_pass_command ⇒ Object
Returns the value of attribute one_pass_command.
7 8 9 |
# File 'lib/video_converter/ffmpeg.rb', line 7 def one_pass_command @one_pass_command end |
.second_pass_command ⇒ Object
Returns the value of attribute second_pass_command.
7 8 9 |
# File 'lib/video_converter/ffmpeg.rb', line 7 def second_pass_command @second_pass_command end |
.split_command ⇒ Object
Returns the value of attribute split_command.
7 8 9 |
# File 'lib/video_converter/ffmpeg.rb', line 7 def split_command @split_command end |
.volume_detect_command ⇒ Object
Returns the value of attribute volume_detect_command.
7 8 9 |
# File 'lib/video_converter/ffmpeg.rb', line 7 def volume_detect_command @volume_detect_command end |
Instance Attribute Details
#input ⇒ Object
Returns the value of attribute input.
55 56 57 |
# File 'lib/video_converter/ffmpeg.rb', line 55 def input @input end |
#outputs ⇒ Object
Returns the value of attribute outputs.
55 56 57 |
# File 'lib/video_converter/ffmpeg.rb', line 55 def outputs @outputs end |
Class Method Details
.concat(inputs, output, method = nil) ⇒ Object
41 42 43 44 45 |
# File 'lib/video_converter/ffmpeg.rb', line 41 def self.concat(inputs, output, method = nil) method = %w(ts mpg mpeg).include?(File.extname(inputs.first.to_s).delete('.')) ? :protocol : :muxer unless method output. = { :codec => 'copy' }.merge(output.) send("concat_#{method}", inputs, output) end |
.mux(inputs, output) ⇒ Object
47 48 49 50 51 52 53 |
# File 'lib/video_converter/ffmpeg.rb', line 47 def self.mux(inputs, output) output. = { :codec => 'copy' }.merge(output.) Command.new(mux_command, prepare_params(nil, output).merge({ :inputs => inputs.map { |i| "-i #{i}" }.join(' '), :maps => inputs.each_with_index.map { |_,i| "-map #{i}:0" }.join(' ') })).execute end |
Instance Method Details
#run ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/video_converter/ffmpeg.rb', line 108 def run success = true threads = [] input.output_groups(outputs).each_with_index do |group, group_index| qualities = group.select { |output| output.type != 'playlist' } # common first pass if !one_pass?(qualities) && common_first_pass?(qualities) qualities.each do |output| output.[:passlogfile] = File.join(output.work_dir, "group#{group_index}.log") output.[:keyint_min] = 25 output.[:keyframe_interval] = 100 end best_quality = qualities.sort do |q1, q2| res = q1.[:video_bitrate].to_i <=> q2.[:video_bitrate].to_i res = q1.height.to_i <=> q2.height.to_i if res == 0 res = q1.width.to_i <=> q2.width.to_i if res == 0 # TODO compare by size res end.last success &&= Command.new(self.class.first_pass_command, self.class.prepare_params(input, best_quality)).execute end qualities.each_with_index do |output, output_index| command = if one_pass?(qualities) self.class.one_pass_command elsif common_first_pass?(qualities) self.class.second_pass_command else output.[:passlogfile] = File.join(output.work_dir, "group#{group_index}_#{output_index}.log") output.[:force_key_frames] = (input.[:duration_in_ms] / 1000.0 / Output.keyframe_interval_in_seconds).ceil.times.to_a.map { |t| t * Output.keyframe_interval_in_seconds }.join(',') Command.chain(self.class.first_pass_command, self.class.second_pass_command) end # run ffmpeg command = Command.new(command, self.class.prepare_params(input, output)) if VideoConverter.paral threads << Thread.new { success &&= command.execute } else success &&= command.execute end end end threads.each { |t| t.join } if VideoConverter.paral success end |