vtt2ass 0.3.4 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a864637934d7b15e7f459c532cd5f521e21e3445e0408cea0a0a7b3c966f550
4
- data.tar.gz: 5a58b036d877c8529accd0ccc21fe5568d0bdbd686d994ba119ebc894c906e3b
3
+ metadata.gz: 3047227acbd6bf731e5dc95113a7d70081bed94392e3b00078b760ebbc4440a4
4
+ data.tar.gz: e9bc514e5b41028d872d9e983cc4dbd4442fc648ab1065e2c3e5a2aca3c9b8fd
5
5
  SHA512:
6
- metadata.gz: e46d22748e6e8b64ec2d0486ce42cce993bcdb00b88be35db80c234bbcdf0ddad0b869e35f2b880a30a451b0a81ce99f48dfb5d671cfa40ad284b4eece17f1d3
7
- data.tar.gz: 3bbe4b767f309e820d4c44bf8c351090cbe0810219069970c4ac131e50453eeb7b593e9f4793987a69dc9596ab8d6f35815d2d9bbc6785afe755551bcec7c49d
6
+ metadata.gz: 388af342ebe22e69e52e92e4dadf5a04ea48cb6e491398e864ed1e9d5ae3a602601cddc070ae20f7e8edef0b652a87aa3e8a66f8b8128626315dbac0dd421873
7
+ data.tar.gz: fa2f3b0fa33c3ee1ade343b14837e8f09d2b5145f41e60f68e1cc7236e17e23c67cb7a811f5abf145df7e7121fd651364870073b6ff74679f6c9ddfe375a2ddc
data/.rubocop.yml ADDED
@@ -0,0 +1,19 @@
1
+ ---
2
+ AllCops:
3
+ TargetRubyVersion: 2.7.2
4
+ NewCops: enable
5
+ # Set method line number to 25
6
+ Metrics/MethodLength:
7
+ Max: 25
8
+ # Set parameter number to 10
9
+ Metrics/ParameterLists:
10
+ Max: 10
11
+ # Disable checking of ABC metrics (assignment, branch, condition)
12
+ Metrics/AbcSize:
13
+ Enabled: false
14
+ # Disable method perceived complexity (how it is hard to read a method)
15
+ Metrics/PerceivedComplexity:
16
+ Enabled: false
17
+ # Disable cyclomatic complexity which is a number of paths through a method
18
+ Metrics/CyclomaticComplexity:
19
+ Enabled: false
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in vtt2ass.gemspec
data/README.md CHANGED
@@ -64,6 +64,10 @@ Options:
64
64
  -c, [--css=CSS] # Specify a CSS file path for Hidive subs
65
65
  -l, [--line-offset=N] # Specify a line offset for the main dialog (e.g. 50 lowers the text line by 50px of the total height)
66
66
  # Default: 0
67
+ -w, [--width=N] # Specify the video width
68
+ # Default: 1920
69
+ -h, [--height=N] # Specify the video height
70
+ # Default: 1080
67
71
  -q, [--quiet], [--no-quiet] # Don't output to the console
68
72
 
69
73
  Run the VTT to ASS conversion for the specified file(s)
@@ -99,7 +103,7 @@ $ gem build vtt2ass.gemspec
99
103
 
100
104
  To install the gem file:
101
105
  ```bash
102
- $ gem install ./vtt2ass-0.3.3.gem
106
+ $ gem install ./vtt2ass-0.3.5.gem
103
107
  ```
104
108
 
105
109
  ## License
data/Rakefile CHANGED
@@ -1,10 +1,12 @@
1
- require "bundler/gem_tasks"
2
- require "rake/testtask"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
3
5
 
4
6
  Rake::TestTask.new(:test) do |t|
5
- t.libs << "test"
6
- t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
9
+ t.test_files = FileList['test/**/*_test.rb']
8
10
  end
9
11
 
10
- task :default => :test
12
+ task default: :test
data/bin/vtt2ass CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require_relative '../lib/vtt2ass'
4
- MainCommand.start
5
+ MainCommand.start
data/exe/vtt2ass CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'vtt2ass'
4
- MainCommand.start
5
+ MainCommand.start
@@ -1,77 +1,78 @@
1
- # Relative imports
1
+ # frozen_string_literal: true
2
+
2
3
  require_relative 'vtt_file'
3
4
  require_relative 'ass_file'
4
5
 
5
6
  ##
6
7
  # Main application class that manages all the operations.
