vtt2ass 0.2.8 → 0.2.13

Sign up to get free protection for your applications and to get access to all the features.
@@ -86,7 +86,7 @@
86
86
 
87
87
 
88
88
 
89
- <strong class="classes">Classes:</strong> <span class='object_link'><a href="ASSFile.html" title="ASSFile (class)">ASSFile</a></span>, <span class='object_link'><a href="ASSStyle.html" title="ASSStyle (class)">ASSStyle</a></span>, <span class='object_link'><a href="ASSSubtitle.html" title="ASSSubtitle (class)">ASSSubtitle</a></span>, <span class='object_link'><a href="Application.html" title="Application (class)">Application</a></span>, <span class='object_link'><a href="VTTSubtitle.html" title="VTTSubtitle (class)">VTTSubtitle</a></span>
89
+ <strong class="classes">Classes:</strong> <span class='object_link'><a href="ASSFile.html" title="ASSFile (class)">ASSFile</a></span>, <span class='object_link'><a href="ASSLine.html" title="ASSLine (class)">ASSLine</a></span>, <span class='object_link'><a href="ASSStyle.html" title="ASSStyle (class)">ASSStyle</a></span>, <span class='object_link'><a href="ASSStyleParams.html" title="ASSStyleParams (class)">ASSStyleParams</a></span>, <span class='object_link'><a href="Application.html" title="Application (class)">Application</a></span>, <span class='object_link'><a href="VTTFile.html" title="VTTFile (class)">VTTFile</a></span>, <span class='object_link'><a href="VTTLine.html" title="VTTLine (class)">VTTLine</a></span>
90
90
 
91
91
 
92
92
  </p>
@@ -102,9 +102,9 @@
102
102
  </div>
103
103
 
104
104
  <div id="footer">
105
- Generated on Thu Jan 14 00:31:16 2021 by
105
+ Generated on Tue Mar 23 21:07:02 2021 by
106
106
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
107
- 0.9.26 (ruby-2.7.2).
107
+ 0.9.26 (ruby-3.0.0).
108
108
  </div>
109
109
 
110
110
  </div>
data/lib/vtt2ass.rb CHANGED
@@ -1,42 +1,109 @@
1
1
  # Imports
2
- require 'optparse'
2
+ require 'tty-option'
3
3
 
4
4
  # Relative imports
5
5
  require_relative 'vtt2ass/version'
6
6
  require_relative 'vtt2ass/Application'
7
7
 
8
+ class Command
9
+ include TTY::Option
10
+
11
+ usage do
12
+ header 'VTT2ASS'
13
+ program 'vtt2ass'
14
+ command ''
15
+ desc 'Convert VTT subtitles to ASS subtitles'
16
+ example "Convert files in a specific directory",
17
+ " $ vtt2ass ./path/to/file_input ./path/to/file_output"
18
+ end
19
+
20
+ # ------------------------------
21
+ # Arguments
22
+ # ------------------------------
23
+
24
+ argument :input do
25
+ optional
26
+ desc "Input directory or file (default: current directory)"
27
+ end
28
+
29
+ argument :output do
30
+ optional
31
+ desc "Output directory (default: console output)"
32
+ end
33
+
34
+ # ------------------------------
35
+ # Flags
36
+ # ------------------------------
37
+
38
+ flag :help do
39
+ short "-h"
40
+ long "--help"
41
+ desc "Print usage"
42
+ end
43
+
44
+ flag :version do
45
+ short "-v"
46
+ long "--version"
47
+ desc "Show version"
48
+ end
49
+
50
+ flag :quiet do
51
+ short "-q"
52
+ long "--quiet"
53
+ desc "Prevent the command from outputing to the console"
54
+ end
55
+
56
+ flag :noout do
57
+ short "-x"
58
+ long "--noout"
59
+ desc "Prevents the command from writing the resulting file(s) to the output folder"
60
+ end
61
+
62
+ # ------------------------------
63
+ # Options
64
+ # ------------------------------
65
+
66
+ option :title do
67
+ optional
68
+ short "-t STRING"
69
+ long "--title STRING"
70
+ desc "Specify a title for you file. If the input is a directory, all files will share the same title."
71
+ end
72
+
73
+ option :font_size do
74
+ optional
75
+ short "-s INTEGER"
76
+ long "--font-size INTEGER"
77
+ desc "Specify a font size for the subtitles (default: 52)"
78
+ end
79
+
80
+ option :font_family do
81
+ optional
82
+ short "-f STRING"
83
+ long "--font-family STRING"
84
+ desc "Specify a font family for the subtitles (default: 'Open Sans Semibold')"
85
+ end
86
+
87
+ def run
88
+ if params[:help] then
89
+ print help
90
+ exit
91
+ elsif params[:version] then
92
+ puts Vtt2ass::VERSION
93
+ exit
94
+ else
95
+ runner = Application.new(params)
96
+ # pp params.to_h
97
+ runner.start
98
+ end
99
+ end
100
+ end
101
+
8
102
  module Vtt2ass
