captions 1.2.2 → 1.3.0

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
  SHA1:
3
- metadata.gz: bc2fd7159d9f46c3251b271226828af0370c6c72
4
- data.tar.gz: b87491508efc86cc0b403d76ce98aebaf91aaa2f
3
+ metadata.gz: aabb7f8d8e05f0bdd97f11c7d3d6ad2272daa4a8
4
+ data.tar.gz: 2487803e670a82b5280cbe710d8b1f53aeb7ad7d
5
5
  SHA512:
6
- metadata.gz: 6cd1fa878ad14fa718323d7191da8cb82f44b99feb15aa67987fdb55a8d25136fe2d4bf1a316109011bfec7b4260ce28906e1c2129f667d7e3ff8f5eb093325f
7
- data.tar.gz: e4e09a6c34efcfe00892c956decd8c803b786f7afde0f0764c23976d01826871b47d82fe540cfee44181ebb93cacb66cb5bdca91aa8fa83adb8e949ee708986c
6
+ metadata.gz: 247cbaedb31a2c5afc6d987b9521a62ef11e7c40460d1a5831093e00f1308ef682e86ee68832695110f85452dd3365fbdf3ea1d76219147b18838b0dd8812d22
7
+ data.tar.gz: ad8c0e97e9fb83e97facabfd17058427368672aa5ac2aa79f9f3b5908b5cf2c9e1e23c9a84c5e2ac8e3369e4e527144c6ab557e82126f15eb5cca828657cbe59
@@ -1,14 +1,14 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "captions"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "captions"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -1,27 +1,27 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'captions/version'
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = "captions"
8
- spec.version = Captions::VERSION
9
- spec.authors = ["navin"]
10
- spec.email = ["navin@amagi.com"]
11
-
12
- spec.summary = %q{Subtitle Editor and Converter written in Ruby}
13
- spec.description = %q{Subtitle Editor and Converter written in Ruby. Captions can read/modify/export subtitles from one format to another }
14
- spec.homepage = "https://github.com/navinre/captions"
15
- spec.license = "MIT"
16
-
17
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
- f.match(%r{^(test|spec|features)/})
19
- end
20
- spec.bindir = "exe"
21
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
- spec.require_paths = ["lib"]
23
-
24
- spec.add_development_dependency "rspec"
25
- spec.add_development_dependency "bundler", "~> 1.13"
26
- spec.add_development_dependency "rake", "~> 10.0"
27
- end
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'captions/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "captions"
8
+ spec.version = Captions::VERSION
9
+ spec.authors = ["navin"]
10
+ spec.email = ["navin@amagi.com"]
11
+
12
+ spec.summary = %q{Subtitle Editor and Converter written in Ruby}
13
+ spec.description = %q{Subtitle Editor and Converter written in Ruby. Captions can read/modify/export subtitles from one format to another }
14
+ spec.homepage = "https://github.com/navinre/captions"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "rspec"
25
+ spec.add_development_dependency "bundler", "~> 1.13"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ end
@@ -170,9 +170,9 @@ module Captions
170
170
  # block is passed, it returns the entire cuelist.
171
171
  def fetch_result(&block)
172
172
  if block_given?
173
- @cue_list.select(&block)
173
+ return @cue_list.select(&block)
174
174
  else
175
- @cue_list
175
+ return @cue_list
176
176
  end
177
177
  end
178
178
  end
