Class: FFMPEG::Transcoder

Inherits:
Object
  • Object
show all
Defined in:
lib/ffmpeg/transcoder.rb

Instance Method Summary collapse

Constructor Details

#initialize(movie, output_file, options = EncodingOptions.new, transcoder_options = {}) ⇒ Transcoder

Returns a new instance of Transcoder.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/ffmpeg/transcoder.rb', line 5

def initialize(movie, output_file, options = EncodingOptions.new, transcoder_options = {})
  @movie = movie
  @output_file = output_file
  
  if options.is_a?(String) || 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."
  end
  
  @transcoder_options = transcoder_options
  @errors = []
  
  apply_transcoder_options
end

Instance Method Details

#encodedObject



78
79
80
# File 'lib/ffmpeg/transcoder.rb', line 78

def encoded
  @encoded ||= Movie.new(@output_file)
end

#encoding_succeeded?Boolean

Returns:

  • (Boolean)


56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/ffmpeg/transcoder.rb', line 56

def encoding_succeeded?
  unless File.exists?(@output_file)
    @errors << "no output file created"
    return false
  end
  
  unless encoded.valid?
    @errors << "encoded file is invalid"
    return false
  end
  
  if validate_duration?
    precision = 1.1
    unless !(encoded.duration >= (@movie.duration * precision) or encoded.duration <= (@movie.duration / precision))
      @errors << "encoded file duration differed from original (original: #{@movie.duration}sec, encoded: #{encoded.duration}sec)"
      return false
    end
  end
  
  true
end

#runObject



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/ffmpeg/transcoder.rb', line 23

def run
  command = "ffmpeg -y -i '#{@movie.path}' #{@raw_options} '#{@output_file}'"
  FFMPEG.logger.info("Running transcoding...\n#{command}\n")
  output = ""
  last_output = nil
  Open3.popen3(command) do |stdin, stdout, stderr|
    stderr.each("r") do |line|
      output << line
      if line =~ /time=(\d+.\d+)/
        time = $1.to_f
        progress = time / @movie.duration
        yield(progress) if block_given?
      end
      if line =~ /Unsupported codec/
        FFMPEG.logger.error "Failed encoding...\nCommand\n#{command}\nOutput\n#{output}\n"
        raise "Failed encoding: #{line}"
      end
      last_output = line
    end
  end

  if encoding_succeeded?
    FFMPEG.logger.info "Transcoding of #{@movie.path} to #{@output_file} succeeded\n"
    yield(1.0) if block_given?
  else
    errors = @errors.empty? ? "" : "Errors: #{@errors.join(", ")}"
    FFMPEG.logger.error "Failed encoding...\n#{command}\n\n#{output}\n#{errors}\n"
    raise "Failed encoding. Last output: #{last_output}. #{errors}"
  end
  
  encoded
end