9
- ##
10
- # This function creates a new application instance and starts the process.
11
- #
12
- # It also defines the arguments that can be provided from the CLI.
13
103
  def main
14
- options = {}
15
-
16
- OptionParser.new do |opts|
17
- opts.banner = "Usage: vtt2ass [options]"
18
- opts.separator ""
19
- opts.separator "Specific options:"
20
- opts.on("-i", "--input PATH", "Specify a custom input file or directory (default: './')") do |file_path|
21
- options[:input] = file_path
22
- end
23
- opts.on("-o", "--output PATH", "Specify a custom output directory (default: './')") do |file_path|
24
- options[:output] = file_path
25
- end
26
- opts.on("-f", "--font-family FONT", String, "Specify a font family for the subtitles (default: 'Open Sans Semibold')") do |font_family|
27
- options[:font_family] = font_family
28
- end
29
- opts.on("-s", "--font-size SIZE", Integer, "Specify a font size for the subtitles (default: 52)") do |font_size|
30
- options[:font_size] = font_size
31
- end
32
- opts.on("-v", "--version", "Show version") do
33
- puts Vtt2ass::VERSION
34
- exit
35
- end
36
- end.parse!
37
-
38
- app = Application.new(options)
39
- app.start
104
+ app = Command.new
105
+ app.parse
106
+ app.run
40
107
  end
41
108
 
42
109
  module_function :main
@@ -8,6 +8,8 @@ class ASSFile
8
8
  attr_reader :title, :width, :height
9
9
  attr_accessor :ass_styles, :ass_lines
10
10
 
11
+ ##
12
+ # Creates a new ASSFile instance and assigns the default values of instance variables.
11
13
  def initialize(title, width, height)
12
14
  @width = width
13
15
  @height = height
@@ -34,12 +36,16 @@ class ASSFile
34
36
  @ass_lines = []
35
37
  end
36
38
 
39
+ ##
40
+ # This method receives a VTTFile object and font arguments creates new ASSLine with the params of
41
+ # each VTTLine. All those ASSLine are stored in an array. It also creates an array of ASSStyle that
42
+ # will be used in the ASS style list.
37
43
  def convertVTTtoASS(vtt_file, font_family, font_size)
38
44
  vtt_file.lines.each do |line|
39
45
  @ass_lines.push(ASSLine.new(line.style, line.time_start, line.time_end, line.text))
40
46
  style_exists = false
41
47
  @ass_styles.each do |style|
42
- if (style.style_name == line.style) then
48
+ if (style.style_name.eql? line.style) then
43
49
  style_exists = true
44
50
  break
45
51
  end
@@ -50,6 +56,8 @@ class ASSFile
50
56
  end
51
57
  end
52
58
 
59
+ ##
60
+ # This method writes the content of the ASSFile object into a file path that is provided.
53
61
  def writeToFile(file_path)
54
62
  File.open(file_path, 'w') do |line|
55
63
  line.print "\ufeff"
@@ -83,7 +83,7 @@ class ASSLine
83
83
  end
84
84
 
85
85
  ##
86
- # The method pads text so that time numbers are a fixed number of digit.
86
+ # This method pads text so that time numbers are a fixed number of digit.
87
87
  #
88
88
  # * Requires +sep+, a string separator.
89
89
  # * Requires +input+, an integer.
@@ -20,6 +20,9 @@ class ASSStyle
20
20
  @font_size = font_size
21
21
  @style_name = style_name
22
22
  @s_params = ASSStyleParams.new(params, width, height)
23
+ if style_name.eql? 'MainTop' then
24
+ @s_params.vertical_margin = 50
25
+ end
23
26
  end
24
27
 
25
28
  ##
@@ -1,8 +1,12 @@
1
1
  ##
2
2
  # This class defines the ASS style parameters from VTT cue settings.
3
3
  class ASSStyleParams
4
- attr_reader :horizontal_margin, :vertical_margin, :alignment, :align
4
+ attr_accessor :horizontal_margin, :vertical_margin, :alignment, :align
5
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.
6
10
  def initialize(params, width, height)
7
11
  (params.split(' ').map { |p| p.split(':') }).each do |p|
8
12
  case p[0]
@@ -20,6 +24,9 @@ class ASSStyleParams
20
24
  createVerticalMargin(height)
21
25
  end
22
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".
23
30
  def createAlignment()
24
31
  if (defined?(@line) and not defined?(@position)) then
25
32
  if (defined?(@align)) then
@@ -50,6 +57,9 @@ class ASSStyleParams
50
57
  end
51
58
  end
52
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.
53
63
  def createHorizontalMargin(width)
54
64
  steps = (width / 100).to_i
55
65
  if defined?(@position) then
@@ -59,6 +69,9 @@ class ASSStyleParams
59
69
  end
60
70
  end
61
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.
62
75
  def createVerticalMargin(height)
63
76
  steps = (height / 100).to_i
64
77
  if defined?(@line) then
@@ -1,6 +1,3 @@
1
- # Imports
2
- require 'os'
3
-
4
1
  # Relative imports
5
2
  require_relative 'VTTFile'
6
3
  require_relative 'ASSFile'
@@ -13,12 +10,17 @@ class Application
13
10
  # Creates a new Application instance.
14
11
  # It receives +options+ that can define the input and output directories.
15
12
  def initialize(options)
16
- @input = options[:input] ? options[:input].gsub('\\', '/') : "./"
17
- @output = options[:output] ? options[:output].gsub('\\', '/') : "./"
13
+ @input = options[:input] ? options[:input].gsub('\\', '/').delete_suffix('/') : "."
14
+ @output = options[:output] ? options[:output].gsub('\\', '/').delete_suffix('/') : "."
18
15
  @width = 1920
19
16
  @height = 1080
20
17
  @font_family = options[:font_family] ? options[:font_family] : 'Open Sans Semibold'
21
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
+ @noout = options[:noout]
22
24
  end
23
25
 
24
26
  ##
@@ -28,18 +30,31 @@ class Application
28
30
  def start
29
31
  if File.directory?(@input) then
30
32
  Dir["#{@input}/*.vtt"].each do |file_path|
31
- vtt_to_ass(file_path).writeToFile(File.basename(file_path).gsub('.vtt', '.ass'))
33
+ convert(file_path)
32
34
  end
33
35
  elsif File.file?(@input) then
34
- vtt_to_ass(@input).writeToFile(@output + File.basename(@input).gsub('.vtt', '.ass'))
36
+ convert(@input)
35
37
  else
36
38
  puts 'Error: input file or directory does not exist.'
37
39
  end
38
40
  end
39
41
 
42
+ def convert(input_path)
43
+ ass_file = vtt_to_ass(input_path)
44
+ ass_file.writeToFile(@output + '/' + File.basename(input_path).gsub('.vtt', '.ass')) unless @noout
45
+ puts ass_file.to_s unless @quiet
46
+ end
47
+
48
+ ##
49
+ # This method creates a new VTTFile object from the file path provided and convert its content
50
+ # inside a new ASSFile object.
40
51
  def vtt_to_ass(file_path)
41
- vtt_file = VTTFile.new(file_path)
42
- ass_file = ASSFile.new(File.basename(file_path).gsub('.vtt', ''), @width, @height)
52
+ vtt_file = VTTFile.new(file_path, @width, @height)
53
+ ass_file = ASSFile.new(
54
+ (defined?(@title) ? @title : File.basename(file_path).gsub('.vtt', '')),
55
+ @width,
56
+ @height
57
+ )
43
58
  ass_file.convertVTTtoASS(vtt_file, @font_family, @font_size)
44
59
  return ass_file
45
60
  end
@@ -1,6 +1,3 @@
1
- # Imports
2
- require 'os'
3
-
4
1
  # Relative imports
5
2
  require_relative 'VTTLine'
6
3
 
@@ -9,19 +6,32 @@ require_relative 'VTTLine'
9
6
  class VTTFile
10
7
  attr_accessor :lines
11
8
 
12
- def initialize(file_path)
9
+ ##
10
+ # Creates a new VTTFile instance and assigns the default values of instance variables.
11
+ def initialize(file_path, width, height)
13
12
  @title = File.basename(file_path).gsub('.vtt', '')
14
13
  @lines = []
15
- separator = OS.posix? ? "\r\n\r\n": "\n\n"
14
+ separator = determine_line_ending(file_path) ? "\n\n" : "\r\n\r\n"
15
+ count = 0
16
16
  File.foreach(file_path, separator) do |paragraph|
17
- paragraph = paragraph.rstrip.gsub(/\r\n/, "\n")
17
+ paragraph = paragraph.rstrip.gsub(/[\r\n]/, "\n")
18
18
  if not paragraph.eql? "" then