@@ -1,66 +1,93 @@
1
- module Captions
2
- class Cue
3
- include Util
4
-
5
- attr_accessor :number, :start_time, :end_time, :duration, :text, :property
6
-
7
- # Creates a new Cue class
8
- # Each cue denotes a subtitle.
9
- def initialize
10
- self.text = nil
11
- self.start_time = nil
12
- self.end_time = nil
13
- self.duration = nil
14
- self.number = nil
15
- self.property = {}
16
- end
17
-
18
- # Sets the time for the cue. Both start-time and
19
- # end-time can be passed together. This just assigns
20
- # the value passed.
21
- def set_time(start_time, end_time, duration = nil)
22
- self.start_time = start_time
23
- self.end_time = end_time
24
- self.duration = duration
25
- end
26
-
27
- # Serializes the values set for the cue.
28
- # Converts start-time, end-time and duration to milliseconds
29
- # If duration is not found, it will be calculated based on
30
- # start-time and end-time.
31
- def serialize(fps)
32
- raise InvalidSubtitle, "Subtitle should have start time" if self.start_time.nil?
33
- raise InvalidSubtitle, "Subtitle shold have end time" if self.end_time.nil?
34
-
35
- begin
36
- ms_per_frame = (1000.0 / fps)
37
- self.start_time = convert_to_msec(self.start_time, ms_per_frame)
38
- self.end_time = convert_to_msec(self.end_time, ms_per_frame)
39
- if duration.nil?
40
- self.duration = self.end_time - self.start_time
41
- else
42
- self.duration = convert_to_msec(self.duration, ms_per_frame)
43
- end
44
- rescue
45
- raise InvalidSubtitle, "Cannot calculate start-time or end-time"
46
- end
47
- end
48
-
49
- # Changes start-time, end-time and duration based on new frame-rate
50
- def change_frame_rate(old_rate, new_rate)
51
- self.start_time = convert_frame_rate(self.start_time, old_rate, new_rate)
52
- self.end_time = convert_frame_rate(self.end_time, old_rate, new_rate)
53
- self.duration = convert_frame_rate(self.duration, old_rate, new_rate)
54
- end
55
-
56
- # Adds text. If text is already found, new-line is appended.
57
- def add_text(text)
58
- if self.text.nil?
59
- self.text = text
60
- else
61
- self.text += "\n" + text
62
- end
63
- end
64
-
65
- end
66
- end
1
+ module Captions
2
+ class Cue
3
+ include Util
4
+
5
+ # Text Properties supported
6
+ ALIGNMENT = "alignment"
7
+ COLOR = "color"
8
+ POSITION = "position"
9
+
10
+ # List of Text Properties
11
+ TEXT_PROPERTIES = [ALIGNMENT, COLOR, POSITION]
12
+
13
+ attr_accessor :number, :start_time, :end_time, :duration, :text, :properties
14
+
15
+ # Creates a new Cue class
16
+ # Each cue denotes a subtitle.
17
+ def initialize
18
+ self.text = nil
19
+ self.start_time = nil
20
+ self.end_time = nil
21
+ self.duration = nil
22
+ self.number = nil
23
+ self.properties = {}
24
+ end
25
+
26
+ # Sets the time for the cue. Both start-time and
27
+ # end-time can be passed together. This just assigns
28
+ # the value passed.
29
+ def set_time(start_time, end_time, duration = nil)
30
+ self.start_time = start_time
31
+ self.end_time = end_time
32
+ self.duration = duration
33
+ end
34
+
35
+ # Getter and Setter methods for Text Properties
36
+ # These are pre-defined properties. This is just to assign
37
+ # or access the properties of that text.
38
+ TEXT_PROPERTIES.each do |setting|
39
+ define_method :"#{setting}" do
40
+ if self.properties[setting].present?
41
+ return self.properties[setting]
42
+ end
43
+ return nil
44
+ end
45
+
46
+ define_method :"#{setting}=" do |value|
47
+ self.properties[setting] = value
48
+ end
49
+ end
50
+
51
+ # Serializes the values set for the cue.
52
+ # Converts start-time, end-time and duration to milliseconds
53
+ # If duration is not found, it will be calculated based on
54
+ # start-time and end-time.
55
+ def serialize(fps)
56
+ raise InvalidSubtitle, "Subtitle should have start time" if self.start_time.nil?
57
+ raise InvalidSubtitle, "Subtitle shold have end time" if self.end_time.nil?
58
+
59
+ begin
60
+ ms_per_frame = (1000.0 / fps)
61
+ self.start_time = convert_to_msec(self.start_time, ms_per_frame)
62
+ self.end_time = convert_to_msec(self.end_time, ms_per_frame)
63
+ if duration.nil?
64
+ self.duration = self.end_time - self.start_time
65
+ else
66
+ self.duration = convert_to_msec(self.duration, ms_per_frame)
67
+ end
68
+ rescue
69
+ raise InvalidSubtitle, "Cannot calculate start-time or end-time"
70
+ end
71
+ end
72
+
73
+ # Changes start-time, end-time and duration based on new frame-rate
74
+ def change_frame_rate(old_rate, new_rate)
75
+ self.start_time = convert_frame_rate(self.start_time, old_rate, new_rate)
76
+ self.end_time = convert_frame_rate(self.end_time, old_rate, new_rate)
77
+ self.duration = convert_frame_rate(self.duration, old_rate, new_rate)
78
+ end
79
+
80
+ # Adds text. If text is already found, new-line is appended.
81
+ def add_text(text)
82
+ if self.text.nil?
83
+ self.text = text
84
+ else
85
+ self.text += "\n" + text
86
+ end
87
+ end
88
+
89
+ def <=>(other_cue)
90
+ self.start_time <=> other_cue.start_time
91
+ end
92
+ end
93
+ end
@@ -1,75 +1,121 @@
1
- module Captions
2
- class VTT < Base
3
-
4
- # Header used for all VTT files
5
- VTT_HEADER = "WEBVTT"
6
-
7
- # VTT file comments/style section
8
- VTT_METADATA = /^NOTE|^STYLE/
9
-
10
- # Parse VTT file and update CueList
11
- def parse
12
- base_parser do
13
- count = 1
14
- cue_count = 0
15
- meta_data_section = false
16
- cue = nil
17
- raise InvalidSubtitle, "Invalid VTT Signature" unless validate_header(@file.gets)
18
- while(line = @file.gets) do
19
- line = line.strip
20
- if line.empty?
21
- meta_data_section = false
22
- elsif is_meta_data?(line)
23
- meta_data_section = true
24
- elsif is_time?(line)
25
- @cue_list.append(cue) if cue
26
- cue_count += 1
27
- cue = Cue.new
28
- cue.number = cue_count
29
- line = line.split
30
- cue.set_time(line[0], line[2])
31
- elsif !meta_data_section and is_text?(line)
32
- cue.add_text(line)
33
- end
34
- end
35
- @cue_list.append(cue) if cue
36
- end
37
- end
38
-
39
- # Export CueList to VTT file
40
- def dump(file)
41
- base_dump(file) do |file|
42
- file.write(VTT_HEADER)
43
- @cue_list.each do |cue|
44
- file.write("\n\n")
45
- file.write(msec_to_timecode(cue.start_time))
46
- file.write(" --> ")
47
- file.write(msec_to_timecode(cue.end_time))
48
- file.write("\n")
49
- file.write(cue.text)
50
- end
51
- end
52
- end
53
-
54
- # Check whether its a VTT_HEADER or not
55
- def validate_header(line)
56
- !!line.strip.match(/^#{VTT_HEADER}/)
57
- end
58
-
59
- # Check whether its a meta-data or not
60
- def is_meta_data?(text)
61
- !!text.match(VTT_METADATA)
62
- end
63
-
64
- # Timecode format used in VTT file
65
- def is_time?(text)
66
- !!text.match(/^(\d{2}:)?\d{2}:\d{2}.\d{3}.*(\d{2}:)?\d{2}:\d{2}.\d{3}/)
67
- end
68
-
69
- # Check whether if its subtilte text or not
70
- def is_text?(text)
71
- !text.empty? and text.is_a?(String) and text != VTT_HEADER
72
- end
73
-
74
- end
75
- end
1
+ module Captions
2
+ class VTT < Base
3
+
4
+ # Header used for all VTT files
5
+ VTT_HEADER = "WEBVTT"
6
+
7
+ # VTT file comments/style section
8
+ VTT_METADATA = /^NOTE|^STYLE/
9
+
10
+ # Auto Keyword used in Alignment
11
+ AUTO_KEYWORD = "auto"
12
+
13
+ # Alignment Data
14
+ ALIGNMENT_VALUES = {
15
+ "middle" => "middle",
16
+ "left" => "left",
17
+ "right" => "right",
18
+ "start" => "start",
19
+ "end" => "end",
20
+ }
21
+
22
+ # Parse VTT file and update CueList
23
+ def parse
24
+ base_parser do
25
+ count = 1
26
+ cue_count = 0
27
+ meta_data_section = false
28
+ cue = nil
29
+ raise InvalidSubtitle, "Invalid VTT Signature" unless validate_header(@file.gets)
30
+ while(line = @file.gets) do
31
+ line = line.strip
32
+ if line.empty?
33
+ meta_data_section = false
34
+ elsif is_meta_data?(line)
35
+ meta_data_section = true
36
+ elsif is_time?(line)
37
+ @cue_list.append(cue) if cue
38
+ cue_count += 1
39
+ cue = Cue.new
40
+ cue.number = cue_count
41
+ line = line.split
42
+ cue.set_time(line[0], line[2])
43
+ set_properties(cue, line[3..-1])
44
+ elsif !meta_data_section and is_text?(line)
45
+ cue.add_text(line)
46
+ end
47
+ end
48
+ @cue_list.append(cue) if cue
49
+ end
50
+ end
51
+
52
+ # Export CueList to VTT file
53
+ def dump(file)
54
+ base_dump(file) do |file|
55
+ file.write(VTT_HEADER)
56
+ @cue_list.each do |cue|
57
+ file.write("\n\n")
58
+ file.write(msec_to_timecode(cue.start_time))
59
+ file.write(" --> ")
60
+ file.write(msec_to_timecode(cue.end_time))
61
+ file.write("\n")
62
+ file.write(cue.text)
63
+ end
64
+ end
65
+ end
66
+
67
+ # Check whether its a VTT_HEADER or not
68
+ def validate_header(line)
69
+ !!line.strip.match(/^#{VTT_HEADER}/)
70
+ end
71
+
72
+ # Check whether its a meta-data or not
73
+ def is_meta_data?(text)
74
+ !!text.match(VTT_METADATA)
75
+ end
76
+
77
+ # Timecode format used in VTT file
78
+ def is_time?(text)
79
+ !!text.match(/^(\d{2}:)?\d{2}:\d{2}.\d{3}.*(\d{2}:)?\d{2}:\d{2}.\d{3}/)
80
+ end
81
+
82
+ # Check whether if its subtilte text or not
83
+ def is_text?(text)
84
+ !text.empty? and text.is_a?(String) and text != VTT_HEADER
85
+ end
86
+
87
+ def set_properties(cue, properties)
88
+ properties.each do |prop|
89
+ prop, value = prop.split(":")
90
+ value.gsub!("%","")
91
+ case prop
92
+ when "align"
93
+ cue.alignment = get_alignment(value)
94
+ when "line"
95
+ value = value.split(",")[0]
96
+ cue.position = get_line(value)
97
+ end
98
+ end
99
+ end
100
+
101
+ def get_alignment(value)
102
+ raise InvalidSubtitle, "Invalid VTT Alignment Property" unless ALIGNMENT_VALUES[value]
103
+ return ALIGNMENT_VALUES[value]
104
+ end
105
+
106
+ def get_line(value)
107
+ raise InvalidSubtitle, "VTT Line property should be a valid number" if !is_integer?(value) and value != AUTO_KEYWORD
108
+ return value.to_i
109
+ end
110
+
111
+ def get_position(value)
112
+ raise InvalidSubtitle, "VTT Position should be a valid number" if !is_integer?(value)
113
+ raise InvalidSubtitle, "VTT Position should be a number between 0 to 100" if (value.to_i < 0) or (value.to_i > 100)
114
+ return value.to_i
115
+ end
116
+
117
+ def is_integer?(val)
118
+ val.to_i.to_s == val
119
+ end
120
+ end
121
+ end
@@ -13,6 +13,11 @@ module Captions
13
13
  @fps
14
14
  end
15
15
 
16
+ # Returns the parsed subtitles
17
+ def entries
18
+ @list
19
+ end
20
+
16
21
  # Hide all cues when inspecting CueList
17
22
  # Show only necessary info rather than printing everything
18
23
  def inspect
@@ -36,7 +41,13 @@ module Captions
36
41
 
37
42
  # Iterate through CueList
38
43
  def each
44
+ return to_enum(:each) unless block_given?
39
45
  @list.each { |c| yield(c) }
40
46
  end
47
+
48
+ # Array based enumerables for cuelist
49
+ def [](index)
50
+ @list[index]
51
+ end
41
52
  end
42
53
  end
@@ -1,3 +1,3 @@
1
1
  module Captions
2
- VERSION = "1.2.2"
2
+ VERSION = "1.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: captions
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - navin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-05-21 00:00:00.000000000 Z
11
+ date: 2017-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec