mm_tool 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitattributes +4 -0
- data/.gitignore +24 -0
- data/Gemfile +3 -0
- data/LICENSE.md +22 -0
- data/README.md +15 -0
- data/Rakefile +2 -0
- data/Truth Tables.xlsx +0 -0
- data/bin/console +14 -0
- data/bin/mm_tool +19 -0
- data/bin/setup +8 -0
- data/lib/mm_tool.rb +21 -0
- data/lib/mm_tool/application_main.rb +172 -0
- data/lib/mm_tool/mm_movie.rb +217 -0
- data/lib/mm_tool/mm_movie_ignore_list.rb +68 -0
- data/lib/mm_tool/mm_movie_stream.rb +492 -0
- data/lib/mm_tool/mm_tool_cli.rb +322 -0
- data/lib/mm_tool/mm_user_defaults.rb +290 -0
- data/lib/mm_tool/output_helper.rb +121 -0
- data/lib/mm_tool/user_defaults.rb +377 -0
- data/lib/mm_tool/version.rb +3 -0
- data/mm_tool.gemspec +50 -0
- metadata +155 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
module MmTool
|
2
|
+
|
3
|
+
#=============================================================================
|
4
|
+
# A list of movie files to ignore during :normal and :all scan types. Will
|
5
|
+
# keep the on-file list in sync with the in-memory list.
|
6
|
+
#=============================================================================
|
7
|
+
class MmMovieIgnoreList
|
8
|
+
|
9
|
+
require 'fileutils'
|
10
|
+
require 'yaml'
|
11
|
+
|
12
|
+
#------------------------------------------------------------
|
13
|
+
# Singleton accessor.
|
14
|
+
#------------------------------------------------------------
|
15
|
+
def self.shared_ignore_list
|
16
|
+
unless @self
|
17
|
+
@self = self.new
|
18
|
+
end
|
19
|
+
@self
|
20
|
+
end
|
21
|
+
|
22
|
+
#------------------------------------------------------------
|
23
|
+
# Initialize
|
24
|
+
#------------------------------------------------------------
|
25
|
+
def initialize
|
26
|
+
@ignore_list = []
|
27
|
+
if !File.file?(file_path)
|
28
|
+
FileUtils.mkdir_p(File.dirname(file_path))
|
29
|
+
else
|
30
|
+
#noinspection RubyResolve
|
31
|
+
@ignore_list = YAML.load(File.read(file_path))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
#------------------------------------------------------------
|
36
|
+
# The location on the filesystem where the file exists.
|
37
|
+
#------------------------------------------------------------
|
38
|
+
def file_path
|
39
|
+
PATH_IGNORE_LIST
|
40
|
+
end
|
41
|
+
|
42
|
+
#------------------------------------------------------------
|
43
|
+
# Is the given file on the ignore list?
|
44
|
+
#------------------------------------------------------------
|
45
|
+
def include?(path)
|
46
|
+
@ignore_list.include?(path)
|
47
|
+
end
|
48
|
+
|
49
|
+
#------------------------------------------------------------
|
50
|
+
# Add a path to the list, and write list to disk.
|
51
|
+
#------------------------------------------------------------
|
52
|
+
def add(path:)
|
53
|
+
new_list = @ignore_list |= [path]
|
54
|
+
@ignore_list = new_list.sort
|
55
|
+
File.open(file_path, 'w') { |file| file.write(@ignore_list.to_yaml) }
|
56
|
+
end
|
57
|
+
|
58
|
+
#------------------------------------------------------------
|
59
|
+
# Remove a path from the list, and update on disk.
|
60
|
+
#------------------------------------------------------------
|
61
|
+
def remove(path:)
|
62
|
+
@ignore_list.delete(path)
|
63
|
+
File.open(file_path, 'w') { |file| file.write(@ignore_list.to_yaml) }
|
64
|
+
end
|
65
|
+
|
66
|
+
end # class
|
67
|
+
|
68
|
+
end # module
|
@@ -0,0 +1,492 @@
|
|
1
|
+
module MmTool
|
2
|
+
|
3
|
+
#=============================================================================
|
4
|
+
# A stream of an MmMovie. Instances contain simple accessors to the data
|
5
|
+
# made available by ffmpeg, and have knowledge on how to generate useful
|
6
|
+
# arguments for ffmpeg and mkvpropedit.
|
7
|
+
#=============================================================================
|
8
|
+
class MmMovieStream
|
9
|
+
|
10
|
+
require 'streamio-ffmpeg'
|
11
|
+
require 'mm_tool/mm_movie'
|
12
|
+
|
13
|
+
#------------------------------------------------------------
|
14
|
+
# Given an array of related files, this class method returns
|
15
|
+
# an array of MmMovieStreams reflecting the streams present
|
16
|
+
# in each of them.
|
17
|
+
#------------------------------------------------------------
|
18
|
+
def self.streams(with_files:)
|
19
|
+
# Arrays are passed around by reference; when this array is created and
|
20
|
+
# used as a reference in each stream, and *also* returned from this class
|
21
|
+
# method, everyone will still be using the same reference. It's important
|
22
|
+
# below to build up this array without replacing it with another instance.
|
23
|
+
streams = []
|
24
|
+
with_files.each_with_index do |path, i|
|
25
|
+
ff_movie = FFMPEG::Movie.new(path)
|
26
|
+
ff_movie.metadata[:streams].each do |stream|
|
27
|
+
streams << MmMovieStream.new(stream_data: stream, source_file: path, file_number: i, streams_ref: streams)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
streams
|
31
|
+
end
|
32
|
+
|
33
|
+
#------------------------------------------------------------
|
34
|
+
# Initialize
|
35
|
+
#------------------------------------------------------------
|
36
|
+
def initialize(stream_data:, source_file:, file_number:, streams_ref:)
|
37
|
+
@defaults = MmUserDefaults.shared_user_defaults
|
38
|
+
@data = stream_data
|
39
|
+
@source_file = source_file
|
40
|
+
@file_number = file_number
|
41
|
+
@streams = streams_ref
|
42
|
+
end
|
43
|
+
|
44
|
+
#------------------------------------------------------------
|
45
|
+
# Attribute accessors
|
46
|
+
#------------------------------------------------------------
|
47
|
+
attr_accessor :file_number
|
48
|
+
attr_accessor :source_file
|
49
|
+
|
50
|
+
#------------------------------------------------------------
|
51
|
+
# Property - returns the index of the stream.
|
52
|
+
#------------------------------------------------------------
|
53
|
+
def index
|
54
|
+
@data[:index]
|
55
|
+
end
|
56
|
+
|
57
|
+
#------------------------------------------------------------
|
58
|
+
# Property - returns the input specifier of the stream.
|
59
|
+
#------------------------------------------------------------
|
60
|
+
def input_specifier
|
61
|
+
"#{@file_number}:#{index}"
|
62
|
+
end
|
63
|
+
|
64
|
+
#------------------------------------------------------------
|
65
|
+
# Property - returns the codec name of the stream.
|
66
|
+
#------------------------------------------------------------
|
67
|
+
def codec_name
|
68
|
+
@data[:codec_name]
|
69
|
+
end
|
70
|
+
|
71
|
+
#------------------------------------------------------------
|
72
|
+
# Property - returns the codec type of the stream.
|
73
|
+
#------------------------------------------------------------
|
74
|
+
def codec_type
|
75
|
+
@data[:codec_type]
|
76
|
+
end
|
77
|
+
|
78
|
+
#------------------------------------------------------------
|
79
|
+
# Property - returns the coded width of the stream.
|
80
|
+
#------------------------------------------------------------
|
81
|
+
def coded_width
|
82
|
+
@data[:coded_width]
|
83
|
+
end
|
84
|
+
|
85
|
+
#------------------------------------------------------------
|
86
|
+
# Property - returns the coded height of the stream.
|
87
|
+
#------------------------------------------------------------
|
88
|
+
def coded_height
|
89
|
+
@data[:coded_height]
|
90
|
+
end
|
91
|
+
|
92
|
+
#------------------------------------------------------------
|
93
|
+
# Property - returns the number of channels of the stream.
|
94
|
+
#------------------------------------------------------------
|
95
|
+
def channels
|
96
|
+
@data[:channels]
|
97
|
+
end
|
98
|
+
|
99
|
+
#------------------------------------------------------------
|
100
|
+
# Property - returns the channel layout of the stream.
|
101
|
+
#------------------------------------------------------------
|
102
|
+
def channel_layout
|
103
|
+
@data[:channel_layout]
|
104
|
+
end
|
105
|
+
|
106
|
+
#------------------------------------------------------------
|
107
|
+
# Property - returns the language of the stream, or 'und'
|
108
|
+
# if the language is not defined.
|
109
|
+
#------------------------------------------------------------
|
110
|
+
def language
|
111
|
+
if @data.key?(:tags)
|
112
|
+
lang = @data[:tags][:language]
|
113
|
+
lang = @data[:tags][:LANGUAGE] unless lang
|
114
|
+
lang = 'und' unless lang
|
115
|
+
else
|
116
|
+
lang = 'und'
|
117
|
+
end
|
118
|
+
lang
|
119
|
+
end
|
120
|
+
|
121
|
+
#------------------------------------------------------------
|
122
|
+
# Property - returns the title of the stream, or nil.
|
123
|
+
#------------------------------------------------------------
|
124
|
+
def title
|
125
|
+
if @data.key?(:tags)
|
126
|
+
@data[:tags][:title]
|
127
|
+
else
|
128
|
+
nil
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
#------------------------------------------------------------
|
133
|
+
# Property - returns the disposition flags of the stream as
|
134
|
+
# a comma-separated list for compactness.
|
135
|
+
#------------------------------------------------------------
|
136
|
+
def dispositions
|
137
|
+
MmMovie.dispositions
|
138
|
+
.collect {|symbol| @data[:disposition][symbol]}
|
139
|
+
.join(',')
|
140
|
+
end
|
141
|
+
|
142
|
+
#------------------------------------------------------------
|
143
|
+
# Property - returns an appropriate "quality" indicator
|
144
|
+
# based on the type of the stream.
|
145
|
+
#------------------------------------------------------------
|
146
|
+
def quality_01
|
147
|
+
if codec_type == 'audio'
|
148
|
+
channels
|
149
|
+
elsif codec_type == 'video'
|
150
|
+
coded_width
|
151
|
+
else
|
152
|
+
nil
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
#------------------------------------------------------------
|
157
|
+
# Property - returns a different appropriate "quality"
|
158
|
+
# indicator based on the type of the stream.
|
159
|
+
#------------------------------------------------------------
|
160
|
+
def quality_02
|
161
|
+
if codec_type == 'audio'
|
162
|
+
channel_layout
|
163
|
+
elsif codec_type == 'video'
|
164
|
+
coded_height
|
165
|
+
else
|
166
|
+
nil
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
#------------------------------------------------------------
|
171
|
+
# Property - returns a convenient label indicating the
|
172
|
+
# recommended actions for the stream.
|
173
|
+
#------------------------------------------------------------
|
174
|
+
def action_label
|
175
|
+
"#{output_specifier} #{actions.select {|a| a != :interesting}.join(' ')}"
|
176
|
+
end
|
177
|
+
|
178
|
+
#------------------------------------------------------------
|
179
|
+
# Property - indicates whether or not the stream is the
|
180
|
+
# default stream per its dispositions.
|
181
|
+
#------------------------------------------------------------
|
182
|
+
def default?
|
183
|
+
@data[:disposition][:default] == 1
|
184
|
+
end
|
185
|
+
|
186
|
+
#------------------------------------------------------------
|
187
|
+
# Property - indicates whether or not the stream is
|
188
|
+
# considered "low quality" based on the application
|
189
|
+
# configuration.
|
190
|
+
#------------------------------------------------------------
|
191
|
+
def low_quality?
|
192
|
+
if codec_type == 'audio'
|
193
|
+
channels.to_i < @defaults[:min_channels].to_i
|
194
|
+
elsif codec_type == 'video'
|
195
|
+
coded_width.to_i < @defaults[:min_width].to_i
|
196
|
+
else
|
197
|
+
false
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
#------------------------------------------------------------
|
202
|
+
# Property - stream action includes :drop?
|
203
|
+
#------------------------------------------------------------
|
204
|
+
def drop?
|
205
|
+
actions.include?(:drop)
|
206
|
+
end
|
207
|
+
|
208
|
+
#------------------------------------------------------------
|
209
|
+
# Property - stream action includes :copy?
|
210
|
+
#------------------------------------------------------------
|
211
|
+
def copy?
|
212
|
+
actions.include?(:copy)
|
213
|
+
end
|
214
|
+
|
215
|
+
#------------------------------------------------------------
|
216
|
+
# Property - stream action includes :transcode?
|
217
|
+
#------------------------------------------------------------
|
218
|
+
def transcode?
|
219
|
+
actions.include?(:transcode)
|
220
|
+
end
|
221
|
+
|
222
|
+
#------------------------------------------------------------
|
223
|
+
# Property - stream action includes :set_language?
|
224
|
+
#------------------------------------------------------------
|
225
|
+
def set_language?
|
226
|
+
actions.include?(:set_language)
|
227
|
+
end
|
228
|
+
|
229
|
+
#------------------------------------------------------------
|
230
|
+
# Property - stream action includes :interesting?
|
231
|
+
#------------------------------------------------------------
|
232
|
+
def interesting?
|
233
|
+
actions.include?(:interesting)
|
234
|
+
end
|
235
|
+
|
236
|
+
#------------------------------------------------------------
|
237
|
+
# Property - indicates whether or not the stream will be
|
238
|
+
# unique for its type at output.
|
239
|
+
#------------------------------------------------------------
|
240
|
+
def output_unique?
|
241
|
+
@streams.count {|s| s.codec_type == codec_type && !s.drop? } == 1
|
242
|
+
end
|
243
|
+
|
244
|
+
#------------------------------------------------------------
|
245
|
+
# Property - indicates whether or not this stream is the
|
246
|
+
# only one of its type.
|
247
|
+
#------------------------------------------------------------
|
248
|
+
def one_of_a_kind?
|
249
|
+
@streams.count {|s| s.codec_type == codec_type && s != self } == 0
|
250
|
+
end
|
251
|
+
|
252
|
+
#------------------------------------------------------------
|
253
|
+
# Property - returns the index of the stream in the output
|
254
|
+
# file.
|
255
|
+
#------------------------------------------------------------
|
256
|
+
def output_index
|
257
|
+
@streams.select {|s| !s.drop? }.index(self)
|
258
|
+
end
|
259
|
+
|
260
|
+
#------------------------------------------------------------
|
261
|
+
# Property - returns a specific output specifier for the
|
262
|
+
# stream, such as v:0 or a:2.
|
263
|
+
#------------------------------------------------------------
|
264
|
+
def output_specifier
|
265
|
+
idx = @streams.select {|s| s.codec_type == codec_type && !s.drop?}.index(self)
|
266
|
+
idx ? "#{codec_type[0]}:#{idx}" : ' ⬇ '
|
267
|
+
end
|
268
|
+
|
269
|
+
#------------------------------------------------------------
|
270
|
+
# Property - returns the -i input instruction for this
|
271
|
+
# stream.
|
272
|
+
#------------------------------------------------------------
|
273
|
+
def instruction_input
|
274
|
+
src = if @file_number == 0
|
275
|
+
File.join(File.dirname(@source_file), File.basename(@source_file, '.*') + @defaults[:suffix] + File.extname(@source_file))
|
276
|
+
else
|
277
|
+
@source_file
|
278
|
+
end
|
279
|
+
"-i \"#{src}\" \\"
|
280
|
+
end
|
281
|
+
|
282
|
+
#------------------------------------------------------------
|
283
|
+
# Property - returns the -map instruction for this stream,
|
284
|
+
# according to the action(s) determined.
|
285
|
+
#------------------------------------------------------------
|
286
|
+
def instruction_map
|
287
|
+
drop? ? nil : "-map #{input_specifier} \\"
|
288
|
+
end
|
289
|
+
|
290
|
+
#------------------------------------------------------------
|
291
|
+
# Property - returns an instruction for handling the stream,
|
292
|
+
# according to the action(s) determined.
|
293
|
+
#------------------------------------------------------------
|
294
|
+
def instruction_action
|
295
|
+
if copy?
|
296
|
+
"-codec:#{output_specifier} copy \\"
|
297
|
+
elsif transcode?
|
298
|
+
if codec_type == 'audio'
|
299
|
+
encode_to = @defaults[:codecs_audio_preferred][0]
|
300
|
+
elsif codec_type == 'video'
|
301
|
+
encode_to = @defaults[:codecs_video_preferred][0]
|
302
|
+
else
|
303
|
+
raise Exception.new "Error: somehow the program branched where it shouldn't have."
|
304
|
+
end
|
305
|
+
"-codec:#{output_specifier} #{encoder_string(for_codec: encode_to)} \\"
|
306
|
+
else
|
307
|
+
nil
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
#------------------------------------------------------------
|
312
|
+
# Property - returns an instruction for setting the metadata
|
313
|
+
# of the stream, if necessary.
|
314
|
+
#------------------------------------------------------------
|
315
|
+
def instruction_metadata
|
316
|
+
# We only want to set fixed_lang if options allow us to fix the language,
|
317
|
+
# and we want to set subtitle language from the filename, if applicable.
|
318
|
+
fixed_lang = @defaults[:fix_undefined_language] ? @defaults[:undefined_language] : nil
|
319
|
+
lang = subtitle_file_language ? subtitle_file_language : fixed_lang
|
320
|
+
set_language = set_language? ? "language=#{lang} " : nil
|
321
|
+
set_title = title && ! @defaults[:ignore_titles] ? "title=\"#{title}\" " : nil
|
322
|
+
|
323
|
+
if set_language || set_title
|
324
|
+
"-metadata:s:#{output_specifier} #{set_language}#{set_title}\\"
|
325
|
+
else
|
326
|
+
nil
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
#------------------------------------------------------------
|
331
|
+
# Property - returns an instruction for setting the stream's
|
332
|
+
# default disposition, if necessary.
|
333
|
+
#------------------------------------------------------------
|
334
|
+
def instruction_disposition
|
335
|
+
set_disposition = output_unique? && !default? && !drop? ? "default " : nil
|
336
|
+
|
337
|
+
if set_disposition
|
338
|
+
"-disposition:#{output_specifier} #{set_disposition}\\"
|
339
|
+
else
|
340
|
+
nil
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
|
345
|
+
#============================================================
|
346
|
+
private
|
347
|
+
#============================================================
|
348
|
+
|
349
|
+
|
350
|
+
#------------------------------------------------------------
|
351
|
+
# Property - returns an array of actions that are suggested
|
352
|
+
# for the stream based on quality, language, codec, etc.
|
353
|
+
#------------------------------------------------------------
|
354
|
+
def actions
|
355
|
+
|
356
|
+
#------------------------------------------------------------
|
357
|
+
# Note: logic below a result of Karnaugh mapping of the
|
358
|
+
# selection truth table for each desired action. There's
|
359
|
+
# probably an excel file somewhere in the repository.
|
360
|
+
#------------------------------------------------------------
|
361
|
+
|
362
|
+
if @actions.nil?
|
363
|
+
@actions = []
|
364
|
+
|
365
|
+
#––––––––––––––––––––––––––––––––––––––––––––––––––
|
366
|
+
# subtitle stream handler
|
367
|
+
#––––––––––––––––––––––––––––––––––––––––––––––––––
|
368
|
+
if codec_type == 'subtitle'
|
369
|
+
|
370
|
+
a = @defaults[:keep_langs_subs]&.include?(language)
|
371
|
+
b = @defaults[:codecs_subs_preferred]&.include?(codec_name)
|
372
|
+
c = language.downcase == 'und'
|
373
|
+
d = title != nil && ! @defaults[:ignore_titles]
|
374
|
+
|
375
|
+
if (!a && !c) || (!b)
|
376
|
+
@actions |= [:drop]
|
377
|
+
else
|
378
|
+
@actions |= [:copy]
|
379
|
+
end
|
380
|
+
|
381
|
+
if (b && c) && (@defaults[:fix_undefined_language])
|
382
|
+
@actions |= [:set_language]
|
383
|
+
end
|
384
|
+
|
385
|
+
if (!a || !b || c || (d))
|
386
|
+
@actions |= [:interesting]
|
387
|
+
end
|
388
|
+
|
389
|
+
#––––––––––––––––––––––––––––––––––––––––––––––––––
|
390
|
+
# video stream handler
|
391
|
+
#––––––––––––––––––––––––––––––––––––––––––––––––––
|
392
|
+
elsif codec_type == 'video'
|
393
|
+
|
394
|
+
a = codec_name.downcase == 'mjpeg'
|
395
|
+
b = @defaults[:codecs_video_preferred]&.include?(codec_name)
|
396
|
+
c = @defaults[:keep_langs_video]&.include?(language)
|
397
|
+
d = language.downcase == 'und'
|
398
|
+
e = title != nil && ! @defaults[:ignore_titles]
|
399
|
+
f = @defaults[:scan_type] == 'quality' && low_quality?
|
400
|
+
|
401
|
+
if (a)
|
402
|
+
@actions |= [:drop]
|
403
|
+
end
|
404
|
+
|
405
|
+
if (!a && b)
|
406
|
+
@actions |= [:copy]
|
407
|
+
end
|
408
|
+
|
409
|
+
if (!a && !b)
|
410
|
+
@actions |= [:transcode]
|
411
|
+
end
|
412
|
+
|
413
|
+
if (!a && d) && (@defaults[:fix_undefined_language])
|
414
|
+
@actions |= [:set_language]
|
415
|
+
end
|
416
|
+
|
417
|
+
if (a || !b || !c || d || e || f)
|
418
|
+
@actions |= [:interesting]
|
419
|
+
end
|
420
|
+
|
421
|
+
#––––––––––––––––––––––––––––––––––––––––––––––––––
|
422
|
+
# audio stream handler
|
423
|
+
#––––––––––––––––––––––––––––––––––––––––––––––––––
|
424
|
+
elsif codec_type == 'audio'
|
425
|
+
|
426
|
+
a = @defaults[:codecs_audio_preferred]&.include?(codec_name)
|
427
|
+
b = @defaults[:keep_langs_audio]&.include?(language)
|
428
|
+
c = language.downcase == 'und'
|
429
|
+
d = title != nil && ! @defaults[:ignore_titles]
|
430
|
+
e = @defaults[:scan_type] == 'quality' && low_quality?
|
431
|
+
|
432
|
+
if (!b && !c)
|
433
|
+
@actions |= one_of_a_kind? ? [:set_language] : [:drop]
|
434
|
+
end
|
435
|
+
|
436
|
+
if (a && b) || (a && !b && c)
|
437
|
+
@actions |= [:copy]
|
438
|
+
end
|
439
|
+
|
440
|
+
if (!a && !b && c) || (!a && b)
|
441
|
+
@actions |= [:transcode]
|
442
|
+
end
|
443
|
+
|
444
|
+
if (c) && (@defaults[:fix_undefined_language])
|
445
|
+
@actions |= [:set_language]
|
446
|
+
end
|
447
|
+
|
448
|
+
if (!a || !b || c || d || e)
|
449
|
+
@actions |= [:interesting]
|
450
|
+
end
|
451
|
+
|
452
|
+
#––––––––––––––––––––––––––––––––––––––––––––––––––
|
453
|
+
# other stream handler
|
454
|
+
#––––––––––––––––––––––––––––––––––––––––––––––––––
|
455
|
+
else
|
456
|
+
@actions |= [:drop]
|
457
|
+
end
|
458
|
+
end # if @actions.nil?
|
459
|
+
|
460
|
+
@actions
|
461
|
+
end # actions
|
462
|
+
|
463
|
+
#------------------------------------------------------------
|
464
|
+
# Given a codec, return the ffmpeg encoder string.
|
465
|
+
#------------------------------------------------------------
|
466
|
+
def encoder_string(for_codec:)
|
467
|
+
case for_codec.downcase
|
468
|
+
when 'hevc'
|
469
|
+
"libx265 -crf 28 -preset slow"
|
470
|
+
when 'h264'
|
471
|
+
"libx264 -crf 23 -preset slow"
|
472
|
+
when 'aac'
|
473
|
+
"libfdk_aac"
|
474
|
+
else
|
475
|
+
raise Exception.new "Error: somehow an unsupported codec '#{for_codec}' was specified."
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
#------------------------------------------------------------
|
480
|
+
# If the source file is an srt, and there's a language, and
|
481
|
+
# it's in the approved language list, then return it;
|
482
|
+
# otherwise return nil.
|
483
|
+
#------------------------------------------------------------
|
484
|
+
def subtitle_file_language
|
485
|
+
langs = @defaults[:keep_langs_subs]&.join('|')
|
486
|
+
lang = @source_file.match(/^.*\.(#{langs})\.srt$/)
|
487
|
+
lang ? lang[1] : nil
|
488
|
+
end
|
489
|
+
|
490
|
+
end # class
|
491
|
+
|
492
|
+
end # module
|