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
data/lib/vtt2ass/ASSStyle.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
# Relative imports
|
2
|
-
require_relative 'ASSStyleParams'
|
3
|
-
require_relative 'Validator'
|
4
|
-
require 'redgreenblue'
|
5
|
-
|
6
|
-
##
|
7
|
-
# This class defines an ASS style that can be applied on a subtitle line.
|
8
|
-
class ASSStyle
|
9
|
-
attr_reader :style_name
|
10
|
-
|
11
|
-
##
|
12
|
-
# This method creates and instance of an ASSStyle.
|
13
|
-
#
|
14
|
-
# * Requires +style_name+, a string name for the style as input.
|
15
|
-
# * Requires +params+, a string of VTT styling as input.
|
16
|
-
# * Requires a video +width+ as input.
|
17
|
-
# * Requires a video +height+ as input.
|
18
|
-
def initialize(style_name, params, font_family, font_size, font_color, is_bold, is_italic, line_offset, width, height)
|
19
|
-
@width = width
|
20
|
-
@height = height
|
21
|
-
@font_family = font_family
|
22
|
-
@font_size = font_size
|
23
|
-
@font_color = font_color
|
24
|
-
@style_name = style_name
|
25
|
-
@s_params = ASSStyleParams.new(params, width, height)
|
26
|
-
if style_name.eql? 'MainTop' then
|
27
|
-
@s_params.vertical_margin = 50
|
28
|
-
end
|
29
|
-
if style_name.include? 'Subtitle' then
|
30
|
-
@s_params.vertical_margin -= line_offset
|
31
|
-
end
|
32
|
-
@is_italic = is_italic
|
33
|
-
@is_bold = is_bold
|
34
|
-
end
|
35
|
-
|
36
|
-
##
|
37
|
-
# This method assigns the object values to an ASS style line and outputs it.
|
38
|
-
def to_s
|
39
|
-
# Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
|
40
|
-
return "Style: #{@style_name},#{@font_family},#{@font_size},#{@font_color},&H000000FF,&H00020713,&H00000000,#{@is_bold ? '-1' : '0'},#{@is_italic ? '-1' : '0'},0,0,100,100,0,0,1,2.0,2.0,#{@s_params.alignment},#{@s_params.horizontal_margin},0,#{@s_params.vertical_margin},1"
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.convert_color(color_value)
|
44
|
-
color_value.gsub!('#', '')
|
45
|
-
color = Validator.hex?(color_value) ? RGB.hex(color_value) : RGB.css(color_value)
|
46
|
-
return ("&H00%02x%02x%02x" % [color.b, color.g, color.r]).upcase
|
47
|
-
end
|
48
|
-
end
|
@@ -1,87 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# This class defines the ASS style parameters from VTT cue settings.
|
3
|
-
class ASSStyleParams
|
4
|
-
attr_accessor :horizontal_margin, :vertical_margin, :alignment, :align
|
5
|
-
|
6
|
-
##
|
7
|
-
# Creates an instance of ASSStyleParams
|
8
|
-
# It takes VTT style arguments and assign them to their respectful instance variable.
|
9
|
-
# It calls methods to create ASS values from the VTT cue settings.
|
10
|
-
def initialize(params, width, height)
|
11
|
-
(params.split(' ').map { |p| p.split(':') }).each do |p|
|
12
|
-
case p[0]
|
13
|
-
when 'position'
|
14
|
-
@position = p[1].gsub(/%/, '').to_i
|
15
|
-
when 'line'
|
16
|
-
@line = p[1].gsub(/%/, '').to_i
|
17
|
-
@line = @line == -1 ? 100 : @line;
|
18
|
-
when 'align'
|
19
|
-
@align = p[1].chomp
|
20
|
-
end
|
21
|
-
end
|
22
|
-
createAlignment()
|
23
|
-
createHorizontalMargin(width)
|
24
|
-
createVerticalMargin(height)
|
25
|
-
end
|
26
|
-
|
27
|
-
##
|
28
|
-
# This method decides the alignement value in a 9 position grid based of the
|
29
|
-
# values in cue settings "align" and "line".
|
30
|
-
def createAlignment()
|
31
|
-
if (defined?(@line) and not defined?(@position)) then
|
32
|
-
if (defined?(@align)) then
|
33
|
-
case @align
|
34
|
-
when 'left', 'start'
|
35
|
-
@alignment = @line >= 50 ? 1 : 7
|
36
|
-
when 'right', 'end'
|
37
|
-
@alignment = @line >= 50 ? 3 : 9
|
38
|
-
when 'center', 'middle'
|
39
|
-
@alignment = @line >= 50 ? 2 : 8
|
40
|
-
end
|
41
|
-
else
|
42
|
-
@alignment = @line >= 50 ? 2 : 8 # If position is higher than 50% align to bottom center, else align to top center
|
43
|
-
end
|
44
|
-
elsif (defined?(@line) and defined?(@position)) then
|
45
|
-
@alignment = 1
|
46
|
-
else
|
47
|
-
case @align
|
48
|
-
when 'left', 'start'
|
49
|
-
@alignment = 1
|
50
|
-
when 'right', 'end'
|
51
|
-
@alignment = 3
|
52
|
-
when 'center', 'middle'
|
53
|
-
@alignment = 2
|
54
|
-
else
|
55
|
-
@alignment = 2
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
##
|
61
|
-
# This method calculates the horizontal margin in px between the alignement position and
|
62
|
-
# and the content displayed by using the "position" cue setting.
|
63
|
-
def createHorizontalMargin(width)
|
64
|
-
steps = (width / 100).to_i
|
65
|
-
if defined?(@position) then
|
66
|
-
@horizontal_margin = @position * steps
|
67
|
-
else
|
68
|
-
@horizontal_margin = 0
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
##
|
73
|
-
# This method calculates the vertical margin in px between the alignement position and
|
74
|
-
# and the content displayed by using the "line" cue setting.
|
75
|
-
def createVerticalMargin(height)
|
76
|
-
steps = (height / 100).to_i
|
77
|
-
if defined?(@line) then
|
78
|
-
if (@alignment == 1) then
|
79
|
-
@vertical_margin = (100 - @line) * steps
|
80
|
-
else
|
81
|
-
@vertical_margin = @line >= 50 ? (100 - @line) * steps : @line * steps
|
82
|
-
end
|
83
|
-
else
|
84
|
-
@vertical_margin = 50
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
data/lib/vtt2ass/Application.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
# Relative imports
|
2
|
-
require_relative 'VTTFile'
|
3
|
-
require_relative 'ASSFile'
|
4
|
-
|
5
|
-
##
|
6
|
-
# Main application class that manages all the operations.
|
7
|
-
class Application
|
8
|
-
|
9
|
-
##
|
10
|
-
# Creates a new Application instance.
|
11
|
-
# It receives +options+ that can define the input and output directories.
|
12
|
-
def initialize(input, options)
|
13
|
-
@input = input ? input.gsub('\\', '/').delete_suffix('/') : "."
|
14
|
-
@output = options[:output] ? options[:output].gsub('\\', '/').delete_suffix('/') : nil
|
15
|
-
@width = 1920
|
16
|
-
@height = 1080
|
17
|
-
@font_family = options[:font_family] ? options[:font_family] : 'Open Sans Semibold'
|
18
|
-
@font_size = options[:font_size] ? options[:font_size] : 52
|
19
|
-
if options[:title] then
|
20
|
-
@title = options[:title]
|
21
|
-
end
|
22
|
-
@quiet = options[:quiet]
|
23
|
-
if options[:css] then
|
24
|
-
@css = options[:css].gsub('\\', '/')
|
25
|
-
end
|
26
|
-
@line_offset = options[:line_offset]
|
27
|
-
end
|
28
|
-
|
29
|
-
##
|
30
|
-
# This method starts the application process.
|
31
|
-
# It sends the file_paths of VTT files in the input directory to convertFileToASS method
|
32
|
-
# and outputs the resulting ASS format to a new file.
|
33
|
-
def start
|
34
|
-
if File.directory?(@input) then
|
35
|
-
Dir["#{@input}/*.vtt"].each do |file_path|
|
36
|
-
convert(file_path)
|
37
|
-
end
|
38
|
-
elsif File.file?(@input) then
|
39
|
-
convert(@input)
|
40
|
-
else
|
41
|
-
puts 'Error: input file or directory does not exist.'
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def convert(input_path)
|
46
|
-
ass_file = vtt_to_ass(input_path)
|
47
|
-
if (not @output.nil?) then
|
48
|
-
ass_file.writeToFile(@output + '/' + File.basename(input_path).gsub('.vtt', '.ass'))
|
49
|
-
end
|
50
|
-
puts ass_file.to_s unless @quiet
|
51
|
-
end
|
52
|
-
|
53
|
-
##
|
54
|
-
# This method creates a new VTTFile object from the file path provided and convert its content
|
55
|
-
# inside a new ASSFile object.
|
56
|
-
def vtt_to_ass(file_path)
|
57
|
-
vtt_file = VTTFile.new(file_path, @width, @height)
|
58
|
-
ass_file = ASSFile.new(
|
59
|
-
(defined?(@title) ? @title : File.basename(file_path).gsub('.vtt', '')),
|
60
|
-
@width,
|
61
|
-
@height,
|
62
|
-
defined?(@css) ? @css : nil
|
63
|
-
)
|
64
|
-
ass_file.convertVTTtoASS(vtt_file, @font_family, @font_size, @line_offset)
|
65
|
-
return ass_file
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
data/lib/vtt2ass/CSSFile.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'css_parser'
|
2
|
-
require_relative 'CSSRule'
|
3
|
-
|
4
|
-
class CSSFile
|
5
|
-
attr_reader :rules
|
6
|
-
include CssParser
|
7
|
-
|
8
|
-
def initialize(file_path)
|
9
|
-
@file_path = file_path
|
10
|
-
parser = CssParser::Parser.new
|
11
|
-
parser.load_file!(file_path)
|
12
|
-
@rules = []
|
13
|
-
parser.each_selector do |selector, declarations, specificity|
|
14
|
-
css_obj = CSSRule.new(selector, declarations)
|
15
|
-
if not css_obj.name.empty? then
|
16
|
-
@rules.push(css_obj)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def find_rule(value)
|
22
|
-
return_rule = nil
|
23
|
-
@rules.each do |rule|
|
24
|
-
if rule.name == value then
|
25
|
-
return_rule = rule
|
26
|
-
break
|
27
|
-
end
|
28
|
-
end
|
29
|
-
return return_rule
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_s
|
33
|
-
return @file_path
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
data/lib/vtt2ass/CSSRule.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
class CSSRule
|
2
|
-
attr_reader :name, :properties
|
3
|
-
|
4
|
-
def initialize(selector, declarations)
|
5
|
-
@name = reduce_selector(selector)
|
6
|
-
@properties = []
|
7
|
-
declarations.split(/;\s?/).each do |dec|
|
8
|
-
temp = dec.split(/:\s?/)
|
9
|
-
@properties.push(
|
10
|
-
{ key: temp.first, value: temp.last}
|
11
|
-
)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def to_s
|
16
|
-
return "#{@name} #{@properties}"
|
17
|
-
end
|
18
|
-
|
19
|
-
def reduce_selector(selector)
|
20
|
-
return selector.to_s.gsub(/\.rmp-container>\.rmp-content>\.rmp-cc-area>\.rmp-cc-container>\.rmp-cc-display>\.rmp-cc-cue\s?\.?/, '')
|
21
|
-
end
|
22
|
-
end
|
data/lib/vtt2ass/VTTFile.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
# Relative imports
|
2
|
-
require_relative 'VTTLine'
|
3
|
-
|
4
|
-
##
|
5
|
-
# This class defines a VTT subtile file.
|
6
|
-
class VTTFile
|
7
|
-
attr_accessor :lines
|
8
|
-
|
9
|
-
##
|
10
|
-
# Creates a new VTTFile instance and assigns the default values of instance variables.
|
11
|
-
def initialize(file_path, width, height)
|
12
|
-
@title = File.basename(file_path).gsub('.vtt', '')
|
13
|
-
@lines = []
|
14
|
-
separator = determine_line_ending(file_path) ? "\n\n" : "\r\n\r\n"
|
15
|
-
count = 0
|
16
|
-
style_count = 1
|
17
|
-
File.foreach(file_path, separator) do |paragraph|
|
18
|
-
paragraph = paragraph.rstrip.gsub(/[\r\n]/, "\n")
|
19
|
-
if not paragraph.eql? "" then
|
20
|
-
vtt_line = VTTLine.new(paragraph, width, height)
|
21
|
-
if vtt_line.style.eql? 'Main' and
|
22
|
-
not vtt_line.params.to_s.empty? and
|
23
|
-
(not vtt_line.params.to_s.eql? 'align:middle' and
|
24
|
-
not vtt_line.params.to_s.eql? 'align:center') then
|
25
|
-
vtt_line.style = "Style#{style_count}"
|
26
|
-
style_count += 1
|
27
|
-
end
|
28
|
-
@lines.push(vtt_line)
|
29
|
-
count += 1
|
30
|
-
end
|
31
|
-
end
|
32
|
-
@lines.shift
|
33
|
-
end
|
34
|
-
|
35
|
-
##
|
36
|
-
# This method determines the line ending character to use as a separator.
|
37
|
-
def determine_line_ending(file_path)
|
38
|
-
File.open(file_path, 'r') do |file|
|
39
|
-
return file.readline[/\r?\n$/] == "\n"
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
##
|
44
|
-
# This method writes the content of the VTTFile object into a file path that is provided.
|
45
|
-
def writeToFile(file_path)
|
46
|
-
File.open(file_path, 'w') do |line|
|
47
|
-
line.print "\ufeff"
|
48
|
-
line.puts self.to_s
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
##
|
53
|
-
# This method concatenates the object data in the right order for a string output.
|
54
|
-
def to_s
|
55
|
-
return "WEBVTT\n\n\n" + @lines
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
data/lib/vtt2ass/VTTLine.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
##
|
2
|
-
# This class defines a VTT subtile line.
|
3
|
-
class VTTLine
|
4
|
-
attr_accessor :style
|
5
|
-
attr_reader :time_start, :time_end, :params, :text
|
6
|
-
|
7
|
-
##
|
8
|
-
# This method creates an instance of an VTTLine.
|
9
|
-
#
|
10
|
-
# * Requires +paragraph+, a VTT formatted string as input.
|
11
|
-
def initialize(paragraph, width, height)
|
12
|
-
lines = paragraph.split("\n")
|
13
|
-
rx = /^([\d:.]*) --> ([\d:.]*)\s?(.*?)\s*$/
|
14
|
-
@style = "Main"
|
15
|
-
@text, @time_start, @time_end, @params = ""
|
16
|
-
count = 0
|
17
|
-
|
18
|
-
lines.each do |line|
|
19
|
-
m = line.match(rx)
|
20
|
-
if not m and count == 0 then
|
21
|
-
@style = line
|
22
|
-
elsif m then
|
23
|
-
@time_start = m[1]
|
24
|
-
@time_end = m[2]
|
25
|
-
@params = m[3]
|
26
|
-
ass_style = ASSStyleParams.new(@params, width, height)
|
27
|
-
if @style.eql? 'Main' and ass_style.alignment == 8 then
|
28
|
-
@style = 'MainTop'
|
29
|
-
end
|
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
|
-
return "#{@style} \n#{@time_start} --> #{@time_end} #{@params}\n#{@text}"
|
43
|
-
end
|
44
|
-
end
|