19
- @lines.push(VTTLine.new(paragraph))
19
+ vtt_line = VTTLine.new(paragraph, width, height)
20
+ @lines.push(vtt_line)
21
+ count += 1
20
22
  end
21
23
  end
22
24
  @lines.shift
23
25
  end
24
26
 
27
+ def determine_line_ending(file_path)
28
+ File.open(file_path, 'r') do |file|
29
+ return file.readline[/\r?\n$/] == "\n"
30
+ end
31
+ end
32
+
33
+ ##
34
+ # This method writes the content of the VTTFile object into a file path that is provided.
25
35
  def writeToFile(file_path)
26
36
  File.open(file_path, 'w') do |line|
27
37
  line.print "\ufeff"
@@ -29,6 +39,8 @@ class VTTFile
29
39
  end
30
40
  end
31
41
 
42
+ ##
43
+ # This method concatenates the object data in the right order for a string output.
32
44
  def to_s
33
45
  return "WEBVTT\n\n\n" + @lines
34
46
  end
@@ -7,7 +7,7 @@ class VTTLine
7
7
  # This method creates an instance of an VTTLine.
8
8
  #
9
9
  # * Requires +paragraph+, a VTT formatted string as input.
10
- def initialize(paragraph)
10
+ def initialize(paragraph, width, height)
11
11
  lines = paragraph.split("\n")
12
12
  rx = /^([\d:.]*) --> ([\d:.]*)\s?(.*?)\s*$/
13
13
  @style = "Main"
@@ -22,7 +22,8 @@ class VTTLine
22
22
  @time_start = m[1]
23
23
  @time_end = m[2]
24
24
  @params = m[3]
25
- if @params.include? "align:middle line:7%" then
25
+ ass_style = ASSStyleParams.new(@params, width, height)
26
+ if @style.eql? 'Main' and ass_style.alignment == 8 then
26
27
  @style = "MainTop"
27
28
  end
28
29
  else
@@ -30,6 +31,8 @@ class VTTLine
30
31
  end
31
32
  count += 1;
32
33
  end
34
+
35
+ @text = @text.lstrip
33
36
  end
34
37
 
35
38
  ##
@@ -1,3 +1,8 @@
1
+ ##
2
+ # Vtt2ass module to provide the version number
1
3
  module Vtt2ass
2
- VERSION = "0.2.8"
4
+ ##
5
+ # This is the version of the application.
6
+ # This needs to be changed for each gem release.
7
+ VERSION = "0.2.13"
3
8
  end
data/vtt2ass.gemspec CHANGED
@@ -25,10 +25,10 @@ Gem::Specification.new do |spec|
25
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
26
  spec.require_paths = ["lib"]
27
27
 
28
- spec.add_dependency 'os'
29
- spec.add_dependency 'htmlentities'
28
+ spec.add_dependency 'htmlentities', '~> 4.3'
29
+ spec.add_dependency 'tty-option', '~> 0.1'
30
30
 
31
- spec.add_development_dependency 'rake'
32
- spec.add_development_dependency 'minitest'
33
- spec.add_development_dependency 'yard'
31
+ spec.add_development_dependency 'rake', '~> 12.0'
32
+ spec.add_development_dependency 'minitest', '~> 5.0'
33
+ spec.add_development_dependency 'yard', '~> 0.9'
34
34
  end
metadata CHANGED
@@ -1,85 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vtt2ass
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.8
4
+ version: 0.2.13
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: 2021-03-21 00:00:00.000000000 Z
11
+ date: 2021-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: os
14
+ name: htmlentities
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '4.3'
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: '0'
26
+ version: '4.3'
27
27
  - !ruby/object:Gem::Dependency
28
- name: htmlentities
28
+ name: tty-option
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '0.1'
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: '0'
40
+ version: '0.1'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '12.0'
48
48
  type: :development
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: '0'
54
+ version: '12.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: minitest
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '5.0'
62
62
  type: :development
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: '0'
68
+ version: '5.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: yard
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '0.9'
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: '0'
82
+ version: '0.9'
83
83
  description:
84
84
  email:
85
85
  - timemaster.lpf@gmail.com
@@ -97,9 +97,13 @@ files:
97
97
  - bin/run
98
98
  - bin/setup
99
99
  - doc/ASSFile.html
100
+ - doc/ASSLine.html
100
101
  - doc/ASSStyle.html
102
+ - doc/ASSStyleParams.html
101
103
  - doc/ASSSubtitle.html
102
104
  - doc/Application.html
105
+ - doc/VTTFile.html
106
+ - doc/VTTLine.html
103
107
  - doc/VTTSubtitle.html
104
108
  - doc/Vtt2ass.html
105
109
  - doc/Vtt2ass/Error.html