mkvtoolnix 0.7.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e948c21a4ec224548451bef5cb144ef2f3a1b3f4c3955dfbd019158f7c2a2b6f
4
- data.tar.gz: 98410a664b3d1b2fa218de1803438e8d0e9cc42038bf97d956c402449e769a38
3
+ metadata.gz: 2fbb34a6ebad7edff1fd7a8b346772d03cb4586266708b1117023fc5212ee278
4
+ data.tar.gz: 3c943c0d0839585b61b7bcec644811cd7ba2ebcb02717bab4da6d242d187d635
5
5
  SHA512:
6
- metadata.gz: a296517bee0136c8c2c3cf6d80db74ddf229aa2f84898bb99b58db108e3fc8a2b1f9f8b8a472616ae41356cae2f11f0f5896616a562c96a6882f2920d9a272ea
7
- data.tar.gz: 010a4cfe800ff5e5e09e88c44c4780bfd50d6f7b11bb801e77815c415025788315d1122b571c83cbfa9801b68d4c18041741d85522a4472073edd01653acf9cc
6
+ metadata.gz: 499dbf2eee5835142fc5e68bed28ca54bcac1d9c59be5eaa692bfabf1284267c4e5a5c4798410d2b04d3035ee43a0270a798674496f4be290121317e2d62aa5d
7
+ data.tar.gz: 061047311adda84e1ad76e119aca20dd37048c25a77dc68ae3862c00d0634f897d5f56fa5aa88326b17c61b64951a184413c3bd93ad6f7e076ead73069b00c69
data/README.md CHANGED
@@ -6,7 +6,7 @@ Currently the following modules are implemented (fully):
6
6
  * [mkvpropedit](https://mkvtoolnix.download/doc/mkvpropedit.html)
7
7
  * [mkvextract](https://mkvtoolnix.download/doc/mkvextract.html)
8
8
 
9
- Partly implemented (aka just started :p, this one is pretty complex, and I am still thinking about how to make it as simple as possible without sacrificing functionality)
9
+ Fully implemented, except `split`:
10
10
  * [mkvmerge](https://mkvtoolnix.download/doc/mkvmerge.html)
11
11
 
12
12
  ## Installation
@@ -218,12 +218,210 @@ extract_attachments('myFile.mkv', [Attachment.new(0, 'attachment1.jpeg'), 'attac
218
218
  ```
219
219
  will extract the attachments of the given file with ID 0 to `attachment1.jpeg` and ID 2 to `attachment.2.png`.
220
220
 
221
+ ### mkvmerge
221
222
 
222
- ## Development
223
+ merges or modifies several input files by muxing it. This does not alter just metadata of a file, and instead writes a new
224
+ file depending on the provides input files and options.
223
225
 
224
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
226
+ #### available commands
227
+
228
+ * version
229
+ * info
230
+ * merge
231
+
232
+ `merge` covers all options except for split from [here](https://mkvtoolnix.download/doc/mkvmerge.html). It requires an input, and an
233
+ output file. If you just want to alter a file, e.g. removing a track, then only this file needs to be given as an input file.
234
+ All options from the manual page are available as some kind of builder. This way, an input file with the selected options can be build, and
235
+ will be applied when passed to `merge`.
236
+ The global options are seperated into different option builder. Those ones are:
237
+ * Chapter
238
+ * Tags
239
+ * Segment Info
240
+ * General Output
241
+ * Attachments
242
+
243
+ To build an option or an input file, mkvmerge provides already methods to do so:
244
+ * build_attachment(file)
245
+ * build_chapter
246
+ * build_segment_info
247
+ * build_tags(file)
248
+ * build_output_control
249
+ * build_input_file(file)
250
+
251
+ For specific track options for an input file, `InputFile` offers a `build_track_option(track_id)` method, which offers
252
+ options for this specific track and afterwards added to the input file via `add_track_options`
253
+
254
+ For specific details what options are available, just check the manual page. The available options are:
255
+ **Attachment:**
256
+ * with_mime_type
257
+ * with_name
258
+ * with_description
259
+
260
+ **Chapter:**
261
+ * with_chapter_language
262
+ * with_chapter_charset
263
+ * generate_chapter_every_secs
264
+ * generate_chapter_name_template
265
+ * generate_chapter_cue_name_format
266
+ * with_chapters_file
267
+
268
+ **Output Control:**
269
+ * with_title
270
+ * with_default_language
271
+ * with_track_order
272
+ * with_cluster_length_in_blocks
273
+ * with_meta_seek_element
274
+ * with_timestamp_scale
275
+ * with_durations_enabled
276
+ * without_cues
277
+ * without_date
278
+ * with_disabled_lacing
279
+ * without_track_statistics_tags
280
+ * without_language_ietf
281
+
282
+ **Segment Info:**
283
+ * for_file
284
+ * for_uids
285
+
286
+ **Tags:**
287
+ * can only be build by file
288
+
289
+ **Input File:**
290
+ * with_audio_tracks
291
+ * with_video_tracks
292
+ * with_subtitle_tracks
293
+ * with_track_tags
294
+ * with_attachments
295
+ * with_no_audio
296
+ * with_no_video
297
+ * with_no_subtitles
298
+ * with_no_chapters
299
+ * with_no_track_tags
300
+ * with_no_global_tags
301
+ * with_no_attachments
302
+ * add_track_options
303
+ * with_track_options
304
+ * chapter_sync
305
+
306
+ **Input Track Option**
307
+ * with_name
308
+ * with_language
309
+ * with_tags
310
+ * handle_as_aac_sbr
311
+ * with_track_sync
312
+ * with_cues
313
+ * default?
314
+ * forced?
315
+ * hearing_impaired?
316
+ * visual_impaired?
317
+ * text_description?
318
+ * original?
319
+ * commentary?
320
+ * reduce_audio_to_core
321
+ * with_timestamps
322
+ * remove_dialog_normalization_gain
323
+ * with_default_duration_in_secs
324
+ * fix_bitstream_timing_information
325
+ * with_compression_mode
326
+ * with_four_cc
327
+ * with_dimensions
328
+ * with_aspect_ratio
329
+ * with_cropping
330
+ * with_color_matrix_coefficients
331
+ * with_color_bits_per_channel
332
+ * with_chroma_sub_sample
333
+ * with_cb_sub_sample
334
+ * with_chroma_siting
335
+ * with_color_range
336
+ * with_color_transfer_characteristics
337
+ * with_color_primaries
338
+ * with_max_content_light
339
+ * with_max_frame_light
340
+ * with_chromaticity_coordinates
341
+ * with_white_color_coordinate
342
+ * with_max_luminance
343
+ * with_min_luminance
344
+ * with_projection_type
345
+ * with_projection_private
346
+ * with_projection_pose_yaw
347
+ * with_projection_pose_pitch
348
+ * with_projection_pose_roll
349
+ * with_field_order
350
+ * with_stereo_mode
351
+ * with_sub_charset
352
+
353
+ For example, to specify that a meta seek element,
354
+ no cues and no date are written, a the general output can be build accordingly:
355
+ ```ruby
356
+ output_control = merge.build_output_control
357
+ output_control.with_meta_seek_element.without_cues.without_date
358
+ ```
359
+ just pass this `output_control` to `merge`, and the options will be applied.
360
+
361
+ #### Example
362
+
363
+ ##### merge video and audio from 2 different files
364
+ ```ruby
365
+ video_input = merge.build_input_file('pathToVideo')
366
+ # we don't want the audio from this video file
367
+ video_input.with_no_audio
368
+ audio_input = merge.build_input_file('pathToAudio')
369
+ # we don't want the video from this audio file, if it has any
370
+ audio_input.with_no_video
371
+
372
+ # lets take the output control as defined earlier
373
+ merge.merge('outputFilePath', video_input, audio_input, output_control: output_control)
374
+ # => nil, or an error and the merged file is written to the given path
375
+ ```
376
+
377
+ ##### add 2 Attachments, chapters and tags to an mkv file
378
+ ```ruby
379
+ attachment1 = merge.build_attachment('pathToAttachment1')
380
+ # no mime type provided, so it will be determined automatically by mkvmerge
381
+ attachment1.with_name('My first Attachment').with_description('and the description')
382
+
383
+ attachment2 = merge.build_attachment('pathToAttachment2')
384
+ attachment2.with_name('the 2nd one').with_mime_type('mime/type')
385
+
386
+ chapters = merge.build_chapter.with_chapters_file('pathToChapters.xml')
387
+ tags = merge.build_tags('pathToTags.xml')
388
+
389
+ input_file = merge.build_input_file('pathToInputFile')
390
+
391
+ merge.merge('outputFle', input_file, attachments: [attachment1, attachment2], chapter_options: chapters,
392
+ tag_options: tags)
393
+ # => nil, and outPutFile now contains the attachments, chapers and tag options
394
+ ```
395
+
396
+ ##### switch the track order of an mkv file
397
+ assuming we have 1 video, 2 audios, and 2 subtitles
398
+ ```ruby
399
+ output_control = merge.build_output_control
400
+ # the order can be given as a String, hash, Array, or TrackOrder object
401
+ # mkv always builds video, audio and subtitle order, so we just need to switch the audio ids, video will be the first
402
+ # and subtitles the last tracks
403
+ output_control.with_track_order({ file_index: 0, track_index: 2 }, [0, 1])
404
+
405
+ input_file = merge.build_input_file('pathToInputFile')
406
+
407
+ merge.merge('outputFle', input_file, output_control: output_control)
408
+ # => nil, and the new file has the audio tracks switched
409
+ ```
410
+
411
+ ##### switch rename the first audio track and language
412
+ the first audio stream in this example has ID 1
413
+ ```ruby
414
+ input_file = merge.build_input_file('pathToInputFile')
415
+ track_option = input_file.build_track_option(1)
416
+ track_option.with_name('the new track name')
417
+ # this will also set the language_ietf field
418
+ track_option.with_language('en')
419
+
420
+ input_file.add_track_options(track_option)
421
+
422
+ merge.merge('outputFle', input_file)
423
+ ```
225
424
 
226
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
227
425
 
228
426
  ## Contributing
229
427
 
@@ -235,4 +433,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
235
433
 
236
434
  ## Code of Conduct
237
435
 
238
- Everyone interacting in the Mkvtoolnix project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/mkvtoolnix/blob/master/CODE_OF_CONDUCT.md).
436
+ Everyone interacting in the Mkvtoolnix project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/cfe86/RubyMkvToolNix/blob/master/CODE_OF_CONDUCT.md).
@@ -6,8 +6,12 @@ module MkvToolNix
6
6
  class MkvMerge
7
7
  include MkvModule
8
8
 
9
+ attr_accessor :default_language, :disable_language_ietf
10
+
9
11
  def initialize(bin_path)
10
12
  @bin_path = "#{bin_path}mkvmerge"
13
+ @default_language = 'und'
14
+ @disable_language_ietf = false
11
15
  end
12
16
 
13
17
  def version
@@ -18,9 +22,29 @@ module MkvToolNix
18
22
  result.stdout.strip
19
23
  end
20
24
 
25
+ def merge(output_file, *input_files, attachments: nil, chapter_options: nil, tag_options: nil,
26
+ output_control: nil, segment_info: nil)
27
+ raise Errors::MkvToolNixError, 'No Input File(s) given.' if input_files.nil?
28
+
29
+ cmd = ['mkvmerge']
30
+
31
+ attachments&.each { |attachment| attachment.add_to_cmd(cmd) }
32
+ chapter_options&.add_to_cmd(cmd)
33
+ segment_info&.add_to_cmd(cmd)
34
+ tag_options&.add_to_cmd(cmd)
35
+ output_control&.add_to_cmd(cmd)
36
+
37
+ cmd << '-o' << output_file
38
+
39
+ input_files.each { |input| input.add_to_cmd(cmd) }
40
+
41
+ a = cmd.join(' ')
42
+
43
+ call_cmd(cmd)
44
+ end
45
+
21
46
  def info(file)
22
47
  cmd = [@bin_path, '-J']
23
- # cmd = [@bin_path, '--identififcation-format', 'json', '--identify']
24
48
  cmd << file
25
49
 
26
50
  result = call_cmd(cmd)
@@ -28,6 +52,30 @@ module MkvToolNix
28
52
  json = JSON.parse(result.stdout)
29
53
  Types::Info::MkvContainer.create(json)
30
54
  end
55
+
56
+ def build_segment_info
57
+ Types::Merge::SegmentInfo.new
58
+ end
59
+
60
+ def build_attachment(file)
61
+ Types::Merge::Attachment.new(file)
62
+ end
63
+
64
+ def build_chapter
65
+ Types::Merge::Chapter.new
66
+ end
67
+
68
+ def build_tags(file)
69
+ Types::Merge::Tags.new(file)
70
+ end
71
+
72
+ def build_output_control
73
+ Types::Merge::OutputControl.new
74
+ end
75
+
76
+ def build_input_file(file)
77
+ Types::Merge::InputFile.new(file)
78
+ end
31
79
  end
32
80
  end
33
81
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MkvToolNix
4
+ module Types
5
+ module Merge
6
+ class Attachment
7
+
8
+ attr_reader :file, :mime_type, :name, :description
9
+
10
+ def with_mime_type(type)
11
+ @mime_type = type
12
+ self
13
+ end
14
+
15
+ def with_name(name)
16
+ @name = name
17
+ self
18
+ end
19
+
20
+ def with_description(description)
21
+ @description = description
22
+ self
23
+ end
24
+
25
+ def initialize(file)
26
+ @file = file
27
+ end
28
+
29
+ def add_to_cmd(cmd)
30
+ unless @file.nil?
31
+ cmd << '--attachment-description' << @description unless @description.nil?
32
+ cmd << '--attachment-mime-type' << @mime_type unless @mime_type.nil?
33
+ cmd << '--attachment-name' << @name unless @name.nil?
34
+ cmd << '--attach-file' << @file
35
+ end
36
+ nil
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MkvToolNix
4
+ module Types
5
+ module Merge
6
+ class Chapter
7
+
8
+ attr_reader :chapter_language, :chapter_charset, :generate_chapter_interval_secs,
9
+ :gen_chapter_cue_name_format, :gen_chapter_name_template, :chapters_file
10
+
11
+ def with_chapter_language(language_code)
12
+ @chapter_language = language_code
13
+ self
14
+ end
15
+
16
+ def with_chapter_charset(charset)
17
+ @chapter_charset = charset
18
+ self
19
+ end
20
+
21
+ def generate_chapter_every_secs(num_secs)
22
+ @generate_chapter_interval_secs = num_secs
23
+ self
24
+ end
25
+
26
+ def generate_chapter_name_template(template)
27
+ @gen_chapter_name_template = template
28
+ self
29
+ end
30
+
31
+ def generate_chapter_cue_name_format(format)
32
+ @gen_chapter_cue_name_format = format
33
+ self
34
+ end
35
+
36
+ def with_chapters_file(file)
37
+ @chapters_file = file
38
+ self
39
+ end
40
+
41
+ def add_to_cmd(cmd)
42
+ cmd << '--chapters' << @chapters_file unless @chapters_file.nil?
43
+ cmd << '--chapter-language' << @chapter_language unless @chapter_language.nil?
44
+ cmd << '--chapter-charset' << @chapter_charset unless @chapter_charset.nil?
45
+ cmd << '--generate-chapters' << "interval:#{@generate_chapter_interval_secs}s" unless @generate_chapter_interval_secs.nil?
46
+ cmd << '--generate-chapters-name-template' << @gen_chapter_name_template unless @gen_chapter_name_template.nil?
47
+ cmd << '--cue-chapter-name-format' << @gen_chapter_cue_name_format unless @gen_chapter_cue_name_format.nil?
48
+ nil
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MkvToolNix
4
+ module Types
5
+ module Merge
6
+ class InputFile
7
+
8
+ attr_reader :audio_tracks, :video_tracks, :subtitle_tracks, :track_tags, :attachments, :no_audio,
9
+ :no_video, :no_subtitles, :no_chapters, :no_attachments, :no_track_tags, :no_global_tags,
10
+ :track_options
11
+
12
+ def with_audio_tracks(*track_ids)
13
+ @audio_tracks = track_ids
14
+ self
15
+ end
16
+
17
+ def with_video_tracks(*track_ids)
18
+ @video_tracks = track_ids
19
+ self
20
+ end
21
+
22
+ def with_subtitle_tracks(*track_ids)
23
+ @subtitle_tracks = track_ids
24
+ self
25
+ end
26
+
27
+ def with_track_tags(*track_ids)
28
+ @track_tags = track_ids
29
+ self
30
+ end
31
+
32
+ def with_attachments(*attachment_ids)
33
+ @attachments = attachment_ids
34
+ self
35
+ end
36
+
37
+ def with_no_audio
38
+ @no_audio = true
39
+ self
40
+ end
41
+
42
+ def with_no_video
43
+ @no_video = true
44
+ self
45
+ end
46
+
47
+ def with_no_subtitles
48
+ @no_subtitles = true
49
+ self
50
+ end
51
+
52
+ def with_no_chapters
53
+ @no_chapters = true
54
+ self
55
+ end
56
+
57
+ def with_no_track_tags
58
+ @no_track_tags = true
59
+ self
60
+ end
61
+
62
+ def with_no_global_tags
63
+ @no_global_tags = true
64
+ self
65
+ end
66
+
67
+ def with_no_attachments
68
+ @no_attachments = true
69
+ self
70
+ end
71
+
72
+ def add_track_options(option)
73
+ @track_options << option
74
+ self
75
+ end
76
+
77
+ def with_track_options(options)
78
+ @track_options = options
79
+ self
80
+ end
81
+
82
+ def chapter_sync(d = 0, o_div_p = 1.0)
83
+ @chapter_sync = "-2:#{d},#{o_div_p}"
84
+ self
85
+ end
86
+
87
+ def build_track_option(track_id)
88
+ InputTrackOption.new(track_id)
89
+ end
90
+
91
+ def add_to_cmd(cmd)
92
+ cmd << '--audio-tracks' << @audio_tracks.join(',') unless @audio_tracks.nil?
93
+ cmd << '--video-tracks' << @video_tracks.join(',') unless @video_tracks.nil?
94
+ cmd << '--subtitle-tracks' << @subtitle_tracks.join(',') unless @subtitle_tracks.nil?
95
+ cmd << '--track-tags' << @track_tags.join(',') unless @track_tags.nil?
96
+ cmd << '--attachments' << @attachments.join(',') unless @attachments.nil?
97
+ cmd << '--no-audio' unless @no_audio.nil?
98
+ cmd << '--no-video' unless @no_video.nil?
99
+ cmd << '--no-subtitles' unless @no_subtitles.nil?
100
+ cmd << '--no-track-tags' unless @no_track_tags.nil?
101
+ cmd << '--no-chapters' unless @no_chapters.nil?
102
+ cmd << '--no-attachments' unless @no_attachments.nil?
103
+ cmd << '--no-global-tags' unless @no_global_tags.nil?
104
+ cmd << '--sync' << @chapter_sync unless @chapter_sync.nil?
105
+
106
+ @track_options.each { |option| option.add_to_cmd(cmd) }
107
+
108
+ cmd << @file
109
+ nil
110
+ end
111
+
112
+ def initialize(file)
113
+ @file = file
114
+ @track_options = []
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,390 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MkvToolNix
4
+ module Types
5
+ module Merge
6
+ class InputTrackOption
7
+
8
+ attr_reader :track_id, :name, :language, :tag_file, :aac_sbr, :track_sync, :cues, :is_default,
9
+ :is_forced, :is_hearing_impaired, :is_visual_impaired, :is_text_description, :is_original,
10
+ :is_commentary, :reduce_to_core, :no_dialog_norm_gain, :timestamp_file, :default_duration_in_secs,
11
+ :fix_bitstream_timing_info, :compression, :four_cc, :dimensions, :aspect_ratio,
12
+ :color_matrix_coefficients, :color_bits_per_channel, :chroma_sub_sample, :cb_sub_sample,
13
+ :color_transfer_characteristics, :color_primaries, :max_content_light, :max_frame_light,
14
+ :chromaticity_coordinates, :white_color_coordinate, :max_luminance, :min_luminance,
15
+ :projection_type, :projection_private, :projection_pose_yaw, :projection_pose_pitch,
16
+ :projection_pose_roll, :field_order, :stereo_mode, :sub_charset
17
+
18
+ def with_name(name)
19
+ @name = "#{@track_id}:#{name}"
20
+ self
21
+ end
22
+
23
+ def with_language(language)
24
+ @language = "#{@track_id}:#{language}"
25
+ self
26
+ end
27
+
28
+ def with_tags(file)
29
+ @tag_file = "#{@track_id}:#{file}"
30
+ self
31
+ end
32
+
33
+ def handle_as_aac_sbr(enabled: true)
34
+ @aac_sbr = "#{@track_id}:#{enabled ? 1 : 0}"
35
+ self
36
+ end
37
+
38
+ def with_track_sync(d = 0, o_div_p = 1.0)
39
+ @track_sync = "#{@track_id}:#{d},#{o_div_p}"
40
+ self
41
+ end
42
+
43
+ def with_cues(mode = CueMode::I_FRAMES)
44
+ @cues = "#{@track_id}:#{mode}"
45
+ self
46
+ end
47
+
48
+ def default?(enabled: true)
49
+ @is_default = "#{@track_id}:#{enabled}"
50
+ self
51
+ end
52
+
53
+ def forced?(enabled: true)
54
+ @is_forced = "#{@track_id}:#{enabled}"
55
+ self
56
+ end
57
+
58
+ def hearing_impaired?(enabled: true)
59
+ @is_hearing_impaired = "#{@track_id}:#{enabled}"
60
+ self
61
+ end
62
+
63
+ def visual_impaired?(enabled: true)
64
+ @is_visual_impaired = "#{@track_id}:#{enabled}"
65
+ self
66
+ end
67
+
68
+ def text_description?(enabled: true)
69
+ @is_text_description = "#{@track_id}:#{enabled}"
70
+ self
71
+ end
72
+
73
+ def original?(enabled: true)
74
+ @is_original = "#{@track_id}:#{enabled}"
75
+ self
76
+ end
77
+
78
+ def commentary?(enabled: true)
79
+ @is_commentary = "#{@track_id}:#{enabled}"
80
+ self
81
+ end
82
+
83
+ def reduce_audio_to_core
84
+ @reduce_to_core = true
85
+ self
86
+ end
87
+
88
+ def with_timestamps(file)
89
+ @timestamp_file = "#{@track_id}:#{file}"
90
+ self
91
+ end
92
+
93
+ def remove_dialog_normalization_gain
94
+ @no_dialog_norm_gain = true
95
+ self
96
+
97
+ end
98
+
99
+ def with_default_duration_in_secs(secs)
100
+ @default_duration_in_secs = "#{@track_id}:#{secs}s"
101
+ self
102
+ end
103
+
104
+ def fix_bitstream_timing_information(fix: true)
105
+ @fix_bitstream_timing_info = "#{@track_id}:#{fix ? 1 : 0}"
106
+ self
107
+ end
108
+
109
+ def with_compression_mode(mode = Compression::NONE)
110
+ @compression = "#{@track_id}:#{mode}"
111
+ self
112
+ end
113
+
114
+ def with_four_cc(four_cc)
115
+ @four_cc = "#{@track_id}:#{four_cc}"
116
+ self
117
+ end
118
+
119
+ def with_dimensions(width, height)
120
+ @dimensions = "#{@track_id}:#{width}x#{height}"
121
+ self
122
+ end
123
+
124
+ def with_aspect_ratio(ratio)
125
+ @aspect_ratio = "#{@track_id}:#{ratio}"
126
+ self
127
+ end
128
+
129
+ def with_cropping(left, top, right, bottom)
130
+ @cropping = "#{@track_id}:#{left},#{top},#{right},#{bottom}"
131
+ self
132
+ end
133
+
134
+ def with_color_matrix_coefficients(coefficient)
135
+ @color_matrix_coefficients = "#{@track_id}:#{coefficient}"
136
+ self
137
+ end
138
+
139
+ def with_color_bits_per_channel(bits)
140
+ @color_bits_per_channel = "#{@track_id}:#{bits}"
141
+ self
142
+ end
143
+
144
+ def with_chroma_sub_sample(horizontal, vertical)
145
+ @chroma_sub_sample = "#{@track_id}:#{horizontal},#{vertical}"
146
+ self
147
+ end
148
+
149
+ def with_cb_sub_sample(horizontal, vertical)
150
+ @cb_sub_sample = "#{@track_id}:#{horizontal},#{vertical}"
151
+ self
152
+ end
153
+
154
+ def with_chroma_siting(horizontal, vertical)
155
+ @chroma_siting = "#{@track_id}:#{horizontal},#{vertical}"
156
+ self
157
+ end
158
+
159
+ def with_color_range(range)
160
+ @color_range = "#{@track_id}:#{range}"
161
+ self
162
+ end
163
+
164
+ def with_color_transfer_characteristics(characteristics)
165
+ @color_transfer_characteristics = "#{@track_id}:#{characteristics}"
166
+ self
167
+ end
168
+
169
+ def with_color_primaries(primaries)
170
+ @color_primaries = "#{@track_id}:#{primaries}"
171
+ self
172
+ end
173
+
174
+ def with_max_content_light(light)
175
+ @max_content_light = "#{@track_id}:#{light}"
176
+ self
177
+ end
178
+
179
+ def with_max_frame_light(light)
180
+ @max_frame_light = "#{@track_id}:#{light}"
181
+ self
182
+ end
183
+
184
+ def with_chromaticity_coordinates(red_x, red_y, green_x, green_y, blue_x, blue_y)
185
+ @chromaticity_coordinates = "#{@track_id}:#{red_x},#{red_y},#{green_x},#{green_y},#{blue_x},#{blue_y}"
186
+ self
187
+ end
188
+
189
+ def with_white_color_coordinate(x, y)
190
+ @white_color_coordinate = "#{@track_id}:#{x},#{y}"
191
+ self
192
+ end
193
+
194
+ def with_max_luminance(luminance)
195
+ @max_luminance = "#{@track_id}:#{luminance}"
196
+ self
197
+ end
198
+
199
+ def with_min_luminance(luminance)
200
+ @min_luminance = "#{@track_id}:#{luminance}"
201
+ self
202
+ end
203
+
204
+ def with_projection_type(type)
205
+ @projection_type = "#{@track_id}:#{type}"
206
+ self
207
+ end
208
+
209
+ def with_projection_private(hex_data)
210
+ @projection_private = "#{@track_id}:#{hex_data}"
211
+ self
212
+ end
213
+
214
+ def with_projection_pose_yaw(yaw)
215
+ @projection_pose_yaw = "#{@track_id}:#{yaw}"
216
+ self
217
+ end
218
+
219
+ def with_projection_pose_pitch(pitch)
220
+ @projection_pose_pitch = "#{@track_id}:#{pitch}"
221
+ self
222
+ end
223
+
224
+ def with_projection_pose_roll(roll)
225
+ @projection_pose_roll = "#{@track_id}:#{roll}"
226
+ self
227
+ end
228
+
229
+ def with_field_order(order)
230
+ @field_order = "#{@track_id}:#{order}"
231
+ self
232
+ end
233
+
234
+ def with_stereo_mode(mode)
235
+ @stereo_mode = "#{@track_id}:#{mode}"
236
+ self
237
+ end
238
+
239
+ def with_sub_charset(charset)
240
+ @sub_charset = "#{@track_id}:#{charset}"
241
+ self
242
+ end
243
+
244
+ def initialize(track_id)
245
+ raise Errors::MkvToolNixError, 'track_id can\'t be nil' if track_id.nil?
246
+
247
+ @track_id = track_id
248
+ end
249
+
250
+ def add_to_cmd(cmd)
251
+ cmd << '--sync' << @track_sync unless @track_sync.nil?
252
+ cmd << '--cues' << @cues unless @cues.nil?
253
+ cmd << '--default-track' << @is_default unless @is_default.nil?
254
+ cmd << '--forced-track' << @is_forced unless @is_forced.nil?
255
+ cmd << '--hearing-impaired-flag' << @is_hearing_impaired unless @is_hearing_impaired.nil?
256
+ cmd << '--visual-impaired-flag' << @is_visual_impaired unless @is_visual_impaired.nil?
257
+ cmd << '--text-descriptions-flag' << @is_text_description unless @is_text_description.nil?
258
+ cmd << '--original-flag' << @is_original unless @is_original.nil?
259
+ cmd << '--commentary-flag' << @is_commentary unless @is_commentary.nil?
260
+ cmd << '--track-name' << @name unless @name.nil?
261
+ cmd << '--language' << @language unless @language.nil?
262
+ cmd << '--tags' << @tag_file unless @tag_file.nil?
263
+ cmd << '--aac-is-sbr' << @aac_sbr unless @aac_sbr.nil?
264
+ cmd << '--reduce-to-core' unless @reduce_to_core.nil?
265
+ cmd << '--remove-dialog-normalization-gain' unless @no_dialog_norm_gain.nil?
266
+ cmd << '--timestamps' << @timestamp_file unless @timestamp_file.nil?
267
+ cmd << '--default-duration' << @default_duration_in_secs unless @default_duration_in_secs.nil?
268
+ cmd << '--fix-bitstream-timing-information' << @fix_bitstream_timing_info unless @fix_bitstream_timing_info.nil?
269
+ cmd << '--compression' << @compression unless @compression.nil?
270
+ cmd << '--fourcc' << @four_cc unless @four_cc.nil?
271
+ cmd << '--display-dimensions' << @dimensions unless @dimensions.nil?
272
+ cmd << '--aspect-ratio' << @aspect_ratio unless @aspect_ratio.nil?
273
+ cmd << '--cropping' << @cropping unless @cropping.nil?
274
+ cmd << '--colour-matrix-coefficients' << @color_matrix_coefficients unless @color_matrix_coefficients.nil?
275
+ cmd << '--colour-bits-per-channel' << @color_bits_per_channel unless @color_bits_per_channel.nil?
276
+ cmd << '--chroma-subsample' << @chroma_sub_sample unless @chroma_sub_sample.nil?
277
+ cmd << '--cb-subsample' << @cb_sub_sample unless @cb_sub_sample.nil?
278
+ cmd << '--chroma-siting' << @chroma_siting unless @chroma_siting.nil?
279
+ cmd << '--colour-range' << @color_range unless @color_range.nil?
280
+ cmd << '--colour-transfer-characteristics' << @color_transfer_characteristics unless @color_transfer_characteristics.nil?
281
+ cmd << '--colour-primaries' << @color_primaries unless @color_primaries.nil?
282
+ cmd << '--max-content-light' << @max_content_light unless @max_content_light.nil?
283
+ cmd << '--max-frame-light' << @max_frame_light unless @max_frame_light.nil?
284
+ cmd << '--chromaticity-coordinates' << @chromaticity_coordinates unless @chromaticity_coordinates.nil?
285
+ cmd << '--white-colour-coordinates' << @white_color_coordinate unless @white_color_coordinate.nil?
286
+ cmd << '--max-luminance' << @max_luminance unless @max_luminance.nil?
287
+ cmd << '--min-luminance' << @min_luminance unless @min_luminance.nil?
288
+ cmd << '--projection-type' << @projection_type unless @projection_type.nil?
289
+ cmd << '--projection-private' << @projection_private unless @projection_private.nil?
290
+ cmd << '--projection-pose-yaw' << @projection_pose_yaw unless @projection_pose_yaw.nil?
291
+ cmd << '--projection-pose-pitch' << @projection_pose_pitch unless @projection_pose_pitch.nil?
292
+ cmd << '--projection-pose-roll' << @projection_pose_roll unless @projection_pose_roll.nil?
293
+ cmd << '--field-order' << @field_order unless @field_order.nil?
294
+ cmd << '--stereo-mode' << @stereo_mode unless @stereo_mode.nil?
295
+ cmd << '--sub-charset' << @sub_charset unless @sub_charset.nil?
296
+ nil
297
+ end
298
+ end
299
+
300
+ module CueMode
301
+ NONE = 'none'
302
+ I_FRAMES = 'iframes'
303
+ ALL = 'all'
304
+ end
305
+
306
+ module Compression
307
+ NONE = 'none'
308
+ ZLIB = 'zlib'
309
+ MPEG4_P2 = 'mpeg4_p2'
310
+ end
311
+
312
+ module ColorMatrixCoefficients
313
+ GBR = 0
314
+ BT709 = 1
315
+ UNSPECIFIED = 2
316
+ FCC = 4
317
+ BT470BG = 5
318
+ SMPTE_170M = 6
319
+ SMPTE_240M = 7
320
+ YCOCG = 8
321
+ BT2020_NON_CONSTANT_LUMINANCE = 9
322
+ BT2020_CONSTANT_LUMINANCE = 10
323
+ end
324
+
325
+ module ColorRange
326
+ UNSPECIFIED = 0
327
+ BROADCAST_RANGE = 1
328
+ FULL_RANGE = 2
329
+ DEFINED_BY_MATRIX_TRANSFER_COEFFICIENTS = 3
330
+ end
331
+
332
+ module ColorTransferCharacteristics
333
+ ITU_R_BT_709 = 1
334
+ UNSPECIFIED = 2
335
+ GAMMA_2_2_CURVE = 4
336
+ GAMMA_8_CURVE = 5
337
+ SMPTE_170M = 6
338
+ SMPTE_240M = 7
339
+ LINEAR = 8
340
+ LOG = 9
341
+ LOG_SQRT = 10
342
+ IEC_61966_2_4 = 11
343
+ ITU_R_BT_1361_EXTENDED_COLOR_GAMUT = 12
344
+ IEC_61966_2_1 = 13
345
+ ITU_R_BT_2020_10_BIT = 14
346
+ ITU_R_BT_2020_12_BIT = 15
347
+ SMPTE_ST_2084 = 16
348
+ SMPTE_ST_428_1 = 17
349
+ ARIB_STD_B67_HLG = 18
350
+ end
351
+
352
+ module ColorPrimaries
353
+ ITU_R_BT_709 = 1
354
+ ITU_R_BT_470M = 4
355
+ ITU_R_BT_470BG = 5
356
+ SMPTE_170M = 6
357
+ SMPTE_240M = 7
358
+ FILM = 8
359
+ ITU_R_BT_2020 = 9
360
+ SMPTE_ST_428_1 = 10
361
+ JEDEC_P22_PHOSPHORS = 22
362
+ end
363
+
364
+ module ProjectionType
365
+ RECTANGULAR = 0
366
+ EQUIRECTANGULAR = 1
367
+ CUBEMAP = 2
368
+ MESH = 3
369
+ end
370
+
371
+ module StereoMode
372
+ MONO = 'mono'
373
+ SIDE_BY_SIDE_LEFT_FIRST = 'side_by_side_left_first'
374
+ TOP_BOTTOM_RIGHT_FIRST = 'top_bottom_right_first'
375
+ TOP_BOTTOM_LEFT_FIRST = 'top_bottom_left_first'
376
+ CHECKERBOARD_RIGHT_FIRST = 'checkerboard_right_first'
377
+ CHECKERBOARD_LEFT_FIRST = 'checkerboard_left_first'
378
+ ROW_INTERLEAVED_RIGHT_FIRST = 'row_interleaved_right_first'
379
+ ROW_INTERLEAVED_LEFT_FIRST = 'row_interleaved_left_first'
380
+ COLUMN_INTERLEAVED_RIGHT_FIRST = 'column_interleaved_right_first'
381
+ COLUMN_INTERLEAVED_LEFT_FIRST = 'column_interleaved_left_first'
382
+ ANAGLYPH_CYAN_RED = 'anaglyph_cyan_red'
383
+ SIDE_BY_SIDE_RIGHT_FIRST = 'side_by_side_right_first'
384
+ ANAGLYPH_GREEN_MAGENTA = 'anaglyph_green_magenta'
385
+ BOTH_EYES_LACED_LEFT_FIRST = 'both_eyes_laced_left_first'
386
+ BOTH_EYES_LACED_RIGHT_FIRST = 'both_eyes_laced_right_first'
387
+ end
388
+ end
389
+ end
390
+ end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MkvToolNix
4
+ module Types
5
+ module Merge
6
+ class OutputControl
7
+
8
+ attr_reader :title, :default_language, :track_order, :cluster_length_blocks, :generate_meta_seek,
9
+ :timestamp_scale, :enable_duration, :no_cues, :no_date, :disable_lacing, :disable_language_ietf,
10
+ :disable_track_statistics_tags
11
+
12
+ def with_title(title)
13
+ @title = title
14
+ self
15
+ end
16
+
17
+ def with_default_language(language)
18
+ @default_language = language
19
+ self
20
+ end
21
+
22
+ def with_track_order(order)
23
+ if order.is_a?(String)
24
+ @track_order = order
25
+ return self
26
+ end
27
+
28
+ @track_order = order.map do |it|
29
+ # @track_order.map(&:to_s).join(',')
30
+ case it
31
+ when TrackOrder
32
+ next it.to_s
33
+ when Array
34
+ next ["#{it[0]}:#{it[1]}"]
35
+ when Hash
36
+ next ["#{it[:file_index]}:#{it[:track_id]}"]
37
+ end
38
+ end.join(',')
39
+
40
+ self
41
+ end
42
+
43
+ def with_cluster_length_in_blocks(blocks)
44
+ @cluster_length_blocks = blocks
45
+ self
46
+ end
47
+
48
+ def with_meta_seek_element
49
+ @generate_meta_seek = true
50
+ self
51
+ end
52
+
53
+ def with_timestamp_scale(factor)
54
+ @timestamp_scale = factor
55
+ self
56
+ end
57
+
58
+ def with_durations_enabled
59
+ @enable_duration = true
60
+ self
61
+ end
62
+
63
+ def without_cues
64
+ @no_cues = true
65
+ self
66
+ end
67
+
68
+ def without_date
69
+ @no_date = true
70
+ self
71
+ end
72
+
73
+ def with_disabled_lacing
74
+ @disable_lacing = true
75
+ self
76
+ end
77
+
78
+ def without_track_statistics_tags
79
+ @disable_track_statistics_tags = true
80
+ self
81
+ end
82
+
83
+ def without_language_ietf
84
+ @disable_language_ietf = true
85
+ self
86
+ end
87
+
88
+ def add_to_cmd(cmd)
89
+ cmd << '--title' << @title unless @title.nil?
90
+ cmd << '--default-language' << @default_language unless @default_language.nil?
91
+ cmd << '--track-order' << @track_order unless @track_order.nil?
92
+ cmd << '--cluster-length' << @cluster_length_blocks unless @cluster_length_blocks.nil?
93
+ cmd << '--clusters-in-meta-seek' if @generate_meta_seek
94
+ cmd << '--timestamp-scale' << @timestamp_scale unless @timestamp_scale.nil?
95
+ cmd << '--enable-durations' if @enable_duration
96
+ cmd << '--no-cues' if @no_cues
97
+ cmd << '--no-date' if @no_date
98
+ cmd << '--disable-lacing' if @disable_lacing
99
+ cmd << '--disable-track-statistics-tags' if @disable_track_statistics_tags
100
+ cmd << '--disable-language-ietf' if @disable_language_ietf
101
+ nil
102
+ end
103
+ end
104
+
105
+ class TrackOrder
106
+
107
+ attr_reader :file_index, :track_id
108
+
109
+ def to_s
110
+ "#{@file_index}:#{@track_id}"
111
+ end
112
+
113
+ def initialize(file_index, track_id)
114
+ @file_index = file_index
115
+ @track_id = track_id
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MkvToolNix
4
+ module Types
5
+ module Merge
6
+ class SegmentInfo
7
+
8
+ attr_reader :file, :uids
9
+
10
+ def for_file(file)
11
+ @file = file
12
+ self
13
+ end
14
+
15
+ def for_uids(uids)
16
+ @uids = uids
17
+ self
18
+ end
19
+
20
+ def add_to_cmd(cmd)
21
+ cmd << '--segmentinfo' << @file unless @file.nil?
22
+ cmd << '--segment-uid' << @uids.join(',') unless @uids.nil?
23
+ nil
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MkvToolNix
4
+ module Types
5
+ module Merge
6
+ class Tags
7
+
8
+ attr_reader :file
9
+
10
+ def initialize(file)
11
+ @file = file
12
+ end
13
+
14
+ def add_to_cmd(cmd)
15
+ cmd << '--global-tags' << @file unless @file.nil?
16
+ nil
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
data/lib/mkvtoolnix.rb CHANGED
@@ -27,9 +27,17 @@ require 'mkvtoolnix/types/info/subtitle'
27
27
  require 'mkvtoolnix/types/info/video'
28
28
  require 'mkvtoolnix/types/info/attachment'
29
29
 
30
- require 'mkvtoolnix/modules/mkvmerge'
30
+ require 'mkvtoolnix/types/merge/attachment'
31
+ require 'mkvtoolnix/types/merge/chapter'
32
+ require 'mkvtoolnix/types/merge/input_track_options'
33
+ require 'mkvtoolnix/types/merge/input_file'
34
+ require 'mkvtoolnix/types/merge/output_control'
35
+ require 'mkvtoolnix/types/merge/segment_info'
36
+ require 'mkvtoolnix/types/merge/tags'
37
+
31
38
  require 'mkvtoolnix/modules/mkvpropedit'
32
39
  require 'mkvtoolnix/modules/mkvextract'
40
+ require 'mkvtoolnix/modules/mkvmerge'
33
41
 
34
42
  module MkvToolNix
35
43
 
@@ -64,7 +72,12 @@ module MkvToolNix
64
72
 
65
73
  def disable_language_ietf(disabled: true)
66
74
  @mkvpropedit.disable_language_ietf = disabled
75
+ @mkvmerge.disable_language_ietf = disabled
67
76
  self
68
77
  end
78
+
79
+ def default_language(language = 'und')
80
+ @mkvmerge.default_language = language
81
+ end
69
82
  end
70
83
  end
data/mkvtoolnix.gemspec CHANGED
@@ -2,14 +2,14 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'mkvtoolnix'
5
- spec.version = '0.7.0'
5
+ spec.version = '1.0.0'
6
6
  spec.authors = ['Christian Feier']
7
7
  spec.email = ['Christian.Feier@gmail.com']
8
8
 
9
- spec.summary = 'A wrapper for MkvToolNix https://mkvtoolnix.download/ to create, alter and inspect MKV files. For more'\
10
- ' information, please check the github page: https://github.com/cfe86/RubyMkvToolNix'
9
+ spec.summary = 'A wrapper for MkvToolNix https://mkvtoolnix.download/ to create, alter and inspect MKV files.'\
10
+ 'For more information, please check the github page: https://github.com/cfe86/RubyMkvToolNix'
11
11
  spec.description = 'A wrapper for MkvToolNix https://mkvtoolnix.download/ to create, alter and inspect MKV files.'\
12
- 'Currently mkvpropedit and mkvextract are fully implemented. mkvmerge is in progress.'
12
+ 'Currently mkvpropedit and mkvextract are fully implemented. mkvmerge is completed except the split options.'
13
13
  spec.homepage = 'https://github.com/cfe86/RubyMkvToolNix'
14
14
  spec.license = 'MIT'
15
15
  spec.required_ruby_version = '>= 2.5.0'
metadata CHANGED
@@ -1,18 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mkvtoolnix
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Feier
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-30 00:00:00.000000000 Z
11
+ date: 2021-12-02 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A wrapper for MkvToolNix https://mkvtoolnix.download/ to create, alter
14
14
  and inspect MKV files.Currently mkvpropedit and mkvextract are fully implemented.
15
- mkvmerge is in progress.
15
+ mkvmerge is completed except the split options.
16
16
  email:
17
17
  - Christian.Feier@gmail.com
18
18
  executables: []
@@ -43,6 +43,13 @@ files:
43
43
  - lib/mkvtoolnix/types/info/mkv_container.rb
44
44
  - lib/mkvtoolnix/types/info/subtitle.rb
45
45
  - lib/mkvtoolnix/types/info/video.rb
46
+ - lib/mkvtoolnix/types/merge/attachment.rb
47
+ - lib/mkvtoolnix/types/merge/chapter.rb
48
+ - lib/mkvtoolnix/types/merge/input_file.rb
49
+ - lib/mkvtoolnix/types/merge/input_track_options.rb
50
+ - lib/mkvtoolnix/types/merge/output_control.rb
51
+ - lib/mkvtoolnix/types/merge/segment_info.rb
52
+ - lib/mkvtoolnix/types/merge/tags.rb
46
53
  - lib/mkvtoolnix/types/propedit/audio_property.rb
47
54
  - lib/mkvtoolnix/types/propedit/common_property.rb
48
55
  - lib/mkvtoolnix/types/propedit/info_property.rb
@@ -76,5 +83,5 @@ rubygems_version: 3.2.15
76
83
  signing_key:
77
84
  specification_version: 4
78
85
  summary: 'A wrapper for MkvToolNix https://mkvtoolnix.download/ to create, alter and
79
- inspect MKV files. For more information, please check the github page: https://github.com/cfe86/RubyMkvToolNix'
86
+ inspect MKV files.For more information, please check the github page: https://github.com/cfe86/RubyMkvToolNix'
80
87
  test_files: []