vtt2ass 0.2.1 → 0.2.7

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: b13c0f4e714b058d076bddda1685ba4007429a2c9c0dc065073926bee9dd2dad
4
- data.tar.gz: acbfd744b30cd214f174ec4fe991a6983cb206b89a65956115be803cf005b22c
3
+ metadata.gz: 9fe71574454d7bf315cb1de1c25ceb478e98fa0676f30e55a4e97b9522edfca9
4
+ data.tar.gz: d6380d5ee7e0f9e3341636cc266c43daea659724de180ee854811d243efd6348
5
5
  SHA512:
6
- metadata.gz: 99c2d00e1d03c7e8ae463266ea500ad0ebf10f0b7eeae972b4d2776887a1a0936f5707633832c26fc6bc66fdd13e0bd53ff73200c2f5ae128517266a29d46a31
7
- data.tar.gz: 17d541540f391fe95e5aeea3d0795ee36b5856f1cc6d69de4bcf6ac59b7a647e1cc3509e57b291a80c0a753b058a01d291944e435a9dd917358a99c5f69ed574
6
+ metadata.gz: a4a0ce576c898b8a69467dbfc92481017ebb1d467377c7772ca52b05d72aebe14cd1ea2ac84ef3ad2898cb00defd4bde7104372de7e49a1aece6ab5072d1f7ec
7
+ data.tar.gz: 72c4f381475ad497ee697bbedc5d8c54864c4192a780ea7da32a9ebe5752a0b3c4b3f5463aa6486682e7baaa65dafed9ae7fe9439e8b45506e40407a4d60cd88
data/.gitignore CHANGED
@@ -1,6 +1,9 @@
1
1
  # Lock file
2
2
  Gemfile.lock
3
3
 
