mediainfo-simple 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 774cc9754389bb59899baaef43c768b00217f574
4
+ data.tar.gz: d498ba562edaeff68d4a457f81498c7cb5a06469
5
+ SHA512:
6
+ metadata.gz: 97a7730eb1e19f7ccfccf0e22c763c055cb95b9e4e043da0361ef5da8e752ad35658a39ded36c9f652e0bb5725d2d0a1974da5d6d6a7018834470d0bfa4eb0db
7
+ data.tar.gz: 50930e665b202f107715d1bb6cb501e5a77f111b9e467ef7540d7ac91f84dd85dc558f3333bae5b5680cce4b42916eefebb08ec5d179d19ee23f6a702d791ee9
@@ -0,0 +1,101 @@
1
+ require 'mediainfo-simple/parser'
2
+ require 'mediainfo-simple/stream_factory'
3
+ require 'mediainfo-simple/stream'
4
+ require 'mediainfo-simple/streams/audio'
5
+ require 'mediainfo-simple/streams/video'
6
+ require 'mediainfo-simple/streams/text'
7
+ require 'mediainfo-simple/streams/image'
8
+ require 'mediainfo-simple/streams/general'
9
+ require 'mediainfo-simple/streams/menu'
10
+ require 'mediainfo-simple/streams/other'
11
+
12
+
13
+ class MediaInfo
14
+
15
+ attr_accessor :streams
16
+
17
+ def initialize filename
18
+ # we check that the file exist
19
+ raise ArgumentError, "give the filename as a parameter (got nil)" if filename == nil
20
+ raise ArgumentError, "filename must be a string" if ! filename.is_a? String
21
+ filename = File.expand_path filename
22
+ raise ArgumentError, "#{filename} does not exist" if ! File.exist? filename
23
+
24
+ # we parse the file
25
+ @streams = []
26
+ MediaInfoParser.new filename, self
27
+ end
28
+
29
+
30
+ # return true if there is a general stream, false otherwise
31
+ def general?
32
+ @streams.any? { |stream| stream.is_a? GeneralStream }
33
+ end
34
+
35
+ # return true if there is a video stream, false otherwise
36
+ def video?
37
+ @streams.any? { |stream| stream.is_a? VideoStream }
38
+ end
39
+
40
+ # return true if there is an audio stream, false otherwise
41
+ def audio?
42
+ @streams.any? { |stream| stream.is_a? AudioStream }
43
+ end
44
+
45
+ # return true if there is a text stream, false otherwise
46
+ def text?
47
+ @streams.any? { |stream| stream.is_a? TextStream }
48
+ end
49
+
50
+ # return true if there is an image stream, false otherwise
51
+ def image?
52
+ @streams.any? { |stream| stream.is_a? ImageStream }
53
+ end
54
+
55
+ # return true if there is an menu stream, false otherwise
56
+ def menu?
57
+ @streams.any? { |stream| stream.is_a? MenuStream }
58
+ end
59
+
60
+ # return true if there is an undefined stream, false otherwise
61
+ def other?
62
+ @streams.any? { |stream| stream.is_a? OtherStream }
63
+ end
64
+
65
+ # returns an array with all the video streams
66
+ def general
67
+ @streams.select { |stream| stream.is_a? GeneralStream }
68
+ end
69
+
70
+ # returns an array with all the video streams
71
+ def video
72
+ @streams.select { |stream| stream.is_a? VideoStream }
73
+ end
74
+
75
+ # returns an array with all the audio streams
76
+ def audio
77
+ @streams.select { |stream| stream.is_a? AudioStream }
78
+ end
79
+
80
+ # returns an array with all the text streams
81
+ def text
82
+ @streams.select { |stream| stream.is_a? TextStream }
83
+ end
84
+
85
+ # returns an array with all the image streams
86
+ def image
87
+ @streams.select { |stream| stream.is_a? ImageStream }
88
+ end
89
+
90
+ # returns an array with all the menu streams
91
+ def menu
92
+ @streams.select { |stream| stream.is_a? MenuStream }
93
+ end
94
+
95
+ # returns an array with all the other streams
96
+ def other
97
+ @streams.select { |stream| stream.is_a? OtherStream }
98
+ end
99
+
100
+ end
101
+
@@ -0,0 +1,95 @@
1
+ require 'rexml/document'
2
+
3
+
4
+ class MediaInfoParser
5
+ attr_accessor :mediainfo_path_verified
6
+
7
+ def initialize filename, mediainfo_object, mediainfo_path=nil
8
+ # we check that MediaInfo CLI is installed
9
+ if not mediainfo_installed? mediainfo_path
10
+ raise RuntimeError, "mediainfo command-line interface not installed"
11
+ end
12
+
13
+ # we launch the MediaInfo scan
14
+ # it will fill the MediaInfo object with the data
15
+ mediainfo_run! filename, mediainfo_object
16
+ end
17
+
18
+
19
+ private #################################################
20
+
21
+ # a method to check that MediaInfo CLI is installed
22
+ # return true if installed, false otherwise
23
+ def mediainfo_installed? mediainfo_path=nil
24
+ # if the user specified the path, we check that MediaInfo
25
+ # is installed at the path provided by the user
26
+ # else, we get path with bash command `which`
27
+ # (`which` works on Linux and Mac, but I don't know about Windows)
28
+ if mediainfo_path != nil
29
+ if File.exist? File.expand_path(mediainfo_path)
30
+ @mediainfo_path_verified = mediainfo_path
31
+ return true
32
+ else
33
+ return false
34
+ end
35
+ else
36
+ mediainfo_path = `which 'mediainfo'`.rstrip
37
+ # NB: rstrip is needed to remove final '\n'
38
+ if mediainfo_path != ""
39
+ @mediainfo_path_verified = mediainfo_path
40
+ return true
41
+ else
42
+ return false
43
+ end
44
+ end
45
+ end
46
+
47
+ # we use the mediainfo command-line interface to get the XML results
48
+ # it returns the raw XML data
49
+ def mediainfo_run! filename, mediainfo_object
50
+ command = "#{mediainfo_path_verified} '#{filename}' --Output=XML"
51
+ raw_xml_response = `#{command} 2>&1`
52
+ unless $? == 0
53
+ raise RuntimeError, "Execution of `#{command}` failed: #{raw_xml_response.inspect}"
54
+ end
55
+ parse! raw_xml_response, mediainfo_object
56
+ end
57
+
58
+ # we parse the raw XML data (with ReXML),
59
+ # and we fill the MediaInfo object attributes
60
+ def parse! raw_xml_response, mediainfo_object
61
+ # puts "#{raw_xml_response}"
62
+ REXML::Document.new(raw_xml_response).elements.each("/Mediainfo/File/track") { |track|
63
+ # we create a "Stream" object, depending on the Stream type
64
+ stream = StreamFactory.create track.attributes['type']
65
+
66
+ # we get each tag about the stream
67
+ track.children.select { |n| n.is_a? REXML::Element }.each do |c|
68
+ # we convert the tag name to a ruby-attribute-compatible name
69
+ tag_name = c.name.strip # remove whitespaces at the beginning and the end
70
+ tag_name = tag_name.gsub(/ +/, "_") # we replace spaces by '_'
71
+ # we replace characters forbidden in Ruby method names by '_':
72
+ tag_name = tag_name.gsub(/[\(\)\{\}\[\]\*\/\\,;\.:\+=\-\^\$\!\?\|@#\&"'`]+/, '_')
73
+ tag_name = tag_name.gsub(/^_+/, "") # remove '_' at the beginning
74
+ tag_name = tag_name.gsub(/_+$/, "") # remove '_' at the end
75
+ tag_name = tag_name.gsub(/_+/, "_") # we replace several '_' following by a single one
76
+ tag_name = tag_name.downcase
77
+
78
+ # if there is an attribute in the Stream class,
79
+ # that has the same name as the tag name, we set it with the tag content
80
+ if stream.class.method_defined? tag_name + "="
81
+ # we call the method which name is the content of the string tag_name
82
+ stream.send tag_name + "=", c.text.strip
83
+ else
84
+ # to print the tag ignored, in case we want to support them
85
+ # puts "#{stream.class}: tag ignored: #{tag_name}, #{c.text.strip}"
86
+ end
87
+ end
88
+
89
+ # we add the Stream objects to the MediaInfo object
90
+ mediainfo_object.streams << stream
91
+ }
92
+ end
93
+ end
94
+
95
+
@@ -0,0 +1,11 @@
1
+ class Stream
2
+ # to create aliases (getter and setter method)
3
+ # for attributes defined with attr_accessor
4
+ def self.attr_accessor_alias alias_name, alias_target
5
+ alias_method alias_name, alias_target # alias for the getter
6
+ alias_method alias_name.to_s+'=', alias_target.to_s+'=' # alias for the setter
7
+ end
8
+
9
+ attr_accessor :id
10
+ attr_accessor_alias :stream_id, :id
11
+ end
@@ -0,0 +1,14 @@
1
+ class StreamFactory
2
+ def self.create stream_type
3
+ raise ArgumentError, "need a stream_type, received #{stream_type.inspect}" if stream_type.nil?
4
+
5
+ # we check that there is a subclass of stream for this stream
6
+ stream_class_name = "#{stream_type}Stream"
7
+ if not Object.const_defined? stream_class_name
8
+ raise "bad stream type: #{stream_type.inspect}"
9
+ end
10
+
11
+ # we return a (subclass of) Stream object
12
+ return Object.const_get(stream_class_name).new
13
+ end
14
+ end
@@ -0,0 +1,39 @@
1
+ class AudioStream < Stream
2
+ attr_accessor :duration
3
+ attr_accessor :language
4
+
5
+ attr_accessor :sampling_count
6
+ attr_accessor :sampling_rate
7
+ attr_accessor_alias :sample_rate, :sampling_rate
8
+
9
+ attr_accessor :stream_size
10
+ attr_accessor :bit_rate
11
+ attr_accessor :bit_rate_mode
12
+ attr_accessor :interleave_duration
13
+
14
+ attr_accessor :resolution
15
+ attr_accessor_alias :sample_bit_depth, :resolution
16
+
17
+ attr_accessor :format
18
+ attr_accessor :format_profile
19
+ attr_accessor :format_version
20
+ attr_accessor :format_info
21
+ attr_accessor :format_settings_sbr
22
+ attr_accessor :format_settings_endianness
23
+ attr_accessor :format_settings_sign
24
+ attr_accessor :codec_id
25
+ attr_accessor :codec_info
26
+ attr_accessor :codec
27
+ attr_accessor :codec_id_hint
28
+ attr_accessor :channel_positions
29
+
30
+ attr_accessor :channel_s
31
+ def stereo?; channels == 2; end
32
+ def mono?; channels == 1; end
33
+
34
+ attr_accessor :encoded_date
35
+ attr_accessor :tagged_date
36
+
37
+ attr_accessor :menu_id
38
+ end
39
+
@@ -0,0 +1,31 @@
1
+ class GeneralStream < Stream
2
+ attr_accessor :complete_name
3
+ attr_accessor :file_size
4
+ attr_accessor :duration
5
+
6
+ attr_accessor :format
7
+ attr_accessor :format_profile
8
+ attr_accessor :format_info
9
+ attr_accessor :codec
10
+ attr_accessor :overall_bit_rate
11
+ attr_accessor :encoded_application
12
+ attr_accessor_alias :writing_application, :encoded_application
13
+ attr_accessor :encoded_library
14
+ attr_accessor_alias :writing_library, :encoded_library
15
+
16
+ attr_accessor :mastered_date
17
+ attr_accessor :tagged_date
18
+ attr_accessor :encoded_date
19
+ attr_accessor :last_modification_date
20
+ attr_accessor_alias :file_modified_date, :last_modification_date
21
+
22
+ # ID3Tags
23
+ attr_accessor :artist
24
+ attr_accessor :performer
25
+ attr_accessor :title
26
+ attr_accessor :genre
27
+ attr_accessor :album
28
+ attr_accessor :copyright
29
+ attr_accessor :year
30
+ end
31
+
@@ -0,0 +1,12 @@
1
+ class ImageStream < Stream
2
+ attr_accessor :resolution
3
+ attr_accessor :format
4
+
5
+ attr_accessor :width
6
+ attr_accessor :height
7
+
8
+ def frame_size
9
+ "#{width}x#{height}" if width && height
10
+ end
11
+ end
12
+
@@ -0,0 +1,9 @@
1
+ class MenuStream < Stream
2
+ attr_accessor :duration
3
+ attr_accessor :menu_id
4
+ attr_accessor :language
5
+ attr_accessor :encoded_date
6
+ attr_accessor :tagged_date
7
+ attr_accessor :delay
8
+ end
9
+
@@ -0,0 +1,6 @@
1
+ class OtherStream < Stream
2
+ attr_accessor :type
3
+ attr_accessor :timestamp_firstframe
4
+ attr_accessor_alias :timecode, :timestamp_firstframe
5
+ end
6
+
@@ -0,0 +1,10 @@
1
+ class TextStream < Stream
2
+ attr_accessor :duration
3
+ attr_accessor :language
4
+ attr_accessor :language_more_info # like "For hearing impaired people"
5
+ attr_accessor :format
6
+ attr_accessor :codec_id
7
+ attr_accessor :codec_info
8
+ attr_accessor :menu_id
9
+ end
10
+
@@ -0,0 +1,100 @@
1
+ class VideoStream < Stream
2
+ attr_accessor :duration
3
+
4
+ attr_accessor :stream_size
5
+ attr_accessor :bit_rate
6
+ attr_accessor :nominal_bit_rate
7
+
8
+ attr_accessor :bit_rate_mode
9
+ def cbr?
10
+ video? && 'Constant' == bit_rate_mode
11
+ end
12
+
13
+ def vbr?
14
+ video? && !cbr?
15
+ end
16
+
17
+ attr_accessor :scan_order
18
+ attr_accessor :scan_type
19
+ def interlaced?
20
+ video? && 'Interlaced' == scan_type
21
+ end
22
+
23
+ def progressive?
24
+ video? && !interlaced?
25
+ end
26
+
27
+ attr_accessor :bitdepth
28
+ attr_accessor_alias :bit_depth, :bitdepth
29
+
30
+ attr_accessor :resolution
31
+
32
+ attr_accessor :colorimetry
33
+ attr_accessor :colorspace
34
+ attr_accessor_alias :color_space, :colorspace
35
+
36
+ attr_accessor :format
37
+ attr_accessor :format_info
38
+ attr_accessor :format_profile
39
+ attr_accessor :format_version
40
+ attr_accessor :format_settings_cabac
41
+ attr_accessor :format_settings_reframes
42
+ attr_accessor :format_settings_matrix
43
+ attr_accessor :format_settings_gop
44
+ attr_accessor :format_commercial
45
+
46
+ attr_accessor :colour_primaries
47
+ attr_accessor_alias :color_primaries, :colour_primaries
48
+
49
+ attr_accessor :transfer_characteristics
50
+ attr_accessor :matrix_coefficients
51
+
52
+ attr_accessor :codec_id
53
+ attr_accessor :codec_info
54
+ attr_accessor :codec
55
+ attr_accessor_alias :codec_id_info, :codec_info
56
+
57
+ attr_accessor :frame_rate
58
+ attr_accessor_alias :framerate, :frame_rate
59
+ attr_accessor_alias :fps, :frame_rate
60
+ # to convert framerate string to a float
61
+ # example: "25.000 fps" => 25.0 :
62
+ def fps_float
63
+ frame_rate[/[\d.]+/].to_f if frame_rate
64
+ end
65
+
66
+ attr_accessor :minimum_frame_rate
67
+ attr_accessor_alias :min_framerate, :minimum_frame_rate
68
+ attr_accessor_alias :min_fps, :minimum_frame_rate
69
+ # like above, to convert min_fps strng to a float:
70
+ def min_fps_float
71
+ minimum_frame_rate[/[\d.]+/].to_f if video?
72
+ end
73
+
74
+ attr_accessor :maximum_frame_rate
75
+ attr_accessor_alias :max_framerate, :maximum_frame_rate
76
+ attr_accessor_alias :max_fps, :maximum_frame_rate
77
+ def max_fps_float
78
+ maximum_frame_rate[/[\d.]+/].to_f if video?
79
+ end
80
+
81
+ attr_accessor :frame_rate_mode
82
+
83
+ attr_accessor :display_aspect_ratio
84
+
85
+ attr_accessor :bits_pixel_frame # "Bits-(Pixel*Frame)"
86
+
87
+ attr_accessor :width
88
+ attr_accessor :height
89
+
90
+ def frame_size
91
+ "#{width}x#{height}" if width && height
92
+ end
93
+
94
+ attr_accessor :encoded_date
95
+ attr_accessor :tagged_date
96
+
97
+ attr_accessor :standard
98
+ attr_accessor :menu_id
99
+ end
100
+
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mediainfo-simple
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Vincent Marquet
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-18 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A simple MediaInfo wrapper.
14
+ email:
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/mediainfo-simple.rb
20
+ - lib/mediainfo-simple/parser.rb
21
+ - lib/mediainfo-simple/stream.rb
22
+ - lib/mediainfo-simple/stream_factory.rb
23
+ - lib/mediainfo-simple/streams/audio.rb
24
+ - lib/mediainfo-simple/streams/general.rb
25
+ - lib/mediainfo-simple/streams/image.rb
26
+ - lib/mediainfo-simple/streams/menu.rb
27
+ - lib/mediainfo-simple/streams/other.rb
28
+ - lib/mediainfo-simple/streams/text.rb
29
+ - lib/mediainfo-simple/streams/video.rb
30
+ homepage: http://github.com/vmarquet/ruby-mediainfo-simple
31
+ licenses:
32
+ - WTFPL
33
+ metadata: {}
34
+ post_install_message:
35
+ rdoc_options: []
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubyforge_project:
50
+ rubygems_version: 2.4.5
51
+ signing_key:
52
+ specification_version: 4
53
+ summary: A MediaInfo wrapper.
54
+ test_files: []