mkvtoolnix 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +33 -0
- data/.rubocop.yml +24 -0
- data/CODE_OF_CONDUCT.md +73 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +21 -0
- data/README.md +238 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/mkvtoolnix/errors/mkvtoolnix_error.rb +13 -0
- data/lib/mkvtoolnix/extensions/iterable.rb +18 -0
- data/lib/mkvtoolnix/modules/mkv_module.rb +37 -0
- data/lib/mkvtoolnix/modules/mkvextract.rb +152 -0
- data/lib/mkvtoolnix/modules/mkvmerge.rb +33 -0
- data/lib/mkvtoolnix/modules/mkvpropedit.rb +243 -0
- data/lib/mkvtoolnix/propedit_selector.rb +65 -0
- data/lib/mkvtoolnix/types/extract/attachment.rb +18 -0
- data/lib/mkvtoolnix/types/extract/track.rb +17 -0
- data/lib/mkvtoolnix/types/info/attachment.rb +27 -0
- data/lib/mkvtoolnix/types/info/audio.rb +53 -0
- data/lib/mkvtoolnix/types/info/mkv_container.rb +58 -0
- data/lib/mkvtoolnix/types/info/subtitle.rb +51 -0
- data/lib/mkvtoolnix/types/info/video.rb +69 -0
- data/lib/mkvtoolnix/types/propedit/audio_property.rb +17 -0
- data/lib/mkvtoolnix/types/propedit/common_property.rb +29 -0
- data/lib/mkvtoolnix/types/propedit/info_property.rb +17 -0
- data/lib/mkvtoolnix/types/propedit/property.rb +17 -0
- data/lib/mkvtoolnix/types/propedit/subtitle_property.rb +12 -0
- data/lib/mkvtoolnix/types/propedit/video_property.rb +19 -0
- data/lib/mkvtoolnix.rb +70 -0
- data/mkvtoolnix.gemspec +34 -0
- metadata +80 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MkvToolNix
|
4
|
+
module Modules
|
5
|
+
# https://mkvtoolnix.download/doc/mkvmerge.html
|
6
|
+
class MkvMerge
|
7
|
+
include MkvModule
|
8
|
+
|
9
|
+
def initialize(bin_path)
|
10
|
+
@bin_path = "#{bin_path}mkvmerge"
|
11
|
+
end
|
12
|
+
|
13
|
+
def version
|
14
|
+
cmd = [@bin_path, '-V']
|
15
|
+
|
16
|
+
result = call_cmd(cmd)
|
17
|
+
|
18
|
+
result.stdout.strip
|
19
|
+
end
|
20
|
+
|
21
|
+
def info(file)
|
22
|
+
cmd = [@bin_path, '-J']
|
23
|
+
# cmd = [@bin_path, '--identififcation-format', 'json', '--identify']
|
24
|
+
cmd << file
|
25
|
+
|
26
|
+
result = call_cmd(cmd)
|
27
|
+
|
28
|
+
json = JSON.parse(result.stdout)
|
29
|
+
Types::Info::MkvContainer.create(json)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,243 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MkvToolNix
|
4
|
+
module Modules
|
5
|
+
# https://mkvtoolnix.download/doc/mkvpropedit.html#mkvpropedit.edit_selectors
|
6
|
+
class MkvPropEdit
|
7
|
+
include MkvModule
|
8
|
+
|
9
|
+
attr_writer :abort_at_warning, :disable_language_ietf
|
10
|
+
|
11
|
+
def initialize(bin_path)
|
12
|
+
@bin_path = "#{bin_path}mkvpropedit"
|
13
|
+
@abort_at_warning = false
|
14
|
+
@disable_language_ietf = false
|
15
|
+
end
|
16
|
+
|
17
|
+
# returns the mkvpropedit version
|
18
|
+
#
|
19
|
+
# return [String] the version string
|
20
|
+
def version
|
21
|
+
cmd = [@bin_path, '-V']
|
22
|
+
|
23
|
+
result = call_cmd(cmd)
|
24
|
+
|
25
|
+
result.stdout.strip
|
26
|
+
end
|
27
|
+
|
28
|
+
# deletes the track statistics tags
|
29
|
+
#
|
30
|
+
# @param file [String] path to the mkv file
|
31
|
+
# @param full_parse_mode [Boolean] sets full parse mod
|
32
|
+
def delete_track_statistics_tags(file, full_parse_mode: false)
|
33
|
+
cmd = [@bin_path]
|
34
|
+
cmd << '--parse-mode' << 'full' if full_parse_mode
|
35
|
+
cmd << '--abort-on-warnings' if @abort_at_warning
|
36
|
+
cmd << file
|
37
|
+
cmd << '--delete-track-statistics-tags'
|
38
|
+
|
39
|
+
call_cmd(cmd)
|
40
|
+
end
|
41
|
+
|
42
|
+
# calculates and adds the statistics tags
|
43
|
+
#
|
44
|
+
# @param file [String] path to the mkv file
|
45
|
+
# @param full_parse_mode [Boolean] sets full parse mod
|
46
|
+
def add_track_statistics_tags(file, full_parse_mode: false)
|
47
|
+
cmd = [@bin_path]
|
48
|
+
add_default_options(cmd, full_parse_mode)
|
49
|
+
cmd << file
|
50
|
+
cmd << '--add-track-statistics-tags'
|
51
|
+
|
52
|
+
call_cmd(cmd)
|
53
|
+
end
|
54
|
+
|
55
|
+
# adds or replaces the given chapter file to the given mkv file. If the chapter file is empty (valid xml file,
|
56
|
+
# but the <chapter/> tag is empty), it removes the chapters from the mkv file
|
57
|
+
#
|
58
|
+
# @param file [String] path to the mkv file
|
59
|
+
# @param chapter_file [String] path to the chapter xml file
|
60
|
+
# @param full_parse_mode [Boolean] sets full parse mod
|
61
|
+
def set_chapters(file, chapter_file, full_parse_mode: false)
|
62
|
+
cmd = [@bin_path]
|
63
|
+
add_default_options(cmd, full_parse_mode)
|
64
|
+
cmd << file
|
65
|
+
cmd << '--chapters'
|
66
|
+
cmd << chapter_file
|
67
|
+
|
68
|
+
call_cmd(cmd)
|
69
|
+
end
|
70
|
+
|
71
|
+
# sets the given tags to the tag field matching the given selector. A selector can either be all, global or for
|
72
|
+
# a specific track.
|
73
|
+
#
|
74
|
+
# @param file [String] path to the mkv file
|
75
|
+
# @param tag_file [String] path to the tag xml file
|
76
|
+
# @param selector [String] the selector, all, global or a track selector
|
77
|
+
# @param full_parse_mode [Boolean] sets full parse mod
|
78
|
+
def set_tags(file, tag_file, selector, full_parse_mode: false)
|
79
|
+
cmd = [@bin_path]
|
80
|
+
add_default_options(cmd, full_parse_mode)
|
81
|
+
cmd << file
|
82
|
+
cmd << '--tags'
|
83
|
+
cmd << "#{selector}:#{tag_file}"
|
84
|
+
|
85
|
+
call_cmd(cmd)
|
86
|
+
end
|
87
|
+
|
88
|
+
# removes a property from the mkv file
|
89
|
+
#
|
90
|
+
# @param file [String] path to the mkv file
|
91
|
+
# @param selector [String] the info or track selector
|
92
|
+
# @param properties [String, Property] a list containing a Property or a String (Property will be determined
|
93
|
+
# automatically)
|
94
|
+
# @param full_parse_mode [Boolean] sets full parse mod
|
95
|
+
def remove_property(file, selector, properties, full_parse_mode: false)
|
96
|
+
props = properties.map { |it| it.is_a?(Types::PropEdit::Property) ? it : find_property(it) }
|
97
|
+
|
98
|
+
cmd = [@bin_path]
|
99
|
+
add_default_options(cmd, full_parse_mode)
|
100
|
+
cmd << file
|
101
|
+
cmd << '--edit'
|
102
|
+
cmd << selector
|
103
|
+
props.each do |prop|
|
104
|
+
raise Errors::MkvToolNixError, "Property is not removable: #{prop.property}" unless prop.removable
|
105
|
+
|
106
|
+
cmd << '--delete'
|
107
|
+
cmd << prop.property
|
108
|
+
end
|
109
|
+
|
110
|
+
call_cmd(cmd)
|
111
|
+
end
|
112
|
+
|
113
|
+
# sets a property to the mkv file
|
114
|
+
#
|
115
|
+
# @param file [String] path to the mkv file
|
116
|
+
# @param selector [String] the info or track selector
|
117
|
+
# @param property [String, Property] a Property or a String (Property will be determined automatically)
|
118
|
+
# @param value [Any] the value to set
|
119
|
+
# @param full_parse_mode [Boolean] sets full parse mod
|
120
|
+
def set_property(file, selector, property, value, full_parse_mode: false)
|
121
|
+
prop = property.is_a?(Types::PropEdit::Property) ? property : find_property(property)
|
122
|
+
cmd = [@bin_path]
|
123
|
+
add_default_options(cmd, full_parse_mode)
|
124
|
+
cmd << file
|
125
|
+
cmd << '--edit'
|
126
|
+
cmd << selector
|
127
|
+
cmd << '--set'
|
128
|
+
# noinspection RubyNilAnalysis
|
129
|
+
cmd << "#{prop.property}=#{value}"
|
130
|
+
|
131
|
+
call_cmd(cmd)
|
132
|
+
end
|
133
|
+
|
134
|
+
# adds an attachment to the mkv file
|
135
|
+
#
|
136
|
+
# @param file [String] path to the mkv file
|
137
|
+
# @param attachment_file [String] path to the attachment file
|
138
|
+
# @param name [String] the attachment name, or nil to use the attachment's file name
|
139
|
+
# @param description [String] attachments description
|
140
|
+
# @param uid [String] the uid to use, if nil, will be determined automatically
|
141
|
+
# @param mime_type [String] the files mime type. If nil, will be determined automatically
|
142
|
+
# @param full_parse_mode [Boolean] sets full parse mod
|
143
|
+
def add_attachment(file, attachment_file, name = nil, description = nil, uid = nil, mime_type = nil,
|
144
|
+
full_parse_mode: false)
|
145
|
+
cmd = [@bin_path]
|
146
|
+
add_default_options(cmd, full_parse_mode)
|
147
|
+
cmd << file
|
148
|
+
cmd << '--attachment-name' << name unless name.nil?
|
149
|
+
cmd << '--attachment-description' << description unless description.nil?
|
150
|
+
cmd << '--attachment-mime-type' << mime_type unless mime_type.nil?
|
151
|
+
cmd << '--attachment-uid' << uid unless uid.nil?
|
152
|
+
cmd << '--add-attachment' << attachment_file
|
153
|
+
|
154
|
+
call_cmd(cmd)
|
155
|
+
end
|
156
|
+
|
157
|
+
# replaces an attachment of the mkv file
|
158
|
+
#
|
159
|
+
# @param file [String] path to the mkv file
|
160
|
+
# @param selector [String] a selector to determine which attachment(s) to replace.
|
161
|
+
# See MkvToolNix::PropEditSelector
|
162
|
+
# @param attachment_file [String] path to the attachment file
|
163
|
+
# @param name [String] the attachment name, or nil to use the attachment's file name
|
164
|
+
# @param description [String] attachments description
|
165
|
+
# @param uid [String] the uid to use, if nil, will be determined automatically
|
166
|
+
# @param mime_type [String] the files mime type. If nil, will be determined automatically
|
167
|
+
# @param full_parse_mode [Boolean] sets full parse mod
|
168
|
+
def replace_attachment(file, selector, attachment_file, name = nil, description = nil, uid = nil, mime_type = nil,
|
169
|
+
full_parse_mode: false)
|
170
|
+
cmd = [@bin_path]
|
171
|
+
add_default_options(cmd, full_parse_mode)
|
172
|
+
cmd << file
|
173
|
+
cmd << '--attachment-name' << name unless name.nil?
|
174
|
+
cmd << '--attachment-description' << description unless description.nil?
|
175
|
+
cmd << '--attachment-mime-type' << mime_type unless mime_type.nil?
|
176
|
+
cmd << '--attachment-uid' << uid unless uid.nil?
|
177
|
+
cmd << '--replace-attachment' << "#{selector}:#{attachment_file}"
|
178
|
+
|
179
|
+
call_cmd(cmd)
|
180
|
+
end
|
181
|
+
|
182
|
+
# removes an attachment of the mkv file
|
183
|
+
#
|
184
|
+
# @param file [String] path to the mkv file
|
185
|
+
# @param selector [String] a selector to determine which attachment(s) to remove. See MkvToolNix::PropEditSelector
|
186
|
+
# @param full_parse_mode [Boolean] sets full parse mod
|
187
|
+
def remove_attachment(file, selector, full_parse_mode: false)
|
188
|
+
cmd = [@bin_path]
|
189
|
+
add_default_options(cmd, full_parse_mode)
|
190
|
+
cmd << file
|
191
|
+
cmd << '--delete-attachment' << selector
|
192
|
+
|
193
|
+
call_cmd(cmd)
|
194
|
+
end
|
195
|
+
|
196
|
+
# updates an attachment of the mkv file
|
197
|
+
#
|
198
|
+
# @param file [String] path to the mkv file
|
199
|
+
# @param selector [String] a selector to determine which attachment to replace. See MkvToolNix::PropEditSelector
|
200
|
+
# @param name [String] the new attachment name
|
201
|
+
# @param description [String] new attachments description
|
202
|
+
# @param uid [String] the new uid
|
203
|
+
# @param mime_type [String] the new files mime type
|
204
|
+
# @param full_parse_mode [Boolean] sets full parse mod
|
205
|
+
def update_attachment(file, selector, name = nil, description = nil, uid = nil, mime_type = nil,
|
206
|
+
full_parse_mode: false)
|
207
|
+
cmd = [@bin_path]
|
208
|
+
add_default_options(cmd, full_parse_mode)
|
209
|
+
cmd << file
|
210
|
+
cmd << '--attachment-name' << name unless name.nil?
|
211
|
+
cmd << '--attachment-description' << description unless description.nil?
|
212
|
+
cmd << '--attachment-mime-type' << mime_type unless mime_type.nil?
|
213
|
+
cmd << '--attachment-uid' << uid unless uid.nil?
|
214
|
+
cmd << '--update-attachment' << selector
|
215
|
+
|
216
|
+
call_cmd(cmd)
|
217
|
+
end
|
218
|
+
|
219
|
+
def add_default_options(cmd, full_parse_mode)
|
220
|
+
cmd << '--parse-mode' << 'full' if full_parse_mode
|
221
|
+
cmd << '--abort-on-warnings' if @abort_at_warning
|
222
|
+
end
|
223
|
+
|
224
|
+
def find_property(property_name)
|
225
|
+
prop = Types::PropEdit::InfoProperty.find_property(property_name)
|
226
|
+
return prop unless prop.nil?
|
227
|
+
|
228
|
+
prop = Types::PropEdit::VideoProperty.find_property(property_name)
|
229
|
+
return prop unless prop.nil?
|
230
|
+
|
231
|
+
prop = Types::PropEdit::AudioProperty.find_property(property_name)
|
232
|
+
return prop unless prop.nil?
|
233
|
+
|
234
|
+
prop = Types::PropEdit::SubtitleProperty.find_property(property_name)
|
235
|
+
return prop unless prop.nil?
|
236
|
+
|
237
|
+
raise Errors::MkvToolNixError, "Could not find Property: #{property_name}"
|
238
|
+
end
|
239
|
+
|
240
|
+
private :find_property, :add_default_options
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MkvToolNix
|
4
|
+
# https://mkvtoolnix.download/doc/mkvpropedit.html#mkvpropedit.edit_selectors
|
5
|
+
module PropEditSelector
|
6
|
+
def self.for_info
|
7
|
+
'info'
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.for_nth_track(nth)
|
11
|
+
raise Errors::MkvToolNixError, "Number must be > 0, got #{nth}" if nth.nil? || nth.negative?
|
12
|
+
|
13
|
+
"track:#{nth}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.for_nth_video(nth)
|
17
|
+
raise Errors::MkvToolNixError, "Number must be > 0, got #{nth}" if nth.nil? || nth.negative?
|
18
|
+
|
19
|
+
"track:v#{nth}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.for_nth_audio(nth)
|
23
|
+
raise Errors::MkvToolNixError, "Number must be > 0, got #{nth}" if nth.nil? || nth.negative?
|
24
|
+
|
25
|
+
"track:a#{nth}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.for_nth_subtitle(nth)
|
29
|
+
raise Errors::MkvToolNixError, "Number must be > 0, got #{nth}" if nth.nil? || nth.negative?
|
30
|
+
|
31
|
+
"track:s#{nth}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.by_track_number(track_number)
|
35
|
+
n = track_number
|
36
|
+
raise Errors::MkvToolNixError, "Number must be > 0, got #{n}" if n.nil? || n.negative?
|
37
|
+
|
38
|
+
"track:@#{n}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.by_track_uid(uid)
|
42
|
+
"track:=#{uid}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.for_attachment_by_id(id)
|
46
|
+
id
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.for_attachment_by_name(name)
|
50
|
+
"name:#{name}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.for_attachment_by_mime_type(mime_type)
|
54
|
+
"mime-type:#{mime_type}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.tag_all
|
58
|
+
'all'
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.tag_global
|
62
|
+
'global'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MkvToolNix
|
4
|
+
module Types
|
5
|
+
module Extract
|
6
|
+
class Attachment
|
7
|
+
|
8
|
+
attr_accessor :attachment_id, :output_file
|
9
|
+
|
10
|
+
def initialize(attachment_id, output_file)
|
11
|
+
@attachment_id = attachment_id
|
12
|
+
@output_file = output_file
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MkvToolNix
|
4
|
+
module Types
|
5
|
+
module Extract
|
6
|
+
class Track
|
7
|
+
|
8
|
+
attr_accessor :track_id, :output_file
|
9
|
+
|
10
|
+
def initialize(track_id, output_file)
|
11
|
+
@track_id = track_id
|
12
|
+
@output_file = output_file
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MkvToolNix
|
4
|
+
module Types
|
5
|
+
module Info
|
6
|
+
class Attachment
|
7
|
+
|
8
|
+
attr_accessor :id, :uid, :file_name, :description, :content_type, :size_in_b
|
9
|
+
|
10
|
+
def self.create(hash)
|
11
|
+
props = hash['properties']
|
12
|
+
new(id: hash['id'], uid: props['uid'], file_name: hash['file_name'], description: hash['description'],
|
13
|
+
content_type: hash['content_type'], size_in_b: hash['size'])
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(id:, uid:, file_name:, description:, content_type:, size_in_b:)
|
17
|
+
@id = id
|
18
|
+
@uid = uid
|
19
|
+
@file_name = file_name
|
20
|
+
@description = description
|
21
|
+
@content_type = content_type
|
22
|
+
@size_in_b = size_in_b
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MkvToolNix
|
4
|
+
module Types
|
5
|
+
module Info
|
6
|
+
class Audio
|
7
|
+
|
8
|
+
attr_accessor :id, :uid, :name, :codec, :codec_id, :codec_name, :codec_inherent_delay, :sampling_frequency,
|
9
|
+
:bit_depth, :channels, :is_default, :is_enabled, :is_commentary, :is_hearing_impaired,
|
10
|
+
:is_original, :is_text_descriptions, :is_visual_impaired, :is_forced, :language, :language_ietf
|
11
|
+
|
12
|
+
def self.create(hash)
|
13
|
+
props = hash['properties']
|
14
|
+
new(id: hash['id'], uid: props['uid'], name: props['track_name'], codec: hash['codec'],
|
15
|
+
codec_id: props['codec_id'], codec_name: props['codec_name'], codec_inherent_delay: props['codec_delay'],
|
16
|
+
sampling_frequency: props['audio_sampling_frequency'], bit_depth: props['audio_bits_per_sample'],
|
17
|
+
channels: props['audio_channels'], is_default: props['default_track'], is_enabled: props['enabled_track'],
|
18
|
+
is_commentary: props['flag_commentary'], is_hearing_impaired: props['flag_hearing_impaired'],
|
19
|
+
is_original: props['flag_original'], is_text_descriptions: props['flag_text_descriptions'],
|
20
|
+
is_visual_impaired: props['flag_visual_impaired'], is_forced: props['forced_track'],
|
21
|
+
language: props['language'], language_ietf: props['language_ietf'], track_number: props['number'])
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(id:, uid:, name:, codec:, codec_id:, codec_name:, codec_inherent_delay:, sampling_frequency:,
|
25
|
+
bit_depth:, channels:, is_default:, is_enabled:, is_commentary:, is_hearing_impaired:,
|
26
|
+
is_original:, is_text_descriptions:, is_visual_impaired:, is_forced:, language:, language_ietf:,
|
27
|
+
track_number:)
|
28
|
+
@id = id
|
29
|
+
@uid = uid
|
30
|
+
@name = name
|
31
|
+
@codec = codec
|
32
|
+
@codec_id = codec_id
|
33
|
+
@codec_name = codec_name
|
34
|
+
@codec_inherent_delay = codec_inherent_delay
|
35
|
+
@sampling_frequency = sampling_frequency
|
36
|
+
@bit_depth = bit_depth
|
37
|
+
@channels = channels
|
38
|
+
@is_default = is_default
|
39
|
+
@is_enabled = is_enabled
|
40
|
+
@is_commentary = is_commentary
|
41
|
+
@is_hearing_impaired = is_hearing_impaired
|
42
|
+
@is_original = is_original
|
43
|
+
@is_text_descriptions = is_text_descriptions
|
44
|
+
@is_visual_impaired = is_visual_impaired
|
45
|
+
@is_forced = is_forced
|
46
|
+
@language = language
|
47
|
+
@language_ietf = language_ietf
|
48
|
+
@track_number = track_number
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MkvToolNix
|
4
|
+
module Types
|
5
|
+
module Info
|
6
|
+
class MkvContainer
|
7
|
+
|
8
|
+
attr_accessor :title, :file_name, :format_version, :type, :is_supported, :is_recognized, :container_type,
|
9
|
+
:date_utc, :duration_in_secs, :is_providing_timestamps, :mux_application, :segment_uid,
|
10
|
+
:writing_application, :attachments, :videos, :audios, :subtitles
|
11
|
+
|
12
|
+
def self.create(hash)
|
13
|
+
container = hash['container']
|
14
|
+
props = container['properties']
|
15
|
+
attachments = hash['attachments'].map { |it| Attachment.create(it) }
|
16
|
+
tracks = hash['tracks']
|
17
|
+
video_hash = tracks.select { |it| it['type'] == 'video' }
|
18
|
+
videos = video_hash.nil? ? [] : video_hash.map { |it| Video.create(it) }
|
19
|
+
audio_hash = tracks.select { |it| it['type'] == 'audio' }
|
20
|
+
audios = audio_hash.nil? ? [] : audio_hash.map { |it| Audio.create(it) }
|
21
|
+
subtitle_hash = tracks.select { |it| it['type'] == 'subtitles' }
|
22
|
+
subtitles = subtitle_hash.nil? ? [] : subtitle_hash.map { |it| Subtitle.create(it) }
|
23
|
+
|
24
|
+
new(title: props['title'], file_name: hash['file_name'],
|
25
|
+
format_version: hash['identification_format_version'], type: container['type'],
|
26
|
+
is_supported: container['supported'], is_recognized: container['recognized'],
|
27
|
+
container_type: props['container_type'], date_utc: props['date_utc'],
|
28
|
+
duration_in_nano: props['duration'], is_providing_timestamps: props['is_providing_timestamps'],
|
29
|
+
mux_application: props['muxing_application'], segment_uid: props['segment_uid'],
|
30
|
+
writing_application: props['writing_application'], attachments: attachments, videos: videos,
|
31
|
+
audios: audios, subtitles: subtitles)
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(title:, file_name:, format_version:, type:, is_supported:, is_recognized:, container_type:,
|
35
|
+
date_utc:, duration_in_nano:, is_providing_timestamps:, mux_application:, segment_uid:,
|
36
|
+
writing_application:, attachments:, videos:, audios:, subtitles:)
|
37
|
+
@title = title
|
38
|
+
@file_name = file_name
|
39
|
+
@format_version = format_version
|
40
|
+
@type = type
|
41
|
+
@is_supported = is_supported
|
42
|
+
@is_recognized = is_recognized
|
43
|
+
@container_type = container_type
|
44
|
+
@date_utc = date_utc
|
45
|
+
@duration_in_secs = duration_in_nano.to_f / 1_000_000_000
|
46
|
+
@is_providing_timestamps = is_providing_timestamps
|
47
|
+
@mux_application = mux_application
|
48
|
+
@segment_uid = segment_uid
|
49
|
+
@writing_application = writing_application
|
50
|
+
@attachments = attachments
|
51
|
+
@videos = videos
|
52
|
+
@audios = audios
|
53
|
+
@subtitles = subtitles
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MkvToolNix
|
4
|
+
module Types
|
5
|
+
module Info
|
6
|
+
class Subtitle
|
7
|
+
|
8
|
+
attr_accessor :id, :uid, :name, :codec, :codec_id, :codec_name, :codec_inherent_delay, :encoding, :is_default,
|
9
|
+
:is_enabled, :is_commentary, :is_hearing_impaired, :is_original, :is_text_descriptions,
|
10
|
+
:is_visual_impaired, :is_forced, :language, :language_ietf, :is_text, :track_number
|
11
|
+
|
12
|
+
def self.create(hash)
|
13
|
+
props = hash['properties']
|
14
|
+
new(id: hash['id'], uid: props['uid'], name: props['track_name'], codec: hash['codec'],
|
15
|
+
codec_id: props['codec_id'], codec_name: props['codec_name'], codec_inherent_delay: props['codec_delay'],
|
16
|
+
encoding: props['encoding'], is_default: props['default_track'], is_enabled: props['enabled_track'],
|
17
|
+
is_commentary: props['flag_commentary'], is_hearing_impaired: props['flag_hearing_impaired'],
|
18
|
+
is_original: props['flag_original'], is_text_descriptions: props['flag_text_descriptions'],
|
19
|
+
is_visual_impaired: props['flag_visual_impaired'], is_forced: props['forced_track'],
|
20
|
+
language: props['language'], language_ietf: props['language_ietf'], is_text: props['text_subtitles'],
|
21
|
+
track_number: props['number'])
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(id:, uid:, name:, codec:, codec_id:, codec_name:, codec_inherent_delay:, encoding:, is_default:,
|
25
|
+
is_enabled:, is_commentary:, is_hearing_impaired:, is_original:, is_text_descriptions:,
|
26
|
+
is_visual_impaired:, is_forced:, language:, language_ietf:, is_text:, track_number:)
|
27
|
+
@id = id
|
28
|
+
@uid = uid
|
29
|
+
@name = name
|
30
|
+
@codec = codec
|
31
|
+
@codec_id = codec_id
|
32
|
+
@codec_name = codec_name
|
33
|
+
@codec_inherent_delay = codec_inherent_delay
|
34
|
+
@encoding = encoding
|
35
|
+
@is_default = is_default
|
36
|
+
@is_enabled = is_enabled
|
37
|
+
@is_commentary = is_commentary
|
38
|
+
@is_hearing_impaired = is_hearing_impaired
|
39
|
+
@is_original = is_original
|
40
|
+
@is_text_descriptions = is_text_descriptions
|
41
|
+
@is_visual_impaired = is_visual_impaired
|
42
|
+
@is_forced = is_forced
|
43
|
+
@language = language
|
44
|
+
@language_ietf = language_ietf
|
45
|
+
@is_text = is_text
|
46
|
+
@track_number = track_number
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MkvToolNix
|
4
|
+
module Types
|
5
|
+
module Info
|
6
|
+
class Video
|
7
|
+
|
8
|
+
attr_accessor :id, :uid, :name, :codec, :codec_id, :codec_name, :codec_inherent_delay, :is_default, :is_enabled,
|
9
|
+
:is_commentary, :is_hearing_impaired, :is_original, :is_text_descriptions, :is_visual_impaired,
|
10
|
+
:is_forced, :language, :language_ietf, :packetizer, :display_unit, :pixel_dimension, :pixel_width,
|
11
|
+
:pixel_height, :display_dimension, :display_width, :display_height, :cropping, :stereo_mode,
|
12
|
+
:track_number
|
13
|
+
|
14
|
+
def self.create(hash)
|
15
|
+
props = hash['properties']
|
16
|
+
new(id: hash['id'], uid: props['uid'], name: props['track_name'], codec: hash['codec'],
|
17
|
+
codec_id: props['codec_id'], codec_name: props['codec_name'], codec_inherent_delay: props['codec_delay'],
|
18
|
+
is_default: props['default_track'], is_enabled: props['enabled_track'],
|
19
|
+
is_commentary: props['flag_commentary'], is_hearing_impaired: props['flag_hearing_impaired'],
|
20
|
+
is_original: props['flag_original'], is_text_descriptions: props['flag_text_descriptions'],
|
21
|
+
is_visual_impaired: props['flag_visual_impaired'], is_forced: props['forced_track'],
|
22
|
+
language: props['language'], language_ietf: props['language_ietf'], packetizer: props['packetizer'],
|
23
|
+
pixel_dimension: props['pixel_dimensions'], display_dimension: props['display_dimensions'],
|
24
|
+
display_unit: props['display_unit'], cropping: props['cropping'], stereo_mode: props['stereo_mode'],
|
25
|
+
track_number: props['number'])
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(id:, uid:, name:, codec:, codec_id:, codec_name:, codec_inherent_delay:, is_default:,
|
29
|
+
is_enabled:, is_commentary:, is_hearing_impaired:, is_original:, is_text_descriptions:,
|
30
|
+
is_visual_impaired:, is_forced:, language:, language_ietf:, packetizer:, pixel_dimension:,
|
31
|
+
display_dimension:, display_unit:, cropping:, stereo_mode:, track_number:)
|
32
|
+
@id = id
|
33
|
+
@uid = uid
|
34
|
+
@name = name
|
35
|
+
@codec = codec
|
36
|
+
@codec_id = codec_id
|
37
|
+
@codec_name = codec_name
|
38
|
+
@codec_inherent_delay = codec_inherent_delay
|
39
|
+
@is_default = is_default
|
40
|
+
@is_enabled = is_enabled
|
41
|
+
@is_commentary = is_commentary
|
42
|
+
@is_hearing_impaired = is_hearing_impaired
|
43
|
+
@is_original = is_original
|
44
|
+
@is_text_descriptions = is_text_descriptions
|
45
|
+
@is_visual_impaired = is_visual_impaired
|
46
|
+
@is_forced = is_forced
|
47
|
+
@language = language
|
48
|
+
@language_ietf = language_ietf
|
49
|
+
@packetizer = packetizer
|
50
|
+
@display_unit = display_unit
|
51
|
+
@pixel_dimension = pixel_dimension
|
52
|
+
if pixel_dimension.include?('x')
|
53
|
+
@pixel_width = pixel_dimension.split('x')[0]
|
54
|
+
@pixel_height = pixel_dimension.split('x')[1]
|
55
|
+
end
|
56
|
+
@display_dimension = display_dimension
|
57
|
+
if display_dimension.include?('x')
|
58
|
+
@display_width = display_dimension.split('x')[0]
|
59
|
+
@display_height = display_dimension.split('x')[1]
|
60
|
+
end
|
61
|
+
|
62
|
+
@cropping = cropping
|
63
|
+
@stereo_mode = stereo_mode
|
64
|
+
@track_number = track_number
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MkvToolNix
|
4
|
+
module Types
|
5
|
+
module PropEdit
|
6
|
+
module AudioProperty
|
7
|
+
include CommonProperty
|
8
|
+
extend Extensions::Iterable
|
9
|
+
|
10
|
+
SAMPLING_FREQUENCY = Property.new('sampling-frequency')
|
11
|
+
BIT_DEPTH = Property.new('bit-depth')
|
12
|
+
CHANNELS = Property.new('channels')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|