4
+ # gems
5
+ /*.gem
6
+
4
7
  # Temporary files for yard documentation
5
8
  .yardoc/
6
9
 
data/.gitlab-ci.yml CHANGED
@@ -14,18 +14,16 @@ test:
14
14
  build:
15
15
  stage: build
16
16
  only:
17
- - master
17
+ - develop
18
18
  artifacts:
19
19
  untracked: true
20
20
  script:
21
- - mkdir build
22
- - gem build vtt2ass.gemspec -o "build/release.gem"
21
+ - gem build vtt2ass.gemspec
23
22
 
24
23
  deploy:
25
24
  stage: deploy
26
25
  only:
27
26
  - master
28
- dependencies:
29
- - build
30
27
  script:
31
- - gem push build/release.gem -k rubygems_b54a36e70dba06b9a9c7268807eb2bbb896cdba924c67289
28
+ - gem install dpl --pre
29
+ - dpl rubygems --api_key $K8S_SECRET_RUBYGEMS_API_KEY
data/Gemfile CHANGED
@@ -4,6 +4,7 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  gem 'os'
7
+ gem 'htmlentities'
7
8
  gem 'yard'
8
9
  gem "rake", "~> 12.0"
9
10
  gem "minitest", "~> 5.0"
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # VTT to ASS
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/vtt2ass.svg)](https://badge.fury.io/rb/vtt2ass)
4
+
3
5
  This is a simple application to convert VTT files to ASS subtitles.
4
6
 
5
7
  ## Requirements
@@ -36,7 +38,15 @@ $ vtt2ass -h
36
38
  Usage: vtt2ass [options]
37
39
 
38
40
  Specific options:
39
- -i, --input DIRECTORY Specify a custom input directory (default: './input')
40
- -o, --output DIRECTORY Specify a custom output directory (default: './output')
41
- -s, --font-size SIZE Specify a font size for the subtitles (default: 72)
41
+ -i, --input PATH Specify a custom input file or directory (default: './')
42
+ -o, --output PATH Specify a custom output directory (default: './')
43
+ -f, --font-family FONT Specify a font family for the subtitles (default: 'Open Sans Semibold')
44
+ -s, --font-size SIZE Specify a font size for the subtitles (default: 52)
45
+ -v, --version Show version
42
46
  ```
47
+
48
+ # Donate
49
+
50
+ If you want to support me, consider buying me a coffee.
51
+
52
+ [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Y8Y136P0E)
data/lib/vtt2ass.rb CHANGED
@@ -17,14 +17,17 @@ module Vtt2ass
17
17
  opts.banner = "Usage: vtt2ass [options]"
18
18
  opts.separator ""
19
19
  opts.separator "Specific options:"
20
- opts.on("-i", "--input DIRECTORY", "Specify a custom input directory (default: './input')") do |dir|
21
- options[:input] = dir
20
+ opts.on("-i", "--input PATH", "Specify a custom input file or directory (default: './')") do |file_path|
21
+ options[:input] = file_path
22
22
  end
23
- opts.on("-o", "--output DIRECTORY", "Specify a custom output directory (default: './output')") do |dir|
24
- options[:output] = dir
23
+ opts.on("-o", "--output PATH", "Specify a custom output directory (default: './')") do |file_path|
24
+ options[:output] = file_path
25
25
  end
26
- opts.on("-s", "--font-size SIZE", Integer, "Specify a font size for the subtitles (default: 72)") do |size|
27
- options[:font_size] = size
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
28
31
  end
29
32
  opts.on("-v", "--version", "Show version") do
30
33
  puts Vtt2ass::VERSION
@@ -1,20 +1,19 @@
1
+ # Relative imports
2
+ require_relative 'ASSLine'
3
+ require_relative 'ASSStyle'
4
+
1
5
  ##
2
- # This class defines the ASS File that will be created from the conversion.
6
+ # This class defines an ASS subtitle file.
3
7
  class ASSFile
8
+ attr_reader :title, :width, :height
9
+ attr_accessor :ass_styles, :ass_lines
4
10
 
5
- ##
6
- # This method creates an instance of the ASSFile.
7
- #
8
- # * Requires +ass_styles+, a list of ASSStyle as input.
9
- # * Requires +ass_subs+, a list of ASSSubtitles as input.
10
- # * Requires a video +width+ as input.
11
- # * Requires a video +height+ as input.
12
- def initialize(ass_styles, ass_subs, width, height)
11
+ def initialize(title, width, height)
13
12
  @width = width
14
13
  @height = height
15
14
  @header = [
16
15
  '[Script Info]',
17
- 'Title: DKB Team',
16
+ "Title: #{title}",
18
17
  'ScriptType: v4.00+',
19
18
  'Collisions: Normal',
20
19
  'PlayDepth: 0',
@@ -26,18 +25,41 @@ class ASSFile
26
25
  '[V4+ Styles]',
27
26
  'Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding'
28
27
  ]
29
- @ass_styles = ass_styles
30
28
  @events = [
31
29
  '',
32
30
  '[Events]',
33
31
  'Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text'
34
32
  ]
35
- @ass_subs = ass_subs
33
+ @ass_styles = []
34
+ @ass_lines = []
35
+ end
36
+
37
+ def convertVTTtoASS(vtt_file, font_family, font_size)
38
+ vtt_file.lines.each do |line|
39
+ @ass_lines.push(ASSLine.new(line.style, line.time_start, line.time_end, line.text))
40
+ style_exists = false
41
+ @ass_styles.each do |style|
42
+ if (style.style_name == line.style) then
43
+ style_exists = true
44
+ break
45
+ end
46
+ end
47
+ if not style_exists then
48
+ @ass_styles.push(ASSStyle.new(line.style, line.params, font_family, font_size, @width, @height))
49
+ end
50
+ end
51
+ end
52
+
53
+ def writeToFile(file_path)
54
+ File.open(file_path, 'w') do |line|
55
+ line.print "\ufeff"
56
+ line.puts self.to_s
57
+ end
36
58
  end
37
59
 
38
60
  ##
39
61
  # This method concatenates the object data in the right order for a string output.
40
62
  def to_s
41
- return @header + @ass_styles + @events + @ass_subs
63
+ return @header + @ass_styles + @events + @ass_lines
42
64
  end
43
65
  end
@@ -1,20 +1,21 @@
1
+ require 'htmlentities'
2
+
1
3
  ##
2
4
  # This class defines an ASS subtile line.
3
- class ASSSubtitle
4
- attr_reader :style, :time_start, :time_end, :params, :text
5
+ class ASSLine
6
+ attr_reader :style, :time_start, :time_end, :text
5
7
 
6
8
  ##
7
- # This method creates an instance of an ASSSubtitle.
9
+ # This method creates an instance of an ASSLine.
8
10
  #
9
11
  # * Requires a +style+ name as input.
10
12
  # * Requires +time_start+, a VTT formatted timestamp as input.
11
13
  # * Requires +time_start+, a VTT formatted timestamp as input.
12
14
  # * Requires +text+, a VTT formatted string as input.
13
- def initialize(style, time_start, time_end, params, text)
15
+ def initialize(style, time_start, time_end, text)
14
16
  @style = style
15
17
  @time_start = convertTime(time_start)
16
18
  @time_end = convertTime(time_end)
17
- @params = params
18
19
  @text = convertToAssText(text)
19
20
  end
20
21
 
@@ -29,6 +30,7 @@ class ASSSubtitle
29
30
  #
30
31
  # * Requires +text+, a string of VTT formated text as input.
31
32
  def convertToAssText(text)
33
+ decoder = HTMLEntities.new()
32
34
  text = text
33
35
  .gsub(/\r/, '')
34
36
  .gsub(/\n/, '\\N')
@@ -43,7 +45,7 @@ class ASSSubtitle
43
45
  .gsub(/<[^>]>/, '')
44
46
  .gsub(/\\N$/, '')
45
47
  .gsub(/ +$/, '')
46
- return text
48
+ return decoder.decode(text)
47
49
  end
48
50
 
49
51
  ##
@@ -1,3 +1,6 @@
1
+ # Relative imports
2
+ require_relative 'ASSStyleParams'
3
+
1
4
  ##
2
5
  # This class defines an ASS style that can be applied on a subtitle line.
3
6
  class ASSStyle
@@ -10,54 +13,18 @@ class ASSStyle
10
13
  # * Requires +params+, a string of VTT styling as input.
11
14
  # * Requires a video +width+ as input.
12
15
  # * Requires a video +height+ as input.
13
- def initialize(style_name, params, font_size, width, height)
16
+ def initialize(style_name, params, font_family, font_size, width, height)
14
17
  @width = width
15
18
  @height = height
19
+ @font_family = font_family
16
20
  @font_size = font_size
17
21
  @style_name = style_name
18
- assignParams(params)
22
+ @s_params = ASSStyleParams.new(params, width, height)
19
23
  end
20
24
 
21
- ##
22
- # This method converts the string of VTT styling in values used for ASS styling.
23
- #
24
- # * Requires +params+, a string of VTT styling as input.
25
- def assignParams(params)
26
- @alignment = "2"
27
- @left_margin = "10"
28
- @right_margin = "10"
29
- @vertical_margin = "50"
30
-
31
- if params.include? "align:middle line:7%" then
32
- @style_name = "MainTop"
33
- @vertical_margin = "30"
34
- @alignment = "8"
35
- else
36
- param_count = 0
37
- (params.split(' ').map { |p| p.split(':') }).each do |p|
38
- case p[0]
39
- when "position"
40
- @left_margin = (@width * ((p[1].gsub(/%/, '').to_f - 7) / 100)).to_i.to_s
41
- when "align"
42
- case p[1]
43
- when "left"
44
- @alignment = 1
45
- when "middle"
46
- @alignment = 2
47
- when "right"
48
- @alignment = 3
49
- end
50
- when "line"
51
- @vertical_margin = (@height - (@height * ((p[1].gsub(/%/, '').to_f + 7) / 100))).to_i.to_s
52
- end
53
- param_count += 1
54
- end
55
- end
56
- end
57
-
58
25
  ##
59
26
  # This method assigns the object values to an ASS style line and outputs it.
60
27
  def to_s
61
- return "Style: #{@style_name},Open Sans Semibold,#{@font_size},&H00FFFFFF,&H000000FF,&H00020713,&H00000000,-1,0,0,0,100,100,0,0,1,2.0,2.0,#{@alignment},#{@left_margin},#{@right_margin},#{@vertical_margin},1"
28
+ return "Style: #{@style_name},#{@font_family},#{@font_size},&H00FFFFFF,&H000000FF,&H00020713,&H00000000,-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"
62
29
  end
63
30
  end
@@ -0,0 +1,74 @@
1
+ ##
2
+ # This class defines the ASS style parameters from VTT cue settings.
3
+ class ASSStyleParams
4
+ attr_reader :horizontal_margin, :vertical_margin, :alignment, :align
5
+
6
+ def initialize(params, width, height)
7
+ (params.split(' ').map { |p| p.split(':') }).each do |p|
8
+ case p[0]
9
+ when 'position'
10
+ @position = p[1].gsub(/%/, '').to_i
11
+ when 'line'
12
+ @line = p[1].gsub(/%/, '').to_i
13
+ @line = @line == -1 ? 100 : @line;
14
+ when 'align'
15
+ @align = p[1].chomp
16
+ end
17
+ end
18
+ createAlignment()
19
+ createHorizontalMargin(width)
20
+ createVerticalMargin(height)
21
+ end
22
+
23
+ def createAlignment()
24
+ if (defined?(@line) and not defined?(@position)) then
25
+ if (defined?(@align)) then
26
+ case @align
27
+ when 'left', 'start'
28
+ @alignment = @line >= 50 ? 1 : 7
29
+ when 'right', 'end'
30
+ @alignment = @line >= 50 ? 3 : 9
31
+ when 'center', 'middle'
32
+ @alignment = @line >= 50 ? 2 : 8
33
+ end
34
+ else
35
+ @alignment = @line >= 50 ? 2 : 8 # If position is higher than 50% align to bottom center, else align to top center
36
+ end
37
+ elsif (defined?(@line) and defined?(@position)) then
38
+ @alignment = 1
39
+ else
40
+ case @align
41
+ when 'left', 'start'
42
+ @alignment = 1
43
+ when 'right', 'end'
44
+ @alignment = 3
45
+ when 'center', 'middle'
46
+ @alignment = 2
47
+ else
48
+ @alignment = 2
49
+ end
50
+ end
51
+ end
52
+
53
+ def createHorizontalMargin(width)
54
+ steps = (width / 100).to_i
55
+ if defined?(@position) then
56
+ @horizontal_margin = @position * steps
57
+ else
58
+ @horizontal_margin = 0
59
+ end
60
+ end
61
+
62
+ def createVerticalMargin(height)
63
+ steps = (height / 100).to_i
64
+ if defined?(@line) then
65
+ if (@alignment == 1) then
66
+ @vertical_margin = (100 - @line) * steps
67
+ else
68
+ @vertical_margin = @line >= 50 ? (100 - @line) * steps : @line * steps
69
+ end
70
+ else
71
+ @vertical_margin = 50
72
+ end
73
+ end
74
+ end
@@ -1,11 +1,8 @@
1
1
  # Imports
2
2
  require 'os'
3
- require 'fileutils'
4
3
 
5
4
  # Relative imports
6
- require_relative 'VTTSubtitle'
7
- require_relative 'ASSSubtitle'
8
- require_relative 'ASSStyle'
5
+ require_relative 'VTTFile'
9
6
  require_relative 'ASSFile'
10
7
 
11
8
  ##
@@ -16,11 +13,12 @@ class Application
16
13
  # Creates a new Application instance.
17
14
  # It receives +options+ that can define the input and output directories.
18
15
  def initialize(options)
19
- @input_dir = options[:input] ? options[:input]: "./input"
20
- @output_dir = options[:output] ? options[:output]: "./output"
16
+ @input = options[:input] ? options[:input].gsub('\\', '/') : "./"
17
+ @output = options[:output] ? options[:output].gsub('\\', '/') : "./"
21
18
  @width = 1920
22
19
  @height = 1080
23
- @font_size = options[:font_size] ? options[:font_size] : 72
20
+ @font_family = options[:font_family] ? options[:font_family] : 'Open Sans Semibold'
21
+ @font_size = options[:font_size] ? options[:font_size] : 52
24
22
  end
25
23
 
26
24
  ##
@@ -28,55 +26,22 @@ class Application
28
26
  # It sends the file_paths of VTT files in the input directory to convertFileToASS method
29
27
  # and outputs the resulting ASS format to a new file.
30
28
  def start
31
- Dir["#{@input_dir}/*.vtt"].each do |file_path|
32
- file_name = File.basename(file_path).gsub('.vtt', '.ass')
33
- FileUtils.mkdir_p @output_dir
34
- File.open("#{@output_dir}/" + file_name, 'w') do |line|
35
- line.print "\ufeff"
36
- line.puts convertFileToASS(file_path)
29
+ if File.directory?(@input) then
30
+ Dir["#{@input}/*.vtt"].each do |file_path|
31
+ vtt_to_ass(file_path).writeToFile(File.basename(file_path).gsub('.vtt', '.ass'))
37
32
  end
33
+ elsif File.file?(@input) then
34
+ vtt_to_ass(@input).writeToFile(@output + File.basename(@input).gsub('.vtt', '.ass'))
35
+ else
36
+ puts 'Error: input file or directory does not exist.'
38
37
  end
39
38
  end
40
39
 
41
- ##
42
- # This method reads the VTT file and sends back a list of paragraphs.
43
- # It requires a +file_path+ as input.
44
- # It outputs a list named list_paragraph.
45
- def readVTTFile(file_path)
46
- list_parapraph = []
47
- separator = OS.linux? ? "\r\n\r\n": "\n\n"
48
- File.foreach(file_path, separator) do |paragraph|
49
- paragraph = paragraph.rstrip.gsub(/\r\n/, "\n")
50
- if not paragraph.eql? "" then
51
- list_parapraph.push(VTTSubtitle.new(paragraph))
52
- end
53
- end
54
- list_parapraph.shift
55
- return list_parapraph
40
+ 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)
43
+ ass_file.convertVTTtoASS(vtt_file, @font_family, @font_size)
44
+ return ass_file
56
45
  end
57
46
 
58
- ##
59
- # This method gets the list of paragraphs from the VTT file and creates lists of ASSSubtitle and ASSStyles objects from them.
60
- # Those lists are given a new ASSFile object to generate the file content.
61
- # It requires a +file_path+ as input.
62
- # It outputs an ASSFile object.
63
- def convertFileToASS(file_path)
64
- vtt_subs = readVTTFile(file_path)
65
- ass_subs = []
66
- ass_styles = []
67
- vtt_subs.each do |sub|
68
- ass_subs.push(ASSSubtitle.new(sub.style, sub.time_start, sub.time_end, sub.params, sub.text))
69
- style_exists = false
70
- ass_styles.each do |style|
71
- if (style.style_name == sub.style) then
72
- style_exists = true
73
- break
74
- end
75
- end
76
- if not style_exists then
77
- ass_styles.push(ASSStyle.new(sub.style, sub.params, @font_size, @width, @height))
78
- end
79
- end
80
- return ASSFile.new(ass_styles, ass_subs, @width, @height).to_s
81
- end
82
47
  end
@@ -0,0 +1,36 @@
1
+ # Imports
2
+ require 'os'
3
+
4
+ # Relative imports
5
+ require_relative 'VTTLine'
6
+
7
+ ##
8
+ # This class defines a VTT subtile file.
9
+ class VTTFile
10
+ attr_accessor :lines
11
+
12
+ def initialize(file_path)
13
+ @title = File.basename(file_path).gsub('.vtt', '')
14
+ @lines = []
15
+ separator = OS.posix? ? "\r\n\r\n": "\n\n"
16
+ File.foreach(file_path, separator) do |paragraph|
17
+ paragraph = paragraph.rstrip.gsub(/\r\n/, "\n")
18
+ if not paragraph.eql? "" then
19
+ @lines.push(VTTLine.new(paragraph))
20
+ end
21
+ end
22
+ @lines.shift
23
+ end
24
+
25
+ def writeToFile(file_path)
26
+ File.open(file_path, 'w') do |line|
27
+ line.print "\ufeff"
28
+ line.puts self.to_s
29
+ end
30
+ end
31
+
32
+ def to_s
33
+ return "WEBVTT\n\n\n" + @lines
34
+ end
35
+
36
+ end
@@ -1,10 +1,10 @@
1
1
  ##
2
2
  # This class defines a VTT subtile line.
3
- class VTTSubtitle
3
+ class VTTLine
4
4
  attr_reader :style, :time_start, :time_end, :params, :text
5
5
 
6
6
  ##
7
- # This method creates an instance of an VTTSubtitle.
7
+ # This method creates an instance of an VTTLine.
8
8
  #
9
9
  # * Requires +paragraph+, a VTT formatted string as input.
10
10
  def initialize(paragraph)
@@ -1,3 +1,3 @@
1
1
  module Vtt2ass
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.7"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vtt2ass
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.7
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-01-16 00:00:00.000000000 Z
11
+ date: 2021-03-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -50,10 +50,12 @@ files:
50
50
  - exe/vtt2ass
51
51
  - lib/vtt2ass.rb
52
52
  - lib/vtt2ass/ASSFile.rb
53
+ - lib/vtt2ass/ASSLine.rb
53
54
  - lib/vtt2ass/ASSStyle.rb
54
- - lib/vtt2ass/ASSSubtitle.rb
55
+ - lib/vtt2ass/ASSStyleParams.rb
55
56
  - lib/vtt2ass/Application.rb
56
- - lib/vtt2ass/VTTSubtitle.rb
57
+ - lib/vtt2ass/VTTFile.rb
58
+ - lib/vtt2ass/VTTLine.rb
57
59
  - lib/vtt2ass/version.rb
58
60
  - vtt2ass.gemspec
59
61
  homepage: https://gitlab.com/dkb-weeblets/vtt2ass