mkvtoolnix 0.7.0
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.
- 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
|
+
|