titlekit 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1b36a1f0921cdaa8ccdc52e9947507e17fa15000
4
- data.tar.gz: c9925463a03d50b1486625d83e5df62ee4ab010a
3
+ metadata.gz: 650af440419b3a43cd9b6d57a2f83c7ccc61277e
4
+ data.tar.gz: c1a6eee753972bc12345d5f3fa7beeebfab6ed9d
5
5
  SHA512:
6
- metadata.gz: d4eb3bf019168c863b72ed5c3eb05567ec5233fcfe71ca570f561fd08ad0da569f1bac69317f2c227c373144a05468e2efca751db90846e729fd47deb9741e03
7
- data.tar.gz: 166c7fccd1d8085dba1cdf4c6eb49685d2ce20bdbb606fd58082dcd4e0e59c8dbd91f88474bd111ab58d431af0e062c0a11cfa128ce085c6def53ead5651b505
6
+ metadata.gz: b85b8b7783b76a0e9a295790049194dbe47ff7c765d5376c9d27142bac96fe1c4697cf130d0df4a56339538c55f78f12c73febfbff5737bde45ea8469852b7e0
7
+ data.tar.gz: 983e8444dbfced2363ad125ea9d8e720609ffae3804b3657d4799ad660e7871882b856de641c3bb8503821dbd829de810f169c3219b133208cb060d3a75867cb
data/README.md CHANGED
@@ -43,6 +43,14 @@ unknown encoding)
43
43
  end
