titlekit 1.2.1 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|