titlekit 1.2.1 → 1.2.2
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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +1 -1
- data/Rakefile +4 -4
- data/bin/titlekit +1 -1
- data/lib/titlekit/have.rb +5 -5
- data/lib/titlekit/job.rb +63 -59
- data/lib/titlekit/parsers/ass.rb +29 -27
- data/lib/titlekit/parsers/ass.treetop +8 -3
- data/lib/titlekit/parsers/srt.rb +15 -15
- data/lib/titlekit/parsers/ssa.rb +31 -29
- data/lib/titlekit/specification.rb +28 -27
- data/lib/titlekit/utilities.rb +2 -2
- data/lib/titlekit/version.rb +2 -2
- data/lib/titlekit/want.rb +1 -1
- data/lib/titlekit.rb +1 -1
- data/spec/ass_spec.rb +30 -7
- data/spec/automatic_grouping/automatic_grouping_spec.rb +8 -8
- data/spec/encoding_detection/encoding_detection_spec.rb +9 -9
- data/spec/files/ass/bom.ass +17 -0
- data/spec/format_conversion/format_conversion_spec.rb +14 -15
- data/spec/job_spec.rb +9 -10
- data/spec/simultaneous_subtitles/simultaneous_subtitles_spec.rb +19 -19
- data/spec/spec_helper.rb +1 -1
- data/spec/specifications_spec.rb +3 -3
- data/spec/srt_spec.rb +6 -6
- data/spec/ssa_spec.rb +6 -6
- data/spec/timecode_correction/timecode_correction_spec.rb +4 -4
- data/spec/transcoding/transcoding_spec.rb +10 -10
- data/titlekit.gemspec +3 -3
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7b9b35e1b03b4b9643a8c75982aec3d425fb5b84
|
4
|
+
data.tar.gz: 40794f1843dd4cfbc18895dd5bffbd0a8bde6546
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 325f6862335038d5a8ecc03454ec35559b28aa113cdbef9b2183d5d84723e4b83cb6d15abcbee9cfa4541f1e35ab545b3a0a64fb4ef3640dee764d006ea53480
|
7
|
+
data.tar.gz: d300e60449e00888d1799d2e1e3c127bb4975f32c9f502869d609e1b62f5b9e98935800bcbdbfef1f6e9debb3a32edfc047457a627c9070d5a0f0ec3298f9c89
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Rakefile
CHANGED
data/bin/titlekit
CHANGED
data/lib/titlekit/have.rb
CHANGED
@@ -14,7 +14,7 @@ module Titlekit
|
|
14
14
|
# :rchardet19 or :charlock_holmes if you have installed an additional
|
15
15
|
# detection library and want to specifically use one or the other.
|
16
16
|
#
|
17
|
-
# @return If you omit the argument
|
17
|
+
# @return If you omit the argument it returns the already specified encoding
|
18
18
|
def encoding(*args)
|
19
19
|
if args.empty?
|
20
20
|
return @encoding
|
@@ -37,7 +37,7 @@ module Titlekit
|
|
37
37
|
#
|
38
38
|
# @example Referencing a subtitle index (ZERO-INDEXED! First subtitle is 0)
|
39
39
|
# have.reference('Earl grey, hot', subtitle: 645)
|
40
|
-
#
|
40
|
+
#
|
41
41
|
# @example Referencing a timecode by seconds
|
42
42
|
# have.reference('In a galaxy ...', seconds: 14.2)
|
43
43
|
#
|
@@ -60,7 +60,7 @@ module Titlekit
|
|
60
60
|
# @param seconds [Float]
|
61
61
|
# @param milliseconds [Float]
|
62
62
|
def reference(name,
|
63
|
-
*
|
63
|
+
*_args,
|
64
64
|
subtitle: nil,
|
65
65
|
hours: nil,
|
66
66
|
minutes: nil,
|
@@ -83,7 +83,7 @@ module Titlekit
|
|
83
83
|
ass_timecode: ass_timecode)
|
84
84
|
end
|
85
85
|
|
86
|
-
|
86
|
+
self
|
87
87
|
end
|
88
88
|
end
|
89
|
-
end
|
89
|
+
end
|
data/lib/titlekit/job.rb
CHANGED
@@ -18,7 +18,7 @@ module Titlekit
|
|
18
18
|
# and any other unusual events that occur on the job. (regardless if it
|
19
19
|
# failed or succeeded)
|
20
20
|
#
|
21
|
-
# @return [Array<String>] All reported messages
|
21
|
+
# @return [Array<String>] All reported messages
|
22
22
|
attr_reader :report
|
23
23
|
|
24
24
|
# Starts a new job.
|
@@ -39,7 +39,7 @@ module Titlekit
|
|
39
39
|
require 'charlock_holmes'
|
40
40
|
end
|
41
41
|
rescue Gem::LoadError
|
42
|
-
end
|
42
|
+
end
|
43
43
|
end
|
44
44
|
|
45
45
|
# Runs the job.
|
@@ -74,14 +74,14 @@ module Titlekit
|
|
74
74
|
# file('path/to/my/input.srt')
|
75
75
|
# fps(25)
|
76
76
|
# end
|
77
|
-
#
|
77
|
+
#
|
78
78
|
# @example Using a block and providing a variable
|
79
79
|
# job.have do |have|
|
80
80
|
# have.encoding('utf-8')
|
81
81
|
# have.file('path/to/my/input.srt')
|
82
82
|
# have.fps(25)
|
83
83
|
# end
|
84
|
-
#
|
84
|
+
#
|
85
85
|
# @example Catching the reference and assigning things at any later point
|
86
86
|
# have = job.have
|
87
87
|
# have.encoding('utf-8')
|
@@ -93,10 +93,10 @@ module Titlekit
|
|
93
93
|
# have2.encoding('ISO-8859-1')
|
94
94
|
# have2.file('path/to/my/input2.srt')
|
95
95
|
#
|
96
|
-
# @param template [Have] optionally you can specify another {Have} as a
|
96
|
+
# @param template [Have] optionally you can specify another {Have} as a
|
97
97
|
# template, from which all properties but the file path are cloned
|
98
98
|
# @return [Have] a reference to the newly assigned {Have}
|
99
|
-
def have(*
|
99
|
+
def have(*_args, template: nil, &block)
|
100
100
|
specification = Have.new
|
101
101
|
|
102
102
|
if template
|
@@ -114,7 +114,7 @@ module Titlekit
|
|
114
114
|
|
115
115
|
@haves << specification
|
116
116
|
|
117
|
-
|
117
|
+
specification
|
118
118
|
end
|
119
119
|
|
120
120
|
# Adds a new {Want} specification to your job.
|
@@ -125,14 +125,14 @@ module Titlekit
|
|
125
125
|
# file('path/to/my/output.srt')
|
126
126
|
# fps(23.976)
|
127
127
|
# end
|
128
|
-
#
|
128
|
+
#
|
129
129
|
# @example Using a block and providing a variable
|
130
130
|
# job.want do |want|
|
131
131
|
# want.encoding('utf-8')
|
132
132
|
# want.file('path/to/my/output.srt')
|
133
133
|
# want.fps((23.976)
|
134
134
|
# end
|
135
|
-
#
|
135
|
+
#
|
136
136
|
# @example Catching the reference and assigning things at any later point
|
137
137
|
# want = job.want
|
138
138
|
# want.encoding('utf-8')
|
@@ -144,7 +144,7 @@ module Titlekit
|
|
144
144
|
# want2.encoding('ISO-8859-1')
|
145
145
|
# want2.file('path/to/my/output.ass')
|
146
146
|
#
|
147
|
-
# @param template [Want] optionally you can specify another {Want} as a
|
147
|
+
# @param template [Want] optionally you can specify another {Want} as a
|
148
148
|
# template, from which all properties but the file path are cloned
|
149
149
|
# @return [Want] a reference to the newly assigned {Want}
|
150
150
|
def want(*args, template: nil, &block)
|
@@ -165,7 +165,7 @@ module Titlekit
|
|
165
165
|
|
166
166
|
@wants << specification
|
167
167
|
|
168
|
-
|
168
|
+
specification
|
169
169
|
end
|
170
170
|
|
171
171
|
private
|
@@ -188,7 +188,7 @@ module Titlekit
|
|
188
188
|
data.force_encoding(detection[:encoding])
|
189
189
|
elsif [:detect, :rchardet19].include?(have.encoding) && defined?(CharDet)
|
190
190
|
detection = CharDet.detect(data)
|
191
|
-
@report << "Assuming #{detection.encoding} for #{have.file} (detected by rchardet19 with #{(detection.confidence*100).to_i}% confidence)"
|
191
|
+
@report << "Assuming #{detection.encoding} for #{have.file} (detected by rchardet19 with #{(detection.confidence * 100).to_i}% confidence)"
|
192
192
|
data.force_encoding(detection.encoding)
|
193
193
|
else
|
194
194
|
@report << "Assuming #{have.encoding} for #{have.file} (user-supplied)"
|
@@ -207,18 +207,19 @@ module Titlekit
|
|
207
207
|
end
|
208
208
|
|
209
209
|
begin
|
210
|
-
have.subtitles =
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
210
|
+
have.subtitles =
|
211
|
+
case File.extname(have.file)
|
212
|
+
when '.ass'
|
213
|
+
ASS.import(data)
|
214
|
+
when '.ssa'
|
215
|
+
SSA.import(data)
|
216
|
+
when '.srt'
|
217
|
+
SRT.import(data)
|
218
|
+
when '.yt'
|
219
|
+
YT.import(data)
|
220
|
+
else
|
221
|
+
fail 'Not supported'
|
222
|
+
end
|
222
223
|
rescue
|
223
224
|
@report << "Failure while importing #{File.extname(have.file)[1..3].upcase} from #{have.file}"
|
224
225
|
raise AbortJob
|
@@ -240,13 +241,13 @@ module Titlekit
|
|
240
241
|
end
|
241
242
|
|
242
243
|
case matching_references.length
|
243
|
-
when 3..(
|
244
|
+
when 3..(_infinity = 1.0 / 0)
|
244
245
|
# "synchronization jitter" correction by interpolating ? Consider !
|
245
246
|
when 2
|
246
247
|
retime_by_double_reference(have,
|
247
|
-
|
248
|
-
|
249
|
-
|
248
|
+
want,
|
249
|
+
matching_references[0],
|
250
|
+
matching_references[1])
|
250
251
|
when 1
|
251
252
|
if have.fps && want.fps
|
252
253
|
retime_by_framerate_plus_reference(have, want, matching_references[0])
|
@@ -254,15 +255,13 @@ module Titlekit
|
|
254
255
|
retime_by_single_reference(have, want, matching_references[0])
|
255
256
|
end
|
256
257
|
when 0
|
257
|
-
if have.fps && want.fps
|
258
|
-
retime_by_framerate(have, want)
|
259
|
-
end
|
258
|
+
retime_by_framerate(have, want) if have.fps && want.fps
|
260
259
|
end
|
261
260
|
end
|
262
261
|
|
263
262
|
# Cleans out subtitles that fell out of the usable time range
|
264
263
|
#
|
265
|
-
# @params have [Have] What we {Have}
|
264
|
+
# @params have [Have] What we {Have}
|
266
265
|
def cull(have)
|
267
266
|
have.subtitles.reject! { |subtitle| subtitle[:end] < 0 }
|
268
267
|
have.subtitles.each do |subtitle|
|
@@ -273,7 +272,7 @@ module Titlekit
|
|
273
272
|
# Assigns track identification fields for distinguishing
|
274
273
|
# between continuous/simultaneous subtitles
|
275
274
|
#
|
276
|
-
# @params have [Have] What we {Have}
|
275
|
+
# @params have [Have] What we {Have}
|
277
276
|
def group(have)
|
278
277
|
if have.track
|
279
278
|
# Assign a custom track identifier if one was supplied
|
@@ -332,9 +331,9 @@ module Titlekit
|
|
332
331
|
# Glue subtitles ends
|
333
332
|
want.subtitles.sort_by! { |subtitle| subtitle[:end] }
|
334
333
|
want.subtitles.each_cons(2) do |pair|
|
335
|
-
if pair[1][:end]-pair[0][:end] < want.glue_treshold
|
336
|
-
pair[0][:end] += (pair[1][:end]-pair[0][:end]) / 2
|
337
|
-
pair[1][:end] -= (pair[1][:end]-pair[0][:end]) / 2
|
334
|
+
if pair[1][:end] - pair[0][:end] < want.glue_treshold
|
335
|
+
pair[0][:end] += (pair[1][:end] - pair[0][:end]) / 2
|
336
|
+
pair[1][:end] -= (pair[1][:end] - pair[0][:end]) / 2
|
338
337
|
end
|
339
338
|
end
|
340
339
|
end
|
@@ -344,22 +343,23 @@ module Titlekit
|
|
344
343
|
# @param want [Want] What we {Want}
|
345
344
|
def export(want)
|
346
345
|
begin
|
347
|
-
data =
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
346
|
+
data =
|
347
|
+
case File.extname(want.file)
|
348
|
+
when '.ass'
|
349
|
+
ASS.master(want.subtitles)
|
350
|
+
ASS.export(want.subtitles)
|
351
|
+
when '.ssa'
|
352
|
+
SSA.master(want.subtitles)
|
353
|
+
SSA.export(want.subtitles)
|
354
|
+
when '.srt'
|
355
|
+
SRT.master(want.subtitles)
|
356
|
+
SRT.export(want.subtitles)
|
357
|
+
when '.yt'
|
358
|
+
YT.master(want.subtitles)
|
359
|
+
YT.export(want.subtitles)
|
360
|
+
else
|
361
|
+
fail 'Not supported'
|
362
|
+
end
|
363
363
|
rescue
|
364
364
|
@report << "Failure while exporting #{File.extname(want.file)[1..3].upcase} for #{want.file}"
|
365
365
|
raise AbortJob
|
@@ -389,7 +389,7 @@ module Titlekit
|
|
389
389
|
#
|
390
390
|
# @param have [Have] the subtitles we {Have}
|
391
391
|
# @param want [Want] the subtitles we {Want}
|
392
|
-
# @param reference [Symbol, String] the key of the reference
|
392
|
+
# @param reference [Symbol, String] the key of the reference
|
393
393
|
def retime_by_single_reference(have, want, reference)
|
394
394
|
amount = want.references[reference][:timecode] -
|
395
395
|
have.references[reference][:timecode]
|
@@ -420,7 +420,7 @@ module Titlekit
|
|
420
420
|
have.subtitles.each do |subtitle|
|
421
421
|
subtitle[:start] += amount
|
422
422
|
subtitle[:end] += amount
|
423
|
-
end
|
423
|
+
end
|
424
424
|
end
|
425
425
|
|
426
426
|
# Applies a progressive timeshift on the subtitles we {Have}
|
@@ -435,11 +435,15 @@ module Titlekit
|
|
435
435
|
# @param [Array<Float>] targets the two amounts of time by which to shift
|
436
436
|
# either of the two points that shall be shifted
|
437
437
|
def retime_by_double_reference(have, want, reference_a, reference_b)
|
438
|
-
origins = [
|
439
|
-
|
438
|
+
origins = [
|
439
|
+
have.references[reference_a][:timecode],
|
440
|
+
have.references[reference_b][:timecode]
|
441
|
+
]
|
440
442
|
|
441
|
-
targets = [
|
442
|
-
|
443
|
+
targets = [
|
444
|
+
want.references[reference_a][:timecode],
|
445
|
+
want.references[reference_b][:timecode]
|
446
|
+
]
|
443
447
|
|
444
448
|
rescale_factor = (targets[1] - targets[0]) / (origins[1] - origins[0])
|
445
449
|
rebase_shift = targets[0] - origins[0] * rescale_factor
|
@@ -462,4 +466,4 @@ module Titlekit
|
|
462
466
|
end
|
463
467
|
end
|
464
468
|
end
|
465
|
-
end
|
469
|
+
end
|
data/lib/titlekit/parsers/ass.rb
CHANGED
@@ -31,7 +31,7 @@ module Titlekit
|
|
31
31
|
subtitle = {}
|
32
32
|
|
33
33
|
fields = line.text_value.split(',')
|
34
|
-
|
34
|
+
|
35
35
|
subtitle[:id] = elements.index(line) + 1
|
36
36
|
subtitle[:start] = SSA.parse_timecode(fields[1])
|
37
37
|
subtitle[:end] = SSA.parse_timecode(fields[2])
|
@@ -59,8 +59,8 @@ module Titlekit
|
|
59
59
|
failure += "failure_column #{parser.failure_column}\n"
|
60
60
|
failure += "failure_reason #{parser.failure_reason}\n"
|
61
61
|
|
62
|
-
|
63
|
-
end
|
62
|
+
fail failure
|
63
|
+
end
|
64
64
|
end
|
65
65
|
|
66
66
|
# Master the subtitles for best possible usage of the format's features.
|
@@ -70,8 +70,8 @@ module Titlekit
|
|
70
70
|
tracks = subtitles.map { |subtitle| subtitle[:track] }.uniq
|
71
71
|
|
72
72
|
if tracks.length == 1
|
73
|
-
|
74
|
-
# maybe styling? aside that:
|
73
|
+
|
74
|
+
# maybe styling? aside that: nothing more!
|
75
75
|
|
76
76
|
elsif tracks.length == 2 || tracks.length == 3
|
77
77
|
|
@@ -99,21 +99,23 @@ module Titlekit
|
|
99
99
|
|
100
100
|
frames.each do |frame|
|
101
101
|
intersecting = subtitles.select do |subtitle|
|
102
|
-
|
103
|
-
|
102
|
+
subtitle[:end] == frame[:end] ||
|
103
|
+
subtitle[:start] == frame[:start] ||
|
104
|
+
(subtitle[:start] < frame[:start] && subtitle[:end] > frame[:end])
|
104
105
|
end
|
105
106
|
|
106
107
|
if intersecting.any?
|
107
108
|
intersecting.sort_by! { |subtitle| tracks.index(subtitle[:track]) }
|
108
109
|
intersecting.each do |subtitle|
|
109
|
-
|
110
|
-
new_subtitle[:id] = mastered_subtitles.length+1
|
111
|
-
new_subtitle[:start] = frame[:start]
|
112
|
-
new_subtitle[:end] = frame[:end]
|
110
|
+
color = tracks.index(subtitle[:track]) % DEFAULT_PALETTE.length
|
113
111
|
|
114
|
-
|
115
|
-
|
116
|
-
|
112
|
+
new_subtitle = {
|
113
|
+
id: mastered_subtitles.length + 1,
|
114
|
+
start: frame[:start],
|
115
|
+
end: frame[:end],
|
116
|
+
style: DEFAULT_PALETTE[color],
|
117
|
+
lines: subtitle[:lines]
|
118
|
+
}
|
117
119
|
|
118
120
|
mastered_subtitles << new_subtitle
|
119
121
|
end
|
@@ -143,9 +145,9 @@ module Titlekit
|
|
143
145
|
end
|
144
146
|
|
145
147
|
result << "\n" # Close styles section
|
146
|
-
|
148
|
+
|
147
149
|
result << "[Events]\nFormat: Layer, Start, End, Style, Actor, MarginL, MarginR, MarginV, Effect, Text\n"
|
148
|
-
|
150
|
+
|
149
151
|
subtitles.each do |subtitle|
|
150
152
|
fields = [
|
151
153
|
'Dialogue: 0', # Format: Marked
|
@@ -156,14 +158,14 @@ module Titlekit
|
|
156
158
|
'0000', # MarginL
|
157
159
|
'0000', # MarginR
|
158
160
|
'0000', # MarginV
|
159
|
-
''
|
161
|
+
'', # Effect
|
160
162
|
subtitle[:lines].gsub("\n", '\N') # Text
|
161
163
|
]
|
162
164
|
|
163
165
|
result << fields.join(',') + "\n"
|
164
166
|
end
|
165
167
|
|
166
|
-
|
168
|
+
result
|
167
169
|
end
|
168
170
|
|
169
171
|
protected
|
@@ -173,11 +175,11 @@ module Titlekit
|
|
173
175
|
# @param seconds [Float] an amount of seconds
|
174
176
|
# @return [String] An ASS-formatted timecode ('h:mm:ss.ms')
|
175
177
|
def self.build_timecode(seconds)
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
178
|
+
format('%01d:%02d:%02d.%s',
|
179
|
+
seconds / 3600,
|
180
|
+
(seconds % 3600) / 60,
|
181
|
+
seconds % 60,
|
182
|
+
format('%.2f', seconds)[-2, 3])
|
181
183
|
end
|
182
184
|
|
183
185
|
# Parses an ASS-formatted timecode into a float representing seconds
|
@@ -185,8 +187,8 @@ module Titlekit
|
|
185
187
|
# @param timecode [String] An ASS-formatted timecode ('h:mm:ss.ms')
|
186
188
|
# @param [Float] an amount of seconds
|
187
189
|
def self.parse_timecode(timecode)
|
188
|
-
|
189
|
-
|
190
|
-
end
|
190
|
+
m = timecode.match(/(?<h>\d):(?<m>\d{2}):(?<s>\d{2})[:|\.](?<ms>\d+)/)
|
191
|
+
m['h'].to_i * 3600 + m['m'].to_i * 60 + m['s'].to_i + "0.#{m['ms']}".to_f
|
192
|
+
end
|
191
193
|
end
|
192
|
-
end
|
194
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
grammar ASS
|
2
2
|
rule subtitles
|
3
|
+
utf8_bom?
|
3
4
|
info?
|
4
5
|
styles?
|
5
6
|
event_section
|
@@ -10,6 +11,10 @@ grammar ASS
|
|
10
11
|
<Titlekit::ASS::Subtitles>
|
11
12
|
end
|
12
13
|
|
14
|
+
rule utf8_bom
|
15
|
+
"\xEF\xBB\xBF"
|
16
|
+
end
|
17
|
+
|
13
18
|
rule info
|
14
19
|
'[Script Info]' end_of_line lines* end_of_section <Titlekit::ASS::ScriptInfo>
|
15
20
|
end
|
@@ -49,7 +54,7 @@ grammar ASS
|
|
49
54
|
rule end_of_section
|
50
55
|
end_of_line+ / end_of_file
|
51
56
|
end
|
52
|
-
|
57
|
+
|
53
58
|
rule end_of_line
|
54
59
|
"\r\n" / "\n" / "\r"
|
55
60
|
end
|
@@ -61,7 +66,7 @@ grammar ASS
|
|
61
66
|
rule end_of_file
|
62
67
|
!.
|
63
68
|
end
|
64
|
-
|
69
|
+
|
65
70
|
rule number
|
66
71
|
[0-9]+
|
67
72
|
end
|
@@ -69,4 +74,4 @@ grammar ASS
|
|
69
74
|
rule string
|
70
75
|
(!end_of_line .)+
|
71
76
|
end
|
72
|
-
end
|
77
|
+
end
|
data/lib/titlekit/parsers/srt.rb
CHANGED
@@ -6,7 +6,7 @@ module Titlekit
|
|
6
6
|
# Internal intermediate class used for parsing with treetop
|
7
7
|
class Subtitles < Treetop::Runtime::SyntaxNode
|
8
8
|
def build
|
9
|
-
elements.map
|
9
|
+
elements.map(&:build)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -51,8 +51,8 @@ module Titlekit
|
|
51
51
|
failure += "failure_column #{parser.failure_column}\n"
|
52
52
|
failure += "failure_reason #{parser.failure_reason}\n"
|
53
53
|
|
54
|
-
|
55
|
-
end
|
54
|
+
fail failure
|
55
|
+
end
|
56
56
|
end
|
57
57
|
|
58
58
|
# Master the subtitles for best possible usage of the format's features.
|
@@ -62,8 +62,8 @@ module Titlekit
|
|
62
62
|
tracks = subtitles.map { |subtitle| subtitle[:track] }.uniq
|
63
63
|
|
64
64
|
if tracks.length == 1
|
65
|
-
|
66
|
-
# maybe styling? aside that:
|
65
|
+
|
66
|
+
# maybe styling? aside that: nothing more!
|
67
67
|
|
68
68
|
elsif tracks.length >= 2
|
69
69
|
|
@@ -86,7 +86,7 @@ module Titlekit
|
|
86
86
|
intersecting.sort_by! { |subtitle| tracks.index(subtitle[:track]) }
|
87
87
|
|
88
88
|
subtitle = {}
|
89
|
-
subtitle[:id] = mastered_subtitles.length+1
|
89
|
+
subtitle[:id] = mastered_subtitles.length + 1
|
90
90
|
subtitle[:start] = frame[:start]
|
91
91
|
subtitle[:end] = frame[:end]
|
92
92
|
|
@@ -116,7 +116,7 @@ module Titlekit
|
|
116
116
|
result = ''
|
117
117
|
|
118
118
|
subtitles.each_with_index do |subtitle, index|
|
119
|
-
result << (index+1).to_s
|
119
|
+
result << (index + 1).to_s
|
120
120
|
result << "\n"
|
121
121
|
result << SRT.build_timecode(subtitle[:start])
|
122
122
|
result << ' --> '
|
@@ -126,7 +126,7 @@ module Titlekit
|
|
126
126
|
result << "\n\n"
|
127
127
|
end
|
128
128
|
|
129
|
-
|
129
|
+
result
|
130
130
|
end
|
131
131
|
|
132
132
|
protected
|
@@ -136,11 +136,11 @@ module Titlekit
|
|
136
136
|
# @param seconds [Float] an amount of seconds
|
137
137
|
# @return [String] An SRT-formatted timecode ('hh:mm:ss,ms')
|
138
138
|
def self.build_timecode(seconds)
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
139
|
+
format('%02d:%02d:%02d,%s',
|
140
|
+
seconds / 3600,
|
141
|
+
(seconds % 3600) / 60,
|
142
|
+
seconds % 60,
|
143
|
+
format('%.3f', seconds)[-3, 3])
|
144
144
|
end
|
145
145
|
|
146
146
|
# Parses an SRT-formatted timecode into a float representing seconds
|
@@ -149,7 +149,7 @@ module Titlekit
|
|
149
149
|
# @param [Float] an amount of seconds
|
150
150
|
def self.parse_timecode(timecode)
|
151
151
|
mres = timecode.match(/(?<h>\d+):(?<m>\d+):(?<s>\d+),(?<ms>\d+)/)
|
152
|
-
"#{mres[
|
152
|
+
"#{mres['h'].to_i * 3600 + mres['m'].to_i * 60 + mres['s'].to_i}.#{mres['ms']}".to_f
|
153
153
|
end
|
154
154
|
end
|
155
|
-
end
|
155
|
+
end
|