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_rate ⇒ Object
readonly
Returns the value of attribute audio_sample_rate.
-
#audio_stream ⇒ Object
readonly
Returns the value of attribute audio_stream.
-
#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
Returns a new instance of 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 |
# 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 @metadata = MultiJson.load(std_output, symbolize_keys: true) rescue MultiJson::ParseError raise "Could not parse output from FFProbe:\n#{ std_output }" end if @metadata.key?(:error) @duration = 0 else video_streams = @metadata[:streams].select { |stream| stream.key?(:codec_type) and stream[:codec_type] === 'video' } audio_streams = @metadata[:streams].select { |stream| stream.key?(:codec_type) and stream[:codec_type] === 'audio' } @container = @metadata[:format][:format_name] @duration = @metadata[:format][:duration].to_f @time = @metadata[:format][:start_time].to_f @format_tags = @metadata[:format][:tags] @creation_time = if @format_tags and @format_tags.key?(:creation_time) begin Time.parse(@format_tags[:creation_time]) rescue ArgumentError nil end else nil end @bitrate = @metadata[: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 # TODO: Handle multiple audio codecs audio_stream = audio_streams.first unless audio_stream.nil? @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 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 @metadata.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_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 |
#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 @format_tags 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 @metadata 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
172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/ffmpeg/movie.rb', line 172 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
156 157 158 |
# File 'lib/ffmpeg/movie.rb', line 156 def calculated_aspect_ratio aspect_from_dar || aspect_from_dimensions end |
#calculated_pixel_aspect_ratio ⇒ Object
160 161 162 |
# File 'lib/ffmpeg/movie.rb', line 160 def calculated_pixel_aspect_ratio aspect_from_sar || 1 end |
#local? ⇒ Boolean
138 139 140 |
# File 'lib/ffmpeg/movie.rb', line 138 def local? not remote? end |
#remote? ⇒ Boolean
134 135 136 |
# File 'lib/ffmpeg/movie.rb', line 134 def remote? @path =~ URI::regexp(%w(http https)) end |
#resolution ⇒ Object
150 151 152 153 154 |
# File 'lib/ffmpeg/movie.rb', line 150 def resolution unless width.nil? or height.nil? "#{width}x#{height}" end end |
#screenshot(output_file, options = EncodingOptions.new, transcoder_options = {}, &block) ⇒ Object
190 191 192 |
# File 'lib/ffmpeg/movie.rb', line 190 def screenshot(output_file, = EncodingOptions.new, = {}, &block) Transcoder.new(self, output_file, .merge(screenshot: true), ).run &block end |
#size ⇒ Object
164 165 166 167 168 169 170 |
# File 'lib/ffmpeg/movie.rb', line 164 def size if local? File.size(@path) else @head.content_length end end |
#transcode(output_file, options = EncodingOptions.new, transcoder_options = {}, &block) ⇒ Object
186 187 188 |
# File 'lib/ffmpeg/movie.rb', line 186 def transcode(output_file, = EncodingOptions.new, = {}, &block) Transcoder.new(self, output_file, , ).run &block end |
#unsupported_streams(std_error) ⇒ Object
121 122 123 124 125 126 127 128 |
# File 'lib/ffmpeg/movie.rb', line 121 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
130 131 132 |
# File 'lib/ffmpeg/movie.rb', line 130 def valid? not @invalid end |