mkvtoolnix 0.7.0 → 1.0.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 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: []