Class: FFMPEG::Movie

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ Movie

Returns a new instance of Movie.

Raises:

  • (Errno::ENOENT)


11
12
13
14
15
16
17
18
19
20
21
22
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
55
56
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
# 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)

   = MultiJson.load(std_output, symbolize_keys: true)

  if .key?(:error)

    @duration = 0

  else

    video_streams = [:streams].select { |stream| stream.key?(:codec_type) and stream[:codec_type] === 'video' }
    audio_streams = [:streams].select { |stream| stream.key?(:codec_type) and stream[:codec_type] === 'audio' }

    @container = [:format][:format_name]

    @duration = [:format][:duration].to_f

    @time = [:format][:start_time].to_f

    @creation_time = if [:format].key?(:tags) and [:format][:tags].key?(:creation_time)
                       Time.parse([:format][:tags][:creation_time])
                     else
                       nil
                     end

    @bitrate = [: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 .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

Instance Attribute Details

#audio_bitrateObject (readonly)

Returns the value of attribute audio_bitrate.



8
9
10
# File 'lib/ffmpeg/movie.rb', line 8

def audio_bitrate
  @audio_bitrate
end

#audio_channelsObject (readonly)

Returns the value of attribute audio_channels.



8
9
10
# File 'lib/ffmpeg/movie.rb', line 8

def audio_channels
  @audio_channels
end

#audio_codecObject (readonly)

Returns the value of attribute audio_codec.



8
9
10
# File 'lib/ffmpeg/movie.rb', line 8

def audio_codec
  @audio_codec
end

#audio_sample_rateObject (readonly)

Returns the value of attribute audio_sample_rate.



8
9
10
# File 'lib/ffmpeg/movie.rb', line 8

def audio_sample_rate
  @audio_sample_rate
end

#audio_streamObject (readonly)

Returns the value of attribute audio_stream.



8
9
10
# File 'lib/ffmpeg/movie.rb', line 8

def audio_stream
  @audio_stream
end

#bitrateObject (readonly)

Returns the value of attribute bitrate.



6
7
8
# File 'lib/ffmpeg/movie.rb', line 6

def bitrate
  @bitrate
end

#colorspaceObject (readonly)

Returns the value of attribute colorspace.



7
8
9
# File 'lib/ffmpeg/movie.rb', line 7

def colorspace
  @colorspace
end

#containerObject (readonly)

Returns the value of attribute container.



9
10
11
# File 'lib/ffmpeg/movie.rb', line 9

def container
  @container
end

#creation_timeObject (readonly)

Returns the value of attribute creation_time.



6
7
8
# File 'lib/ffmpeg/movie.rb', line 6

def creation_time
  @creation_time
end

#darObject (readonly)

Returns the value of attribute dar.



7
8
9
# File 'lib/ffmpeg/movie.rb', line 7

def dar
  @dar
end

#durationObject (readonly)

Returns the value of attribute duration.



6
7
8
# File 'lib/ffmpeg/movie.rb', line 6

def duration
  @duration
end

#frame_rateObject (readonly)

Returns the value of attribute frame_rate.



7
8
9
# File 'lib/ffmpeg/movie.rb', line 7

def frame_rate
  @frame_rate
end

#heightObject (readonly)

Returns the value of attribute height.



7
8
9
# File 'lib/ffmpeg/movie.rb', line 7

def height
  @height
end

#pathObject (readonly)

Returns the value of attribute path.



6
7
8
# File 'lib/ffmpeg/movie.rb', line 6

def path
  @path
end

#rotationObject (readonly)

Returns the value of attribute rotation.



6
7
8
# File 'lib/ffmpeg/movie.rb', line 6

def rotation
  @rotation
end

#sarObject (readonly)

Returns the value of attribute sar.



7
8
9
# File 'lib/ffmpeg/movie.rb', line 7

def sar
  @sar
end

#timeObject (readonly)

Returns the value of attribute time.



6
7
8
# File 'lib/ffmpeg/movie.rb', line 6

def time
  @time
end

#video_bitrateObject (readonly)

Returns the value of attribute video_bitrate.



7
8
9
# File 'lib/ffmpeg/movie.rb', line 7

def video_bitrate
  @video_bitrate
end

#video_codecObject (readonly)

Returns the value of attribute video_codec.



7
8
9
# File 'lib/ffmpeg/movie.rb', line 7

def video_codec
  @video_codec
end

#video_streamObject (readonly)

Returns the value of attribute video_stream.



7
8
9
# File 'lib/ffmpeg/movie.rb', line 7

def video_stream
  @video_stream
end

#widthObject (readonly)

Returns the value of attribute width.



7
8
9
# File 'lib/ffmpeg/movie.rb', line 7

def width
  @width
end

Instance Method Details

#audio_channel_layoutObject



128
129
130
131
132
133
134
135
136
137
138
139
140
# 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_ratioObject



116
117
118
# File 'lib/ffmpeg/movie.rb', line 116

def calculated_aspect_ratio
  aspect_from_dar || aspect_from_dimensions
end

#calculated_pixel_aspect_ratioObject



120
121
122
# File 'lib/ffmpeg/movie.rb', line 120

def calculated_pixel_aspect_ratio
  aspect_from_sar || 1
end

#resolutionObject



110
111
112
113
114
# 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) ⇒ Object



146
147
148
# 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

#sizeObject



124
125
126
# File 'lib/ffmpeg/movie.rb', line 124

def size
  File.size(@path)
end

#transcode(output_file, options = EncodingOptions.new, transcoder_options = {}, &block) ⇒ Object



142
143
144
# 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?Boolean

Returns:

  • (Boolean)


98
99
100
# File 'lib/ffmpeg/movie.rb', line 98

def valid?
  not @invalid
end