vtt2ass 0.3.2 → 0.3.5
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/.rubocop.yml +19 -0
- data/Gemfile +2 -0
- data/README.md +70 -10
- data/Rakefile +8 -6
- data/bin/vtt2ass +2 -1
- data/exe/vtt2ass +2 -1
- data/lib/vtt2ass/application.rb +78 -0
- data/lib/vtt2ass/ass_file.rb +106 -0
- data/lib/vtt2ass/ass_line.rb +97 -0
- data/lib/vtt2ass/ass_style.rb +51 -0
- data/lib/vtt2ass/ass_style_params.rb +108 -0
- data/lib/vtt2ass/css_file.rb +38 -0
- data/lib/vtt2ass/css_rule.rb +30 -0
- data/lib/vtt2ass/validator.rb +14 -0
- data/lib/vtt2ass/version.rb +3 -1
- data/lib/vtt2ass/vtt_file.rb +58 -0
- data/lib/vtt2ass/vtt_line.rb +44 -0
- data/lib/vtt2ass.rb +52 -22
- data/vtt2ass.gemspec +19 -16
- metadata +32 -30
- data/lib/vtt2ass/ASSFile.rb +0 -110
- data/lib/vtt2ass/ASSLine.rb +0 -94
- data/lib/vtt2ass/ASSStyle.rb +0 -48
- data/lib/vtt2ass/ASSStyleParams.rb +0 -87
- data/lib/vtt2ass/Application.rb +0 -68
- data/lib/vtt2ass/CSSFile.rb +0 -36
- data/lib/vtt2ass/CSSRule.rb +0 -22
- data/lib/vtt2ass/VTTFile.rb +0 -58
- data/lib/vtt2ass/VTTLine.rb +0 -44
- data/lib/vtt2ass/Validator.rb +0 -10
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# This class defines a CSS rule that is included in the CSS file.
|
5
|
+
class CSSRule
|
6
|
+
attr_reader :name, :properties
|
7
|
+
|
8
|
+
def initialize(selector, declarations)
|
9
|
+
@name = reduce_selector(selector)
|
10
|
+
@properties = []
|
11
|
+
declarations.split(/;\s?/).each do |dec|
|
12
|
+
temp = dec.split(/:\s?/)
|
13
|
+
@properties.push(
|
14
|
+
{ key: temp.first, value: temp.last }
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
"#{@name} #{@properties}"
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# This method removes the generic selector from a block.
|
25
|
+
def reduce_selector(selector)
|
26
|
+
selector.to_s.gsub(
|
27
|
+
/\.rmp-container>\.rmp-content>\.rmp-cc-area>\.rmp-cc-container>\.rmp-cc-display>\.rmp-cc-cue\s?\.?/, ''
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# This class defines validation tools for data.
|
5
|
+
class Validator
|
6
|
+
def self.hex?(value)
|
7
|
+
hex = true
|
8
|
+
value.gsub!('#', '')
|
9
|
+
value.chars.each do |digit|
|
10
|
+
hex = false unless digit.match(/\h/)
|
11
|
+
end
|
12
|
+
hex
|
13
|
+
end
|
14
|
+
end
|
data/lib/vtt2ass/version.rb
CHANGED
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'vtt_line'
|
4
|
+
|
5
|
+
##
|
6
|
+
# This class defines a VTT subtile file.
|
7
|
+
class VTTFile
|
8
|
+
attr_accessor :lines
|
9
|
+
|
10
|
+
##
|
11
|
+
# Creates a new VTTFile instance and assigns the default values of instance variables.
|
12
|
+
def initialize(file_path, width, height)
|
13
|
+
@title = File.basename(file_path).gsub('.vtt', '')
|
14
|
+
@lines = []
|
15
|
+
separator = determine_line_ending(file_path) ? "\n\n" : "\r\n\r\n"
|
16
|
+
count = 0
|
17
|
+
style_count = 1
|
18
|
+
File.foreach(file_path, separator) do |paragraph|
|
19
|
+
paragraph = paragraph.rstrip.gsub(/[\r\n]/, "\n")
|
20
|
+
unless paragraph.eql? ''
|
21
|
+
vtt_line = VTTLine.new(paragraph, width, height)
|
22
|
+
if vtt_line.style.eql?('Main') &&
|
23
|
+
!vtt_line.params.to_s.empty? &&
|
24
|
+
(!vtt_line.params.to_s.eql?('align:middle') &&
|
25
|
+
!vtt_line.params.to_s.eql?('align:center'))
|
26
|
+
vtt_line.style = "Style#{style_count}"
|
27
|
+
style_count += 1
|
28
|
+
end
|
29
|
+
@lines.push(vtt_line)
|
30
|
+
count += 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
@lines.shift
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# This method determines the line ending character to use as a separator.
|
38
|
+
def determine_line_ending(file_path)
|
39
|
+
File.open(file_path, 'r') do |file|
|
40
|
+
return file.readline[/\r?\n$/] == "\n"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# This method writes the content of the VTTFile object into a file path that is provided.
|
46
|
+
def write_to_file(file_path)
|
47
|
+
File.open(file_path, 'w') do |line|
|
48
|
+
line.print "\ufeff"
|
49
|
+
line.puts to_s
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# This method concatenates the object data in the right order for a string output.
|
55
|
+
def to_s
|
56
|
+
"WEBVTT\n\n\n#{@lines}"
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# This class defines a VTT subtile line.
|
5
|
+
class VTTLine
|
6
|
+
attr_accessor :style
|
7
|
+
attr_reader :time_start, :time_end, :params, :text
|
8
|
+
|
9
|
+
##
|
10
|
+
# This method creates an instance of an VTTLine.
|
11
|
+
#
|
12
|
+
# * Requires +paragraph+, a VTT formatted string as input.
|
13
|
+
def initialize(paragraph, width, height)
|
14
|
+
lines = paragraph.split("\n")
|
15
|
+
rx = /^([\d:.]*) --> ([\d:.]*)\s?(.*?)\s*$/
|
16
|
+
@style = 'Main'
|
17
|
+
@text, @time_start, @time_end, @params = ''
|
18
|
+
count = 0
|
19
|
+
|
20
|
+
lines.each do |line|
|
21
|
+
m = line.match(rx)
|
22
|
+
if !m && count.zero?
|
23
|
+
@style = line
|
24
|
+
elsif m
|
25
|
+
@time_start = m[1]
|
26
|
+
@time_end = m[2]
|
27
|
+
@params = m[3]
|
28
|
+
ass_style = ASSStyleParams.new(@params, width, height)
|
29
|
+
@style = 'MainTop' if @style.eql?('Main') && ass_style.alignment == 8
|
30
|
+
else
|
31
|
+
@text += "#{line}\n"
|
32
|
+
end
|
33
|
+
count += 1
|
34
|
+
end
|
35
|
+
|
36
|
+
@text = @text.lstrip
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# This method assigns the object values and outputs a VTT dialogue line.
|
41
|
+
def to_s
|
42
|
+
"#{@style} \n#{@time_start} --> #{@time_end} #{@params}\n#{@text}"
|
43
|
+
end
|
44
|
+
end
|
data/lib/vtt2ass.rb
CHANGED
@@ -1,30 +1,60 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'thor'
|
3
4
|
|
4
|
-
# Relative imports
|
5
5
|
require_relative 'vtt2ass/version'
|
6
|
-
require_relative 'vtt2ass/
|
6
|
+
require_relative 'vtt2ass/application'
|
7
7
|
|
8
|
+
##
|
9
|
+
# This is the main command line Class that manages the provided CLI arguments.
|
8
10
|
class MainCommand < Thor
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
def self.exit_on_failure?
|
12
|
+
true
|
13
|
+
end
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
15
|
+
desc 'convert INPUT', 'Run the VTT to ASS conversion for the specified file(s)'
|
16
|
+
method_option :output, aliases: '-o',
|
17
|
+
desc: 'Output directory of the converted file',
|
18
|
+
lazy_default: './',
|
19
|
+
type: :string
|
20
|
+
method_option :title, aliases: '-t',
|
21
|
+
desc: 'Specify a title for you file. If the input is a directory, '\
|
22
|
+
'all files will share the same title.',
|
23
|
+
type: :string
|
24
|
+
method_option :font_size, aliases: '-s',
|
25
|
+
desc: 'Specify a font size for the subtitles',
|
26
|
+
default: 52,
|
27
|
+
type: :numeric
|
28
|
+
method_option :font_family, aliases: '-f',
|
29
|
+
desc: 'Specify a font family for the subtitles',
|
30
|
+
default: 'Open Sans Semibold',
|
31
|
+
type: :string
|
32
|
+
method_option :css, aliases: '-c',
|
33
|
+
desc: 'Specify a CSS file path for Hidive subs',
|
34
|
+
type: :string
|
35
|
+
method_option :line_offset, aliases: '-l',
|
36
|
+
desc: 'Specify a line offset for the main dialog (e.g. 50 lowers the '\
|
37
|
+
'text line by 50px of the total height)',
|
38
|
+
default: 0,
|
39
|
+
type: :numeric
|
40
|
+
method_option :width, aliases: '-w',
|
41
|
+
desc: 'Specify the video width',
|
42
|
+
default: 1920,
|
43
|
+
type: :numeric
|
44
|
+
method_option :height, aliases: '-h',
|
45
|
+
desc: 'Specify the video height',
|
46
|
+
default: 1080,
|
47
|
+
type: :numeric
|
48
|
+
method_option :quiet, aliases: '-q',
|
49
|
+
desc: 'Don\'t output to the console',
|
50
|
+
type: :boolean
|
51
|
+
def convert(input)
|
52
|
+
app = Application.new(input, options)
|
53
|
+
app.start
|
54
|
+
end
|
25
55
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
56
|
+
desc 'version', 'Show version'
|
57
|
+
def version
|
58
|
+
puts Vtt2ass::VERSION
|
59
|
+
end
|
30
60
|
end
|
data/vtt2ass.gemspec
CHANGED
@@ -1,36 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'lib/vtt2ass/version'
|
2
4
|
|
3
5
|
Gem::Specification.new do |spec|
|
4
|
-
spec.name =
|
6
|
+
spec.name = 'vtt2ass'
|
5
7
|
spec.version = Vtt2ass::VERSION
|
6
|
-
spec.authors = [
|
7
|
-
spec.email = [
|
8
|
+
spec.authors = ['Louis-Philippe Fortin']
|
9
|
+
spec.email = ['timemaster.lpf@gmail.com']
|
8
10
|
|
9
|
-
spec.summary =
|
10
|
-
spec.homepage =
|
11
|
-
spec.license =
|
12
|
-
spec.required_ruby_version = Gem::Requirement.new(
|
11
|
+
spec.summary = 'Convert VTT subtitles to ASS subtitles'
|
12
|
+
spec.homepage = 'https://gitlab.com/dkb-weeblets/vtt2ass'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.7.2')
|
13
15
|
|
14
|
-
spec.metadata[
|
16
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
15
17
|
|
16
|
-
spec.metadata[
|
17
|
-
spec.metadata[
|
18
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
19
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
18
20
|
|
19
21
|
# Specify which files should be added to the gem when it is released.
|
20
22
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
-
spec.files
|
23
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
22
24
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
23
25
|
end
|
24
|
-
spec.bindir =
|
26
|
+
spec.bindir = 'exe'
|
25
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
|
-
spec.require_paths = [
|
28
|
+
spec.require_paths = ['lib']
|
27
29
|
|
28
|
-
spec.add_dependency 'htmlentities', '~> 4.3'
|
29
|
-
spec.add_dependency 'thor', '~> 1.1'
|
30
30
|
spec.add_dependency 'css_parser', '~> 1.10'
|
31
|
+
spec.add_dependency 'htmlentities', '~> 4.3'
|
31
32
|
spec.add_dependency 'redgreenblue', '~> 0.15'
|
33
|
+
spec.add_dependency 'thor', '~> 1.1'
|
32
34
|
|
33
|
-
spec.add_development_dependency 'rake', '~> 12.0'
|
34
35
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
36
|
+
spec.add_development_dependency 'rake', '~> 12.0'
|
35
37
|
spec.add_development_dependency 'yard', '~> 0.9'
|
38
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
36
39
|
end
|
metadata
CHANGED
@@ -1,99 +1,99 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vtt2ass
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Louis-Philippe Fortin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: css_parser
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.10'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '1.10'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: htmlentities
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '4.3'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '4.3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: redgreenblue
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '0.15'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '0.15'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: thor
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '1.1'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '1.1'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: minitest
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '5.0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '5.0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rake
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '12.0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '12.0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: yard
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -118,6 +118,7 @@ extra_rdoc_files: []
|
|
118
118
|
files:
|
119
119
|
- ".gitignore"
|
120
120
|
- ".gitlab-ci.yml"
|
121
|
+
- ".rubocop.yml"
|
121
122
|
- Gemfile
|
122
123
|
- LICENSE.txt
|
123
124
|
- README.md
|
@@ -153,17 +154,17 @@ files:
|
|
153
154
|
- doc/top-level-namespace.html
|
154
155
|
- exe/vtt2ass
|
155
156
|
- lib/vtt2ass.rb
|
156
|
-
- lib/vtt2ass/
|
157
|
-
- lib/vtt2ass/
|
158
|
-
- lib/vtt2ass/
|
159
|
-
- lib/vtt2ass/
|
160
|
-
- lib/vtt2ass/
|
161
|
-
- lib/vtt2ass/
|
162
|
-
- lib/vtt2ass/
|
163
|
-
- lib/vtt2ass/
|
164
|
-
- lib/vtt2ass/VTTLine.rb
|
165
|
-
- lib/vtt2ass/Validator.rb
|
157
|
+
- lib/vtt2ass/application.rb
|
158
|
+
- lib/vtt2ass/ass_file.rb
|
159
|
+
- lib/vtt2ass/ass_line.rb
|
160
|
+
- lib/vtt2ass/ass_style.rb
|
161
|
+
- lib/vtt2ass/ass_style_params.rb
|
162
|
+
- lib/vtt2ass/css_file.rb
|
163
|
+
- lib/vtt2ass/css_rule.rb
|
164
|
+
- lib/vtt2ass/validator.rb
|
166
165
|
- lib/vtt2ass/version.rb
|
166
|
+
- lib/vtt2ass/vtt_file.rb
|
167
|
+
- lib/vtt2ass/vtt_line.rb
|
167
168
|
- vtt2ass.gemspec
|
168
169
|
homepage: https://gitlab.com/dkb-weeblets/vtt2ass
|
169
170
|
licenses:
|
@@ -172,6 +173,7 @@ metadata:
|
|
172
173
|
allowed_push_host: https://rubygems.org
|
173
174
|
homepage_uri: https://gitlab.com/dkb-weeblets/vtt2ass
|
174
175
|
source_code_uri: https://gitlab.com/dkb-weeblets/vtt2ass
|
176
|
+
rubygems_mfa_required: 'true'
|
175
177
|
post_install_message:
|
176
178
|
rdoc_options: []
|
177
179
|
require_paths:
|
data/lib/vtt2ass/ASSFile.rb
DELETED
@@ -1,110 +0,0 @@
|
|
1
|
-
# Relative imports
|
2
|
-
require_relative 'ASSLine'
|
3
|
-
require_relative 'ASSStyle'
|
4
|
-
require_relative 'CSSFile'
|
5
|
-
require_relative 'CSSRule'
|
6
|
-
|
7
|
-
##
|
8
|
-
# This class defines an ASS subtitle file.
|
9
|
-
class ASSFile
|
10
|
-
attr_reader :title, :width, :height
|
11
|
-
attr_accessor :ass_styles, :ass_lines
|
12
|
-
|
13
|
-
##
|
14
|
-
# Creates a new ASSFile instance and assigns the default values of instance variables.
|
15
|
-
def initialize(title, width, height, css_file_path = nil)
|
16
|
-
@width = width
|
17
|
-
@height = height
|
18
|
-
if not css_file_path.nil? then
|
19
|
-
@css_file = CSSFile.new(css_file_path)
|
20
|
-
end
|
21
|
-
@header = [
|
22
|
-
'[Script Info]',
|
23
|
-
"Title: #{title}",
|
24
|
-
'ScriptType: v4.00+',
|
25
|
-
'Collisions: Normal',
|
26
|
-
'PlayDepth: 0',
|
27
|
-
"PlayResX: #{@width}",
|
28
|
-
"PlayResY: #{@height}",
|
29
|
-
'WrapStyle: 0',
|
30
|
-
'ScaledBorderAndShadow: yes',
|
31
|
-
'',
|
32
|
-
'[V4+ Styles]',
|
33
|
-
'Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding'
|
34
|
-
]
|
35
|
-
@events = [
|
36
|
-
'',
|
37
|
-
'[Events]',
|
38
|
-
'Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text'
|
39
|
-
]
|
40
|
-
@ass_styles = []
|
41
|
-
@ass_lines = []
|
42
|
-
end
|
43
|
-
|
44
|
-
##
|
45
|
-
# This method receives a VTTFile object and font arguments creates new ASSLine with the params of
|
46
|
-
# each VTTLine. All those ASSLine are stored in an array. It also creates an array of ASSStyle that
|
47
|
-
# will be used in the ASS style list.
|
48
|
-
def convertVTTtoASS(vtt_file, font_family, font_size, line_offset = 0)
|
49
|
-
fs = font_size
|
50
|
-
vtt_file.lines.each do |line|
|
51
|
-
font_color = '&H00FFFFFF'
|
52
|
-
is_italic = false
|
53
|
-
is_bold = false
|
54
|
-
@ass_lines.push(ASSLine.new(line.style, line.time_start, line.time_end, line.text))
|
55
|
-
style_exists = false
|
56
|
-
@ass_styles.each do |style|
|
57
|
-
if (style.style_name.eql? line.style) then
|
58
|
-
style_exists = true
|
59
|
-
break
|
60
|
-
end
|
61
|
-
end
|
62
|
-
if not style_exists then
|
63
|
-
if defined?(@css_file) then
|
64
|
-
css_rule = @css_file.find_rule(line.style)
|
65
|
-
if not css_rule.nil? then
|
66
|
-
css_rule.properties.each do |property|
|
67
|
-
case property[:key]
|
68
|
-
when 'font-family'
|
69
|
-
font_family = property[:value].gsub('"', '').split(' ,').last
|
70
|
-
when 'font-size'
|
71
|
-
em_size = 1
|
72
|
-
#em_size = property[:value][0].eql? '.' ? "0#{property[:value]}" : property[:value]
|
73
|
-
if property[:value][0].eql? '.' then
|
74
|
-
em_size = "0#{property[:value]}".gsub('em', '').to_f
|
75
|
-
end
|
76
|
-
font_size = (fs * em_size).to_i
|
77
|
-
when 'color'
|
78
|
-
font_color = ASSStyle.convert_color(property[:value])
|
79
|
-
when 'font-weight'
|
80
|
-
if property[:value].eql? 'bold' then
|
81
|
-
is_bold = true
|
82
|
-
end
|
83
|
-
when 'font-style'
|
84
|
-
if property[:value].eql? 'italic' then
|
85
|
-
is_italic = true
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
@ass_styles.push(ASSStyle.new(line.style, line.params, font_family, font_size, font_color, is_bold, is_italic, line_offset, @width, @height))
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
##
|
97
|
-
# This method writes the content of the ASSFile object into a file path that is provided.
|
98
|
-
def writeToFile(file_path)
|
99
|
-
File.open(file_path, 'w') do |line|
|
100
|
-
line.print "\ufeff"
|
101
|
-
line.puts self.to_s
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
##
|
106
|
-
# This method concatenates the object data in the right order for a string output.
|
107
|
-
def to_s
|
108
|
-
return @header + @ass_styles + @events + @ass_lines
|
109
|
-
end
|
110
|
-
end
|
data/lib/vtt2ass/ASSLine.rb
DELETED
@@ -1,94 +0,0 @@
|
|
1
|
-
require 'htmlentities'
|
2
|
-
|
3
|
-
##
|
4
|
-
# This class defines an ASS subtile line.
|
5
|
-
class ASSLine
|
6
|
-
attr_reader :style, :time_start, :time_end, :text
|
7
|
-
|
8
|
-
##
|
9
|
-
# This method creates an instance of an ASSLine.
|
10
|
-
#
|
11
|
-
# * Requires a +style+ name as input.
|
12
|
-
# * Requires +time_start+, a VTT formatted timestamp as input.
|
13
|
-
# * Requires +time_start+, a VTT formatted timestamp as input.
|
14
|
-
# * Requires +text+, a VTT formatted string as input.
|
15
|
-
def initialize(style, time_start, time_end, text)
|
16
|
-
@style = style
|
17
|
-
@time_start = convertTime(time_start)
|
18
|
-
@time_end = convertTime(time_end)
|
19
|
-
@text = convertToAssText(text)
|
20
|
-
end
|
21
|
-
|
22
|
-
##
|
23
|
-
# This method assigns the object values and outputs an ASS dialogue line.
|
24
|
-
def to_s
|
25
|
-
return "Dialogue: 0,#{@time_start},#{@time_end},#{@style},,0,0,0,,#{@text}"
|
26
|
-
end
|
27
|
-
|
28
|
-
##
|
29
|
-
# This method replaces characters and tags to ASS compatible characters and tags.
|
30
|
-
#
|
31
|
-
# * Requires +text+, a string of VTT formated text as input.
|
32
|
-
def convertToAssText(text)
|
33
|
-
decoder = HTMLEntities.new()
|
34
|
-
text = text
|
35
|
-
.gsub(/\r/, '')
|
36
|
-
.gsub(/\n/, '\\N')
|
37
|
-
.gsub(/\\n/, '\\N')
|
38
|
-
.gsub(/\\N +/, '\\N')
|
39
|
-
.gsub(/ +\\N/, '\\N')
|
40
|
-
.gsub(/(\\N)+/, '\\N')
|
41
|
-
.gsub(/<b[^>]*>([^<]*)<\/b>/) { |s| "{\\b1}#{$1}{\\b0}" }
|
42
|
-
.gsub(/<i[^>]*>([^<]*)<\/i>/) { |s| "{\\i1}#{$1}{\\i0}" }
|
43
|
-
.gsub(/<u[^>]*>([^<]*)<\/u>/) { |s| "{\\u1}#{$1}{\\u0}" }
|
44
|
-
.gsub(/<c[^>]*>([^<]*)<\/c>/) { |s| $1 }
|
45
|
-
.gsub(/<[^>]>/, '')
|
46
|
-
.gsub(/\\N$/, '')
|
47
|
-
.gsub(/ +$/, '')
|
48
|
-
return decoder.decode(text)
|
49
|
-
end
|
50
|
-
|
51
|
-
##
|
52
|
-
# This method validates the time format and sends the matching time to be converted
|
53
|
-
#
|
54
|
-
# * Requires +str+, a VTT formatted time string.
|
55
|
-
def convertTime(time)
|
56
|
-
mTime = time.match(/([\d:]*)\.?(\d*)/)
|
57
|
-
return toSubsTime(mTime[0])
|
58
|
-
end
|
59
|
-
|
60
|
-
##
|
61
|
-
# This method converts time from VTT format to the ASS format.
|
62
|
-
#
|
63
|
-
# * Requires +str+, a VTT formatted time string.
|
64
|
-
def toSubsTime(str)
|
65
|
-
n = []
|
66
|
-
x = str.split(/[:.]/).map { |x| x.to_i }
|
67
|
-
|
68
|
-
msLen = 2
|
69
|
-
hLen = 1
|
70
|
-
|
71
|
-
x[3] = '0.' + (x[3].to_s).rjust(3, '0')
|
72
|
-
sx = x[0]*60*60 + x[1]*60 + x[2] + x[3].to_f
|
73
|
-
sx = ("%.2f" % sx).split('.')
|
74
|
-
|
75
|
-
n.unshift(padTimeNum('.', sx[1], msLen))
|
76
|
-
sx = sx[0].to_f
|
77
|
-
|
78
|
-
n.unshift(padTimeNum(':', (sx % 60).to_i, 2))
|
79
|
-
n.unshift(padTimeNum(':', (sx / 60).floor % 60, 2))
|
80
|
-
n.unshift(padTimeNum('', (sx / 3600).floor % 60, hLen))
|
81
|
-
|
82
|
-
return n.join('')
|
83
|
-
end
|
84
|
-
|
85
|
-
##
|
86
|
-
# This method pads text so that time numbers are a fixed number of digit.
|
87
|
-
#
|
88
|
-
# * Requires +sep+, a string separator.
|
89
|
-
# * Requires +input+, an integer.
|
90
|
-
# * Requires +pad+, an integer for the number of digits to be padded.
|
91
|
-
def padTimeNum(sep, input, pad)
|
92
|
-
return sep + (input.to_s).rjust(pad, '0')
|
93
|
-
end
|
94
|
-
end
|