7
8
  class Application
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
+ @options = options
14
+ @input = sanitize_path(input)
15
+ end
8
16
 
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('\\', '/').delete_suffix('/')
25
- end
26
- @line_offset = options[:line_offset]
27
- end
17
+ ##
18
+ # Replace backslashes from Windows paths to normal slashes.
19
+ # Deletes the trailing slash if there is one.
20
+ def sanitize_path(path)
21
+ path&.gsub('\\', '/')&.delete_suffix('/')
22
+ end
28
23
 
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
24
+ ##
25
+ # This method starts the application process.
26
+ # It sends the file_paths of VTT files in the input directory to convertFileToASS method
27
+ # and outputs the resulting ASS format to a new file.
28
+ def start
29
+ if File.directory?(@input)
30
+ Dir["#{@input}/*.vtt"].each do |file_path|
31
+ convert(file_path)
32
+ end
33
+ elsif File.file?(@input)
34
+ convert(@input)
35
+ else
36
+ raise StandardError, 'ERROR: Input file or directory does not exist.'
43
37
  end
38
+ rescue SystemExit, Interrupt
39
+ puts 'ERROR: The application stopped unexpectedly. The conversion may not have been completed.'
40
+ rescue StandardError => e
41
+ puts e.message
42
+ end
44
43
 
45
- def convert(input_path)
46
- ass_file = vtt_to_ass(input_path)
47
- if (not @output.nil?) then
48
- ass_file.write_to_file(@output + '/' + File.basename(input_path).gsub('.vtt', '.ass'))
49
- end
50
- puts ass_file.to_s unless @quiet
51
- end
44
+ ##
45
+ # This method launches the conversion process on the specified input file.
46
+ def convert(input_path)
47
+ output = sanitize_path(@options[:output])
48
+ raise StandardError, 'ERROR: Output directory does not exist.' unless File.directory?(output)
52
49
 
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
- base_file_name = File.basename(file_path).gsub('.vtt', '')
58
- css_file = nil
59
- if defined?(@css) and File.directory?(@css) then
60
- css_file = "#{@css}/#{base_file_name}.css"
61
- elsif File.file?("#{file_path.gsub('.vtt', '')}.css") then
62
- css_file = "#{file_path.gsub('.vtt', '')}.css"
63
- else
64
- css_file = @css
65
- end
66
- vtt_file = VTTFile.new(file_path, @width, @height)
67
- ass_file = ASSFile.new(
68
- (defined?(@title) ? @title : base_file_name),
69
- @width,
70
- @height,
71
- css_file
72
- )
73
- ass_file.convert_vtt_to_ass(vtt_file, @font_family, @font_size, @line_offset)
74
- return ass_file
75
- end
50
+ ass_file = vtt_to_ass(input_path)
51
+ ass_file.write_to_file("#{output}/#{File.basename(input_path).gsub('.vtt', '.ass')}") unless output.nil?
52
+ puts ass_file.to_s unless @options[:quiet]
53
+ end
76
54
 
77
- end
55
+ ##
56
+ # This method creates a new VTTFile object from the file path provided and convert its content
57
+ # inside a new ASSFile object.
58
+ def vtt_to_ass(file_path)
59
+ base_file_name = File.basename(file_path).gsub('.vtt', '')
60
+ css_file =
61
+ if !@options[:css].nil? && File.directory?(@options[:css])
62
+ "#{sanitize_path(@options[:css])}/#{base_file_name}.css"
63
+ elsif File.file?("#{file_path.gsub('.vtt', '')}.css")
64
+ "#{file_path.gsub('.vtt', '')}.css"
65
+ else
66
+ @options[:css]
67
+ end
68
+ vtt_file = VTTFile.new(file_path, @options[:width], @options[:height])
69
+ ass_file = ASSFile.new(
70
+ (@options[:title].nil? ? base_file_name : @options[:title]),
71
+ @options[:width],
72
+ @options[:height],
73
+ css_file
74
+ )
75
+ ass_file.convert_vtt_to_ass(vtt_file, @options[:font_family], @options[:font_size], @options[:line_offset])
76
+ ass_file
77
+ end
78
+ end
@@ -1,4 +1,5 @@
1
- # Relative imports
1
+ # frozen_string_literal: true
2
+
2
3
  require_relative 'ass_line'
3
4
  require_relative 'ass_style'
4
5
  require_relative 'css_file'
@@ -7,104 +8,99 @@ require_relative 'css_rule'
7
8
  ##
8
9
  # This class defines an ASS subtitle file.
9
10
  class ASSFile