44
44
  ```
45
45
 
46
+ ### Template
47
+
48
+ To get you started quickly with an edit script for subtitles, you can use a console command provided by Titlekit:
49
+
50
+ $ titlekit template [optional_title]
51
+
52
+ This will generate either `template_job.rb` or `[optional_title].rb` if you have provided an optional title (Inside the directory you are in). The template script contains a basically complete Titlekit script, you just need to fill in your filenames, encodings, references, etc. as needed. There are also some comments included so you know where to start off!
53
+
46
54
  ### All features by example
47
55
 
48
56
  In all following examples I will omit `(1)` and `(4)` from the basic example, because they stay the same.
@@ -0,0 +1,43 @@
1
+ require 'titlekit'
2
+
3
+ job = Titlekit::Job.new
4
+
5
+ job.have do
6
+
7
+ # Specify the file you already have; Also works with .ssa and .ass
8
+ file('original.srt')
9
+
10
+ # Change this to your encoding, uncomment if you don't know
11
+ encoding('utf-8')
12
+
13
+ # Uncomment and edit to set a reference in the existing subtitles
14
+ # reference(:first, srt_timecode: '00:00:00,000')
15
+
16
+ # Uncomment and edit to set another reference in the existing subtitles
17
+ # reference(:second, srt_timecode: '00:00:00,000')
18
+
19
+ end
20
+
21
+ job.want do
22
+
23
+ # Specify the file to be created; Also works with .ssa and .ass
24
+ file('target.srt')
25
+
26
+ # Change this to your desired target encoding
27
+ encoding('utf-8')
28
+
29
+ # Uncomment and edit to set a new target timecode for the first reference
30
+ # reference(:first, srt_timecode: '00:00:00,000')
31
+
32
+ # Uncomment and edit to also set the second target timecode
33
+ # reference(:second, srt_timecode: '00:00:00,000')
34
+
35
+ end
36
+
37
+ if job.run
38
+ puts 'Job completed without errors!'
39
+ else
40
+ puts 'There were errors:'
41
+ puts job.report.join("\n")
42
+ end
43
+
data/bin/titlekit ADDED
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if ARGV.length > 0 && ARGV[0] == 'template'
4
+
5
+ filename = ARGV.length > 1 ? ARGV[1] + '.rb' : 'template_job.rb'
6
+
7
+ content = <<HERETEMPLATE
8
+ require 'titlekit'
9
+
10
+ job = Titlekit::Job.new
11
+
12
+ job.have do
13
+
14
+ # Specify the file you already have; Also works with .ssa and .ass
15
+ file('original.srt')
16
+
17
+ # Change this to your encoding, uncomment if you don't know
18
+ encoding('utf-8')
19
+
20
+ # Uncomment and edit to set a reference in the existing subtitles
21
+ # reference(:first, srt_timecode: '00:00:00,000')
22
+
23
+ # Uncomment and edit to set another reference in the existing subtitles
24
+ # reference(:second, srt_timecode: '00:00:00,000')
25
+
26
+ end
27
+
28
+ job.want do
29
+
30
+ # Specify the file to be created; Also works with .ssa and .ass
31
+ file('target.srt')
32
+
33
+ # Change this to your desired target encoding
34
+ encoding('utf-8')
35
+
36
+ # Uncomment and edit to set a new target timecode for the first reference
37
+ # reference(:first, srt_timecode: '00:00:00,000')
38
+
39
+ # Uncomment and edit to also set the second target timecode
40
+ # reference(:second, srt_timecode: '00:00:00,000')
41
+
42
+ end
43
+
44
+ if job.run
45
+ puts 'Job completed without errors!'
46
+ else
47
+ puts 'There were errors:'
48
+ puts job.report.join("\\n")
49
+ end
50
+
51
+ HERETEMPLATE
52
+
53
+ IO.write(filename, content)
54
+
55
+ puts "Created generic job script '#{filename}' in current directory;"
56
+ puts "Edit and then run with 'ruby #{filename}'"
57
+
58
+ else
59
+ puts 'Your either provided an unknown option, or none at all;'
60
+ puts 'Currently only \'template [optional_title]\' is available;'
61
+ puts 'E.g. \'titlekit template myscript\''
62
+ end
data/lib/titlekit/job.rb CHANGED
@@ -4,14 +4,14 @@ module Titlekit
4
4
 
5
5
  class Job
6
6
 
7
- # Returns everything we {Have}
7
+ # Returns everything you {Have}
8
8
  #
9
- # @return [Array<Have>] All assigned {Have} specifications
9
+ # @return [Array<Have>] Everything you {Have}
10
10
  attr_reader :haves
11
11
 
12
- # Returns everything we {Want}
12
+ # Returns everything you {Want}
13
13
  #
14
- # @return [Array<Want>] All assigned {Want} specifications
14
+ # @return [Array<Want>] Everything you {Want}
15
15
  attr_reader :wants
16
16
 
17
17
  # Returns the job report, which documents the direct cause of failures
@@ -23,7 +23,7 @@ module Titlekit
23
23
 
24
24
  # Starts a new job.
25
25
  #
26
- # A job requires at least one thing you {Have} and one thing you {Want}
26
+ # A job requires at least one file you {Have} and one file you {Want}
27
27
  # in order to be runable. Use {Job#have} and {Job#want} to add
28
28
  # and obtain specification interfaces for the job.
29
29
  #
@@ -42,7 +42,7 @@ module Titlekit
42
42
  end
43
43
  end
44
44
 
45
- # Fulfills the job.
45
+ # Runs the job.
46
46
  #
47
47
  # @return [Boolean] true if the job succeeds, false if it fails.
48
48
  # {Job#report} provides information in case of failure.
@@ -214,6 +214,8 @@ module Titlekit
214
214
  SSA.import(data)
215
215
  when '.srt'
216
216
  SRT.import(data)
217
+ when '.yt'
218
+ YT.import(data)
217
219
  else
218
220
  raise 'Not supported'
219
221
  end
@@ -258,7 +260,9 @@ module Titlekit
258
260
  end
259
261
  end
260
262
 
261
- # Clean out subtitles that fell out of the usable time range
263
+ # Cleans out subtitles that fell out of the usable time range
264
+ #
265
+ # @params have [Have] What we {Have}
262
266
  def cull(have)
263
267
  have.subtitles.reject! { |subtitle| subtitle[:end] < 0 }
264
268
  have.subtitles.each do |subtitle|
@@ -266,8 +270,10 @@ module Titlekit
266
270
  end
267
271
  end
268
272
 
269
- # Assign track identification fields for distinguishing
273
+ # Assigns track identification fields for distinguishing
270
274
  # between continuous/simultaneous subtitles
275
+ #
276
+ # @params have [Have] What we {Have}
271
277
  def group(have)
272
278
  if have.track
273
279
  # Assign a custom track identifier if one was supplied
@@ -348,6 +354,9 @@ module Titlekit
348
354
  when '.srt'
349
355
  SRT.master(want.subtitles)
350
356
  SRT.export(want.subtitles)
357
+ when '.yt'
358
+ YT.master(want.subtitles)
359
+ YT.export(want.subtitles)
351
360
  else
352
361
  raise 'Not supported'
353
362
  end
@@ -391,6 +400,12 @@ module Titlekit
391
400
  end
392
401
  end
393
402
 
403
+ # Rescales timecodes based on two differing framerates and then applies a
404
+ # simple timeshift to the subtitles we {Have}.
405
+ #
406
+ # @param have [Have] the subtitles we {Have}
407
+ # @param want [Want] the subtitles we {Want}
408
+ # @param reference [Symbol, String] the key of the reference
394
409
  def retime_by_framerate_plus_reference(have, want, reference)
395
410
  ratio = want.fps.to_f / have.fps.to_f
396
411
  have.references[reference][:timecode] *= ratio
@@ -435,6 +450,10 @@ module Titlekit
435
450
  end
436
451
  end
437
452
 
453
+ # Rescales timecodes based on two differing framerates.
454
+ #
455
+ # @param have [Have] the subtitles we {Have}
456
+ # @param want [Want] the subtitles we {Want}
438
457
  def retime_by_framerate(have, want)
439
458
  ratio = want.fps.to_f / have.fps.to_f
440
459
  have.subtitles.each do |subtitle|
@@ -3,24 +3,28 @@ require 'treetop'
3
3
  module Titlekit
4
4
  module ASS
5
5
 
6
+ # Internal intermediate class used for parsing with treetop
6
7
  class Subtitles < Treetop::Runtime::SyntaxNode
7
8
  def build
8
9
  event_section.events.build
9
10
  end
10
11
  end
11
12
 
13
+ # Internal intermediate class used for parsing with treetop
12
14
  class ScriptInfo < Treetop::Runtime::SyntaxNode
13
15
  def build
14
16
  # elements.map { |subtitle| subtitle.build }
15
17
  end
16
18
  end
17
19
 
20
+ # Internal intermediate class used for parsing with treetop
18
21
  class V4PStyles < Treetop::Runtime::SyntaxNode
19
22
  def build
20
23
  # elements.map { |subtitle| subtitle.build }
21
24
  end
22
25
  end
23
26
 
27
+ # Internal intermediate class used for parsing with treetop
24
28
  class Events < Treetop::Runtime::SyntaxNode
25
29
  def build
26
30
  elements.map do |line|
@@ -38,9 +42,10 @@ module Titlekit
38
42
  end
39
43
  end
40
44
 
41
- # Parses the supplied string and returns the results.
42
- #
45
+ # Parses the supplied string and builds the resulting subtitles array.
43
46
  #
47
+ # @param string [String] proper UTF-8 ASS file content
48
+ # @return [Array<Hash>] the imported subtitles
44
49
  def self.import(string)
45
50
  Treetop.load(File.join(__dir__, 'ass'))
46
51
  parser = ASSParser.new
@@ -119,6 +124,10 @@ module Titlekit
119
124
  end
120
125
  end
121
126
 
127
+ # Exports the supplied subtitles to ASS format
128
+ #
129
+ # @param subtitles [Array<Hash>] The subtitle to export
130
+ # @return [String] Proper UTF-8 ASS as a string
122
131
  def self.export(subtitles)
123
132
  result = ''
124
133
 
@@ -159,6 +168,10 @@ module Titlekit
159
168
 
160
169
  protected
161
170
 
171
+ # Builds an ASS-formatted timecode from a float representing seconds
172
+ #
173
+ # @param seconds [Float] an amount of seconds
174
+ # @return [String] An ASS-formatted timecode ('h:mm:ss.ms')
162
175
  def self.build_timecode(seconds)
163
176
  sprintf("%01d:%02d:%02d.%s",
164
177
  seconds / 3600,
@@ -167,6 +180,10 @@ module Titlekit
167
180
  sprintf("%.2f", seconds)[-2, 3])
168
181
  end
169
182
 
183
+ # Parses an ASS-formatted timecode into a float representing seconds
184
+ #
185
+ # @param timecode [String] An ASS-formatted timecode ('h:mm:ss.ms')
186
+ # @param [Float] an amount of seconds
170
187
  def self.parse_timecode(timecode)
171
188
  mres = timecode.match(/(?<h>\d):(?<m>\d{2}):(?<s>\d{2})[:|\.](?<ms>\d+)/)
172
189
  return "#{mres["h"].to_i * 3600 + mres["m"].to_i * 60 + mres["s"].to_i}.#{mres["ms"]}".to_f
@@ -3,12 +3,14 @@ require 'treetop'
3
3
  module Titlekit
4
4
  module SRT
5
5
 
6
+ # Internal intermediate class used for parsing with treetop
6
7
  class Subtitles < Treetop::Runtime::SyntaxNode
7
8
  def build
8
9
  elements.map { |subtitle| subtitle.build }
9
10
  end
10
11
  end
11
12
 
13
+ # Internal intermediate class used for parsing with treetop
12
14
  class Subtitle < Treetop::Runtime::SyntaxNode
13
15
  def build
14
16
  {
@@ -20,6 +22,7 @@ module Titlekit
20
22
  end
21
23
  end
22
24
 
25
+ # Internal intermediate class used for parsing with treetop
23
26
  class Timecode < Treetop::Runtime::SyntaxNode
24
27
  def build
25
28
  value = 0
@@ -31,9 +34,10 @@ module Titlekit
31
34
  end
32
35
  end
33
36
 
34
- # Parses the supplied string and returns the results.
35
- #
37
+ # Parses the supplied string and builds the resulting subtitles array.
36
38
  #
39
+ # @param string [String] proper UTF-8 SRT file content
40
+ # @return [Array<Hash>] the imported subtitles
37
41
  def self.import(string)
38
42
  Treetop.load(File.join(__dir__, 'srt'))
39
43
  parser = SRTParser.new
@@ -104,6 +108,10 @@ module Titlekit
104
108
  end
105
109
  end
106
110
 
111
+ # Exports the supplied subtitles to SRT format
112
+ #
113
+ # @param subtitles [Array<Hash>] The subtitle to export
114
+ # @return [String] Proper UTF-8 SRT as a string
107
115
  def self.export(subtitles)
108
116
  result = ''
109
117
 
@@ -123,6 +131,10 @@ module Titlekit
123
131
 
124
132
  protected
125
133
 
134
+ # Builds an SRT-formatted timecode from a float representing seconds
135
+ #
136
+ # @param seconds [Float] an amount of seconds
137
+ # @return [String] An SRT-formatted timecode ('hh:mm:ss,ms')
126
138
  def self.build_timecode(seconds)
127
139
  sprintf("%02d:%02d:%02d,%s",
128
140
  seconds / 3600,
@@ -131,6 +143,10 @@ module Titlekit
131
143
  sprintf("%.3f", seconds)[-3, 3])
132
144
  end
133
145
 
146
+ # Parses an SRT-formatted timecode into a float representing seconds
147
+ #
148
+ # @param timecode [String] An SRT-formatted timecode ('hh:mm:ss,ms')
149
+ # @param [Float] an amount of seconds
134
150
  def self.parse_timecode(timecode)
135
151
  mres = timecode.match(/(?<h>\d+):(?<m>\d+):(?<s>\d+),(?<ms>\d+)/)
136
152
  "#{mres["h"].to_i * 3600 + mres["m"].to_i * 60 + mres["s"].to_i}.#{mres["ms"]}".to_f
@@ -3,24 +3,28 @@ require 'treetop'
3
3
  module Titlekit
4
4
  module SSA
5
5
 
6
+ # Internal intermediate class used for parsing with treetop
6
7
  class Subtitles < Treetop::Runtime::SyntaxNode
7
8
  def build
8
9
  event_section.events.build
9
10
  end
10
11
  end
11
12
 
13
+ # Internal intermediate class used for parsing with treetop
12
14
  class ScriptInfo < Treetop::Runtime::SyntaxNode
13
15
  def build
14
16
  # elements.map { |subtitle| subtitle.build }
15
17
  end
16
18
  end
17
19
 
20
+ # Internal intermediate class used for parsing with treetop
18
21
  class V4PStyles < Treetop::Runtime::SyntaxNode
19
22
  def build
20
23
  # elements.map { |subtitle| subtitle.build }
21
24
  end
22
25
  end
23
26
 
27
+ # Internal intermediate class used for parsing with treetop
24
28
  class Events < Treetop::Runtime::SyntaxNode
25
29
  def build
26
30
  elements.map do |line|
@@ -38,31 +42,10 @@ module Titlekit
38
42
  end
39
43
  end
40
44
 
41
- # class Subtitle < Treetop::Runtime::SyntaxNode
42
- # def build
43
- # {
44
- # id: id.text_value.to_i,
45
- # start: from.build,
46
- # end: to.build,
47
- # lines: lines.text_value.rstrip
48
- # }
49
- # end
50
- # end
51
-
52
- # class Timecode < Treetop::Runtime::SyntaxNode
53
- # def build
54
- # value = 0
55
- # value += hours.text_value.to_i * 3600
56
- # value += minutes.text_value.to_i * 60
57
- # value += seconds.text_value.to_i
58
- # value += "0.#{fractions.text_value}".to_f
59
- # value
60
- # end
61
- # end
62
-
63
- # Parses the supplied string and returns the results.
64
- #
45
+ # Parses the supplied string and builds the resulting subtitles array.
65
46
  #
47
+ # @param string [String] proper UTF-8 SSA file content
48
+ # @return [Array<Hash>] the imported subtitles
66
49
  def self.import(string)
67
50
  Treetop.load(File.join(__dir__, 'ssa'))
68
51
  parser = SSAParser.new
@@ -141,6 +124,10 @@ module Titlekit
141
124
  end
142
125
  end
143
126
 
127
+ # Exports the supplied subtitles to SSA format
128
+ #
129
+ # @param subtitles [Array<Hash>] The subtitle to export
130
+ # @return [String] Proper UTF-8 SSA as a string
144
131
  def self.export(subtitles)
145
132
  result = ''
146
133
 
@@ -185,6 +172,10 @@ module Titlekit
185
172
 
186
173
  protected
187
174
 
175
+ # Builds an SSA-formatted timecode from a float representing seconds
176
+ #
177
+ # @param seconds [Float] an amount of seconds
178
+ # @return [String] An SSA-formatted timecode ('h:mm:ss.ms')
188
179
  def self.build_timecode(seconds)
189
180
  sprintf("%01d:%02d:%02d.%s",
190
181
  seconds / 3600,
@@ -193,6 +184,10 @@ module Titlekit
193
184
  sprintf("%.2f", seconds)[-2, 3])
194
185
  end
195
186
 
187
+ # Parses an SSA-formatted timecode into a float representing seconds
188
+ #
189
+ # @param timecode [String] An SSA-formatted timecode ('h:mm:ss.ms')
190
+ # @param [Float] an amount of seconds
196
191
  def self.parse_timecode(timecode)
197
192
  mres = timecode.match(/(?<h>\d):(?<m>\d{2}):(?<s>\d{2})[:|\.](?<ms>\d+)/)
198
193
  return "#{mres["h"].to_i * 3600 + mres["m"].to_i * 60 + mres["s"].to_i}.#{mres["ms"]}".to_f
@@ -1,7 +1,7 @@
1
1
  module Titlekit
2
2
  class Specification
3
3
 
4
- # Only for internal usage by the job control center
4
+ # Only for internal usage by the job
5
5
  attr_accessor :subtitles
6
6
 
7
7
  def initialize
@@ -15,6 +15,8 @@ module Titlekit
15
15
  return self
16
16
  end
17
17
 
18
+ # Specifies the encoding you have or want.
19
+ #
18
20
  # @param [String] A string specifying the encoding, e.g. 'utf-8' or 'ISO-8859-1'
19
21
  # @return If you omit the argument, it returns the already specified encoding
20
22
  def encoding(*args)
@@ -26,6 +28,8 @@ module Titlekit
26
28
  end
27
29
  end
28
30
 
31
+ # Specifies the file (path) you have or want.
32
+ #
29
33
  # @param [String] A string specifying the path to the file
30
34
  # @return If you omit the argument, it returns the already specified path
31
35
  def file(*args)
@@ -37,6 +41,8 @@ module Titlekit
37
41
  end
38
42
  end
39
43
 
44
+ # Specifies the track the subtitles should be assigned to.
45
+ #
40
46
  # @param [String] A string specifying the track identifier
41
47
  # @return If you omit the argument, it returns the already specified track
42
48
  def track(*args)
@@ -48,6 +54,8 @@ module Titlekit
48
54
  end
49
55
  end
50
56
 
57
+ # Specifies the framerate you have or want.
58
+ #
51
59
  # @param [Float] A float specifying the frames per second, e.g. 23.976
52
60
  # @return If you omit the argument, it returns the already specified fps
53
61
  def fps(*args)
@@ -1,3 +1,6 @@
1
1
  module Titlekit
2
+ # The default palette is used to distinguish simultaneous subtitles
3
+ # by their color (if distinguishing them by different position is either
4
+ # not possible due to the format or not sensible in the specific case)
2
5
  DEFAULT_PALETTE = %w{EDF393 F5E665 FFC472 FFA891 89BABE}
3
6
  end
@@ -1,3 +1,4 @@
1
1
  module Titlekit
2
- VERSION = '1.0.0'
2
+ # Versioning follows the semantic versioning scheme: http://semver.org/
3
+ VERSION = '1.1.0'
3
4
  end
data/lib/titlekit/want.rb CHANGED
@@ -3,12 +3,12 @@ module Titlekit
3
3
 
4
4
  def initialize
5
5
  super
6
- @glue_treshold = 0.08
6
+ @glue_treshold = 0.3
7
7
  end
8
8
 
9
- # For dual subtitles the starts and ends of simultaneously occuring
9
+ # For dual+ subtitles the starts and ends of simultaneously occuring
10
10
  # subtitles can be micro-adjusted together if their distance is smaller
11
- # than the glue_treshold. Normally defaults to 0.08 (super-conservative).
11
+ # than the glue_treshold. Normally defaults to 0.3
12
12
  #
13
13
  # @param [Float] Specifies the new glue_treshold
14
14
  # @return If you omit the argument, it returns the set glue_treshold