Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple inputs support #61

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions lib/ffmpeg/encoding_options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,14 @@ def convert_x264_preset(value)
"-preset #{value}"
end

def convert_scale(value)
value ? "-filter:v scale=#{value}" : ""
end

def convert_deinterlace(value)
value ? "-filter:v #{value}" : ""
end

def convert_custom(value)
value
end
Expand Down
26 changes: 19 additions & 7 deletions lib/ffmpeg/movie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,28 @@

module FFMPEG
class Movie
attr_reader :path, :duration, :time, :bitrate, :rotation, :creation_time
attr_reader :paths, :duration, :time, :bitrate, :rotation, :creation_time
attr_reader :video_stream, :video_codec, :video_bitrate, :colorspace, :resolution, :dar
attr_reader :audio_stream, :audio_codec, :audio_bitrate, :audio_sample_rate
attr_reader :container

def initialize(path)
raise Errno::ENOENT, "the file '#{path}' does not exist" unless File.exists?(path)
def initialize(paths)
paths = [paths] unless paths.is_a? Array

@path = path
inputs = []
paths.each do |path|
raise Errno::ENOENT, "the file '#{path}' does not exist" unless File.exists?(path)
inputs.push Shellwords.escape(path)
end

@paths = paths

# ffmpeg will output to stderr
command = "#{FFMPEG.ffmpeg_binary} -i #{Shellwords.escape(path)}"
output = Open3.popen3(command) { |stdin, stdout, stderr| stderr.read }
source = (inputs.length > 1) ? "-f concat -i <(printf 'file %s\n' #{inputs.join " "})" : "-i #{inputs.first}"
command = "#{FFMPEG.ffmpeg_binary} #{source}"
command = "/bin/bash -c \"#{command}\""

output = Open3.popen3(command) { |stdin, stdout, stderr| stderr.read }
fix_encoding(output)

output[/Input \#\d+\,\s*(\S+),\s*from/]
Expand Down Expand Up @@ -77,7 +85,11 @@ def calculated_aspect_ratio
end

def size
File.size(@path)
size = 0
@paths.each do |path|
size += File.size(path)
end
size
end

def audio_channels
Expand Down
16 changes: 11 additions & 5 deletions lib/ffmpeg/transcoder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,18 @@ def encoded
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)}"
inputs = @movie.paths.map {|path| Shellwords.escape(path)}
source = (inputs.length > 1) ? "-f concat -i <(printf 'file %s\n' #{inputs.join " "})" : "-i #{inputs.first}"

@command = "#{FFMPEG.ffmpeg_binary} -y #{source} #{@raw_options} #{Shellwords.escape(@output_file)}"
@command = "/bin/bash -c \"#{@command}\""

FFMPEG.logger.info("Running transcoding...\n#{@command}\n")
@output = ""

Open3.popen3(@command) do |stdin, stdout, stderr, wait_thr|
begin
yield(0.0) if block_given?
#yield([0.0, "00:00:00.00"]) if block_given? # the progress could be unknown in case multiple inputs are used
next_line = Proc.new do |line|
fix_encoding(line)
@output << line
Expand All @@ -70,8 +75,9 @@ def transcode_movie
else # better make sure it wont blow up in case of unexpected output
time = 0.0
end
processed = "#{$1}:#{$2}:#{$3}"
progress = time / @movie.duration
yield(progress) if block_given?
yield([progress, processed]) if block_given?
end
end

Expand All @@ -90,8 +96,8 @@ def transcode_movie

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"
#yield(1.0) if block_given? # the progress could be unknown in case multiple inputs are used
FFMPEG.logger.info "Transcoding of #{@movie.paths.join ", "} to #{@output_file} succeeded\n"
else
errors = "Errors: #{@errors.join(", ")}. "
FFMPEG.logger.error "Failed encoding...\n#{@command}\n\n#{@output}\n#{errors}\n"
Expand Down
2 changes: 1 addition & 1 deletion lib/ffmpeg/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module FFMPEG
VERSION = "1.0.0"
VERSION = "1.0.2"
end
2 changes: 1 addition & 1 deletion spec/ffmpeg/movie_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ module FFMPEG
end

it "should remember the movie path" do
@movie.path.should == "#{fixture_path}/movies/awesome movie.mov"
@movie.paths.should == ["#{fixture_path}/movies/awesome movie.mov"]
end

it "should parse duration to number of seconds" do
Expand Down
4 changes: 2 additions & 2 deletions spec/ffmpeg/transcoder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ module FFMPEG
progress_updates = []
transcoder.run { |progress| progress_updates << progress }
transcoder.encoded.should be_valid
progress_updates.should include(0.0, 1.0)
progress_updates.length.should >= 3
progress_updates.flatten.should include("00:00:07.58")
progress_updates.flatten.length.should >= 1
File.exists?("#{tmp_path}/awesome.flv").should be_true
end

Expand Down