10
- attr_reader :title, :width, :height
11
- attr_accessor :ass_styles, :ass_lines
11
+ attr_reader :title, :width, :height
12
+ attr_accessor :ass_styles, :ass_lines
12
13
 
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
14
+ ##
15
+ # Creates a new ASSFile instance and assigns the default values of instance variables.
16
+ def initialize(title, width, height, css_file_path = nil)
17
+ @width = width
18
+ @height = height
19
+ @css_file = CSSFile.new(css_file_path) unless css_file_path.nil?
20
+ @header = <<~HEADER
21
+ [Script Info]
22
+ Title: #{title}
23
+ ScriptType: v4.00+
24
+ Collisions: Normal
25
+ PlayDepth: 0
26
+ PlayResX: #{@width}
27
+ PlayResY: #{@height}
28
+ WrapStyle: 0
29
+ ScaledBorderAndShadow: yes
30
+
31
+ [V4+ Styles]
32
+ Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
33
+ HEADER
34
+ @events = <<~EVENTS
43
35
 
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 convert_vtt_to_ass(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
36
+ [Events]
37
+ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
38
+ EVENTS
39
+ @ass_styles = []
40
+ @ass_lines = []
41
+ end
42
+
43
+ ##
44
+ # This method receives a VTTFile object and font arguments creates new ASSLine with the params of
45
+ # each VTTLine. All those ASSLine are stored in an array. It also creates an array of ASSStyle that
46
+ # will be used in the ASS style list.
47
+ def convert_vtt_to_ass(vtt_file, font_family, font_size, line_offset = 0) # rubocop:disable Metrics/MethodLength
48
+ fs = font_size
49
+ vtt_file.lines.each do |line| # rubocop:disable Metrics/BlockLength
50
+ font_color = '&H00FFFFFF'
51
+ is_italic = false
52
+ is_bold = false
53
+ @ass_lines.push(ASSLine.new(line.style, line.time_start, line.time_end, line.text))
54
+ style_exists = false
55
+ @ass_styles.each do |style|
56
+ if style.style_name.eql? line.style
57
+ style_exists = true
58
+ break
93
59
  end
94
- end
60
+ end
61
+ next if style_exists
95
62
 
96
- ##
97
- # This method writes the content of the ASSFile object into a file path that is provided.
98
- def write_to_file(file_path)
99
- File.open(file_path, 'w') do |line|
100
- line.print "\ufeff"
101
- line.puts self.to_s
63
+ unless @css_file.nil?
64
+ css_rule = @css_file.find_rule(line.style)
65
+ css_rule&.properties&.each do |property|
66
+ case property[:key]
67
+ when 'font-family'
68
+ font_family = property[:value].gsub('"', '').split(' ,').last
69
+ when 'font-size'
70
+ em_size = 1
71
+ em_size = "0#{property[:value]}".gsub('em', '').to_f if property[:value][0].eql? '.'
72
+ font_size = (fs * em_size).to_i
73
+ when 'color'
74
+ font_color = ASSStyle.convert_color(property[:value])
75
+ when 'font-weight'
76
+ is_bold = true if property[:value].eql? 'bold'
77
+ when 'font-style'
78
+ is_italic = true if property[:value].eql? 'italic'
79
+ end
102
80
  end
81
+ end
82
+ @ass_styles.push(
83
+ ASSStyle.new(
84
+ line.style, line.params,
85
+ font_family, font_size, font_color, is_bold, is_italic,
86
+ line_offset, @width, @height
87
+ )
88
+ )
103
89
  end
90
+ end
104
91
 
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
92
+ ##
93
+ # This method writes the content of the ASSFile object into a file path that is provided.
94
+ def write_to_file(file_path)
95
+ File.open(file_path, 'w') do |line|
96
+ line.print "\ufeff"
97
+ line.puts to_s
109
98
  end
110
- end
99
+ end
100
+
101
+ ##
102
+ # This method concatenates the object data in the right order for a string output.
103
+ def to_s
104
+ "#{@header}#{@ass_styles.join("\n")}#{@events}#{@ass_lines.join("\n")}"
105
+ end
106
+ end
@@ -1,94 +1,97 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'htmlentities'
2
4
 
3
5
  ##
4
6
  # This class defines an ASS subtile line.
5
7
  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 = convert_time(time_start)
18
- @time_end = convert_time(time_end)
19
- @text = convert_to_ass_text(text)
20
- end
8
+ attr_reader :style, :time_start, :time_end, :text
9
+
10
+ ##
11
+ # This method creates an instance of an ASSLine.
12
+ #
13
+ # * Requires a +style+ name as input.
14
+ # * Requires +time_start+, a VTT formatted timestamp as input.
15
+ # * Requires +time_start+, a VTT formatted timestamp as input.
16
+ # * Requires +text+, a VTT formatted string as input.
17
+ def initialize(style, time_start, time_end, text)
18
+ @style = style
19
+ @time_start = convert_time(time_start)
20
+ @time_end = convert_time(time_end)
21
+ @text = convert_to_ass_text(text)
22
+ end
23
+
24
+ ##
25
+ # This method assigns the object values and outputs an ASS dialogue line.
26
+ def to_s
27
+ "Dialogue: 0,#{@time_start},#{@time_end},#{@style},,0,0,0,,#{@text}"
28
+ end
29
+
30
+ ##
31
+ # This method replaces characters and tags to ASS compatible characters and tags.
32
+ #
33
+ # * Requires +text+, a string of VTT formated text as input.
34
+ def convert_to_ass_text(text)
35
+ decoder = HTMLEntities.new
36
+ text =
37
+ text
38
+ .gsub(/\r/, '')
39
+ .gsub(/\n/, '\\N')
40
+ .gsub(/\\n/, '\\N')
41
+ .gsub(/\\N +/, '\\N')
42
+ .gsub(/ +\\N/, '\\N')
43
+ .gsub(/(\\N)+/, '\\N')
44
+ .gsub(%r{<b[^>]*>([^<]*)</b>}) { |_s| "{\\b1}#{Regexp.last_match(1)}{\\b0}" }
45
+ .gsub(%r{<i[^>]*>([^<]*)</i>}) { |_s| "{\\i1}#{Regexp.last_match(1)}{\\i0}" }
46
+ .gsub(%r{<u[^>]*>([^<]*)</u>}) { |_s| "{\\u1}#{Regexp.last_match(1)}{\\u0}" }
47
+ .gsub(%r{<c[^>]*>([^<]*)</c>}) { |_s| Regexp.last_match(1) }
48
+ .gsub(/<[^>]>/, '')
49
+ .gsub(/\\N$/, '')
50
+ .gsub(/ +$/, '')
51
+ decoder.decode(text)
52
+ end
53
+
54
+ ##
55
+ # This method validates the time format and sends the matching time to be converted
56
+ #
57
+ # * Requires +str+, a VTT formatted time string.
58
+ def convert_time(time)
59
+ matched_time = time.match(/([\d:]*)\.?(\d*)/)
60
+ to_subs_time(matched_time[0])
61
+ end
62
+
63
+ ##
64
+ # This method converts time from VTT format to the ASS format.
65
+ #
66
+ # * Requires +str+, a VTT formatted time string.
67
+ def to_subs_time(str)
68
+ n = []
69
+ x = str.split(/[:.]/).map(&:to_i)
70
+
71
+ ms_len = 2
72
+ h_len = 1
73
+
74
+ x[3] = "0.#{x[3].to_s.rjust(3, '0')}"
75
+ sx = (x[0] * 60 * 60) + (x[1] * 60) + x[2] + x[3].to_f
76
+ sx = format('%.2f', sx).split('.')
77
+
78
+ n.unshift(pad_time_num('.', sx[1], ms_len))
79
+ sx = sx[0].to_f
21
80
 
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
81
+ n.unshift(pad_time_num(':', (sx % 60).to_i, 2))
82
+ n.unshift(pad_time_num(':', (sx / 60).floor % 60, 2))
83
+ n.unshift(pad_time_num('', (sx / 3600).floor % 60, h_len))
27
84
 
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 convert_to_ass_text(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
85
+ n.join
86
+ end
50
87
 
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 convert_time(time)
56
- mTime = time.match(/([\d:]*)\.?(\d*)/)
57
- return to_subs_time(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 to_subs_time(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(pad_time_num('.', sx[1], msLen))
76
- sx = sx[0].to_f
77
-
78
- n.unshift(pad_time_num(':', (sx % 60).to_i, 2))
79
- n.unshift(pad_time_num(':', (sx / 60).floor % 60, 2))
80
- n.unshift(pad_time_num('', (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 pad_time_num(sep, input, pad)
92
- return sep + (input.to_s).rjust(pad, '0')
93
- end
94
- end
88
+ ##
89
+ # This method pads text so that time numbers are a fixed number of digit.
90
+ #
91
+ # * Requires +sep+, a string separator.
92
+ # * Requires +input+, an integer.
93
+ # * Requires +pad+, an integer for the number of digits to be padded.
94
+ def pad_time_num(sep, input, pad)
95
+ sep + input.to_s.rjust(pad, '0')
96
+ end
97
+ end