Class: FFMPEG::Movie
- Inherits:
-
Object
- Object
- FFMPEG::Movie
- Defined in:
- lib/ffmpeg/movie.rb
Constant Summary collapse
- UNSUPPORTED_CODEC_PATTERN =
/^Unsupported codec with id (\d+) for input stream (\d+)$/
Instance Attribute Summary collapse
-
#audio_bitrate ⇒ Object
readonly
Returns the value of attribute audio_bitrate.
-
#audio_channels ⇒ Object
readonly
Returns the value of attribute audio_channels.
-
#audio_codec ⇒ Object
readonly
Returns the value of attribute audio_codec.
-
#audio_sample_fmt ⇒ Object
readonly
Returns the value of attribute audio_sample_fmt.
-
#audio_sample_rate ⇒ Object
readonly
Returns the value of attribute audio_sample_rate.
-
#audio_stream ⇒ Object
readonly
Returns the value of attribute audio_stream.
-
#audio_streams ⇒ Object
readonly
Returns the value of attribute audio_streams.
-
#audio_tags ⇒ Object
readonly
Returns the value of attribute audio_tags.
-
#bitrate ⇒ Object
readonly
Returns the value of attribute bitrate.
-
#colorspace ⇒ Object
readonly
Returns the value of attribute colorspace.
-
#container ⇒ Object
readonly
Returns the value of attribute container.
-
#creation_time ⇒ Object
readonly
Returns the value of attribute creation_time.
-
#dar ⇒ Object
readonly
Returns the value of attribute dar.
-
#duration ⇒ Object
readonly
Returns the value of attribute duration.
-
#format_tags ⇒ Object
readonly
Returns the value of attribute format_tags.
-
#frame_rate ⇒ Object
readonly
Returns the value of attribute frame_rate.
-
#height ⇒ Object
readonly
Returns the value of attribute height.
-
#metadata ⇒ Object
readonly
Returns the value of attribute metadata.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
-
#rotation ⇒ Object
readonly
Returns the value of attribute rotation.
-
#sar ⇒ Object
readonly
Returns the value of attribute sar.
-
#time ⇒ Object
readonly
Returns the value of attribute time.
-
#video_bitrate ⇒ Object
readonly
Returns the value of attribute video_bitrate.
-
#video_codec ⇒ Object
readonly
Returns the value of attribute video_codec.
-
#video_stream ⇒ Object
readonly
Returns the value of attribute video_stream.
-
#width ⇒ Object
readonly
Returns the value of attribute width.
Instance Method Summary collapse
- #audio_channel_layout ⇒ Object
- #calculated_aspect_ratio ⇒ Object
- #calculated_pixel_aspect_ratio ⇒ Object
-
#initialize(path) ⇒ Movie
constructor
A new instance of Movie.
- #local? ⇒ Boolean
- #remote? ⇒ Boolean
- #resolution ⇒ Object
- #screenshot(output_file, options = EncodingOptions.new, transcoder_options = {}, &block) ⇒ Object
- #size ⇒ Object
- #transcode(output_file, options = EncodingOptions.new, transcoder_options = {}, &block) ⇒ Object
- #unsupported_streams(std_error) ⇒ Object
- #valid? ⇒ Boolean
Constructor Details
#initialize(path) ⇒ Movie
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 97 98 99 100 101 102 103 104 105 106 107 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 |
# File 'lib/ffmpeg/movie.rb', line 15 def initialize(path) @path = path if remote? @head = head raise Errno::ENOENT, "the URL '#{path}' does not exist" unless @head.is_a?(Net::HTTPSuccess) else raise Errno::ENOENT, "the file '#{path}' does not exist" unless File.exist?(path) end @path = path # ffmpeg will output to stderr command = [FFMPEG.ffprobe_binary, '-i', path, *%w(-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) fix_encoding(std_error) begin = MultiJson.load(std_output, symbolize_keys: true) rescue MultiJson::ParseError raise "Could not parse output from FFProbe:\n#{ std_output }" end 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 = [:format][:tags] @creation_time = if and .key?(:creation_time) begin Time.parse([:creation_time]) rescue ArgumentError nil end else nil end @bitrate = [:format][:bit_rate].to_i # TODO: Handle multiple video codecs (is that possible?) video_stream = video_streams.first unless video_stream.nil? @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 @audio_streams = audio_streams.map do |stream| { :index => stream[:index], :channels => stream[:channels].to_i, :codec_name => stream[:codec_name], :sample_rate => stream[:sample_rate].to_i, :bitrate => stream[:bit_rate].to_i, :channel_layout => stream[:channel_layout], :tags => stream[:streams], :sample_fmt => stream[:sample_fmt], :overview => "#{stream[:codec_name]} (#{stream[:codec_tag_string]} / #{stream[:codec_tag]}), #{stream[:sample_rate]} Hz, #{stream[:channel_layout]}, #{stream[:sample_fmt]}, #{stream[:bit_rate]} bit/s" } end audio_stream = @audio_streams.first unless audio_stream.nil? @audio_channels = audio_stream[:channels] @audio_codec = audio_stream[:codec_name] @audio_sample_rate = audio_stream[:sample_rate] @audio_bitrate = audio_stream[:bitrate] @audio_channel_layout = audio_stream[:channel_layout] = audio_stream[:audio_tags] @audio_sample_fmt = audio_stream[:sample_fmt] @audio_stream = audio_stream[:overview] end end unsupported_stream_ids = unsupported_streams(std_error) nil_or_unsupported = -> (stream) { stream.nil? || unsupported_stream_ids.include?(stream[:index]) } @invalid = true if nil_or_unsupported.(video_stream) && nil_or_unsupported.(audio_stream) @invalid = true if .key?(:error) @invalid = true if std_error.include?("could not find codec parameters") end |
Instance Attribute Details
#audio_bitrate ⇒ Object (readonly)
Returns the value of attribute audio_bitrate.
9 10 11 |
# File 'lib/ffmpeg/movie.rb', line 9 def audio_bitrate @audio_bitrate end |
#audio_channels ⇒ Object (readonly)
Returns the value of attribute audio_channels.
9 10 11 |
# File 'lib/ffmpeg/movie.rb', line 9 def audio_channels @audio_channels end |
#audio_codec ⇒ Object (readonly)
Returns the value of attribute audio_codec.
9 10 11 |
# File 'lib/ffmpeg/movie.rb', line 9 def audio_codec @audio_codec end |
#audio_sample_fmt ⇒ Object (readonly)
Returns the value of attribute audio_sample_fmt.
9 10 11 |
# File 'lib/ffmpeg/movie.rb', line 9 def audio_sample_fmt @audio_sample_fmt end |
#audio_sample_rate ⇒ Object (readonly)
Returns the value of attribute audio_sample_rate.
9 10 11 |
# File 'lib/ffmpeg/movie.rb', line 9 def audio_sample_rate @audio_sample_rate end |
#audio_stream ⇒ Object (readonly)
Returns the value of attribute audio_stream.
9 10 11 |
# File 'lib/ffmpeg/movie.rb', line 9 def audio_stream @audio_stream end |
#audio_streams ⇒ Object (readonly)
Returns the value of attribute audio_streams.
9 10 11 |
# File 'lib/ffmpeg/movie.rb', line 9 def audio_streams @audio_streams end |
#audio_tags ⇒ Object (readonly)
Returns the value of attribute audio_tags.
9 10 11 |
# File 'lib/ffmpeg/movie.rb', line 9 def end |
#bitrate ⇒ Object (readonly)
Returns the value of attribute bitrate.
7 8 9 |
# File 'lib/ffmpeg/movie.rb', line 7 def bitrate @bitrate end |
#colorspace ⇒ Object (readonly)
Returns the value of attribute colorspace.
8 9 10 |
# File 'lib/ffmpeg/movie.rb', line 8 def colorspace @colorspace end |
#container ⇒ Object (readonly)
Returns the value of attribute container.
10 11 12 |
# File 'lib/ffmpeg/movie.rb', line 10 def container @container end |
#creation_time ⇒ Object (readonly)
Returns the value of attribute creation_time.
7 8 9 |
# File 'lib/ffmpeg/movie.rb', line 7 def creation_time @creation_time end |
#dar ⇒ Object (readonly)
Returns the value of attribute dar.
8 9 10 |
# File 'lib/ffmpeg/movie.rb', line 8 def dar @dar end |
#duration ⇒ Object (readonly)
Returns the value of attribute duration.
7 8 9 |
# File 'lib/ffmpeg/movie.rb', line 7 def duration @duration end |
#format_tags ⇒ Object (readonly)
Returns the value of attribute format_tags.
11 12 13 |
# File 'lib/ffmpeg/movie.rb', line 11 def end |
#frame_rate ⇒ Object (readonly)
Returns the value of attribute frame_rate.
8 9 10 |
# File 'lib/ffmpeg/movie.rb', line 8 def frame_rate @frame_rate end |
#height ⇒ Object (readonly)
Returns the value of attribute height.
8 9 10 |
# File 'lib/ffmpeg/movie.rb', line 8 def height @height end |
#metadata ⇒ Object (readonly)
Returns the value of attribute metadata.
11 12 13 |
# File 'lib/ffmpeg/movie.rb', line 11 def end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
7 8 9 |
# File 'lib/ffmpeg/movie.rb', line 7 def path @path end |
#rotation ⇒ Object (readonly)
Returns the value of attribute rotation.
7 8 9 |
# File 'lib/ffmpeg/movie.rb', line 7 def rotation @rotation end |
#sar ⇒ Object (readonly)
Returns the value of attribute sar.
8 9 10 |
# File 'lib/ffmpeg/movie.rb', line 8 def sar @sar end |
#time ⇒ Object (readonly)
Returns the value of attribute time.
7 8 9 |
# File 'lib/ffmpeg/movie.rb', line 7 def time @time end |
#video_bitrate ⇒ Object (readonly)
Returns the value of attribute video_bitrate.
8 9 10 |
# File 'lib/ffmpeg/movie.rb', line 8 def video_bitrate @video_bitrate end |
#video_codec ⇒ Object (readonly)
Returns the value of attribute video_codec.
8 9 10 |
# File 'lib/ffmpeg/movie.rb', line 8 def video_codec @video_codec end |
#video_stream ⇒ Object (readonly)
Returns the value of attribute video_stream.
8 9 10 |
# File 'lib/ffmpeg/movie.rb', line 8 def video_stream @video_stream end |
#width ⇒ Object (readonly)
Returns the value of attribute width.
8 9 10 |
# File 'lib/ffmpeg/movie.rb', line 8 def width @width end |
Instance Method Details
#audio_channel_layout ⇒ Object
187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/ffmpeg/movie.rb', line 187 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_ratio ⇒ Object
171 172 173 |
# File 'lib/ffmpeg/movie.rb', line 171 def calculated_aspect_ratio aspect_from_dar || aspect_from_dimensions end |
#calculated_pixel_aspect_ratio ⇒ Object
175 176 177 |
# File 'lib/ffmpeg/movie.rb', line 175 def calculated_pixel_aspect_ratio aspect_from_sar || 1 end |
#local? ⇒ Boolean
153 154 155 |
# File 'lib/ffmpeg/movie.rb', line 153 def local? not remote? end |
#remote? ⇒ Boolean
149 150 151 |
# File 'lib/ffmpeg/movie.rb', line 149 def remote? @path =~ URI::regexp(%w(http https)) end |
#resolution ⇒ Object
165 166 167 168 169 |
# File 'lib/ffmpeg/movie.rb', line 165 def resolution unless width.nil? or height.nil? "#{width}x#{height}" end end |
#screenshot(output_file, options = EncodingOptions.new, transcoder_options = {}, &block) ⇒ Object
205 206 207 |
# File 'lib/ffmpeg/movie.rb', line 205 def screenshot(output_file, = EncodingOptions.new, = {}, &block) Transcoder.new(self, output_file, .merge(screenshot: true), ).run &block end |
#size ⇒ Object
179 180 181 182 183 184 185 |
# File 'lib/ffmpeg/movie.rb', line 179 def size if local? File.size(@path) else @head.content_length end end |
#transcode(output_file, options = EncodingOptions.new, transcoder_options = {}, &block) ⇒ Object
201 202 203 |
# File 'lib/ffmpeg/movie.rb', line 201 def transcode(output_file, = EncodingOptions.new, = {}, &block) Transcoder.new(self, output_file, , ).run &block end |
#unsupported_streams(std_error) ⇒ Object
136 137 138 139 140 141 142 143 |
# File 'lib/ffmpeg/movie.rb', line 136 def unsupported_streams(std_error) [].tap do |stream_indices| std_error.each_line do |line| match = line.match(UNSUPPORTED_CODEC_PATTERN) stream_indices << match[2].to_i if match end end end |
#valid? ⇒ Boolean
145 146 147 |
# File 'lib/ffmpeg/movie.rb', line 145 def valid? not @invalid end |