Class: Captive::VTT
Constant Summary collapse
- VTT_HEADER =
Standard VTT Header
'WEBVTT'- VTT_METADATA =
VTT METADATA Regex
/^NOTE|^STYLE/.freeze
Instance Attribute Summary
Attributes included from Base
Class Method Summary collapse
- .integer?(val) ⇒ Boolean
-
.metadata?(text) ⇒ Boolean
VTT Metadata tag matcher.
-
.parse(blob:) ⇒ Object
Parse VTT blob and return array of cues.
-
.time?(text) ⇒ Boolean
VTT Timecode matcher.
-
.validate_header(line) ⇒ Object
VTT Header tag matcher.
Instance Method Summary collapse
-
#to_s ⇒ Object
Dump contents to String.
Methods included from Base
#as_json, included, #initialize, #method_missing, #respond_to_missing?, #save_as
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Captive::Base
Class Method Details
.integer?(val) ⇒ Boolean
103 104 105 |
# File 'lib/captive/formats/vtt.rb', line 103 def self.integer?(val) val.to_i.to_s == val end |
.metadata?(text) ⇒ Boolean
VTT Metadata tag matcher
94 95 96 |
# File 'lib/captive/formats/vtt.rb', line 94 def self.(text) !!text.match(VTT_METADATA) end |
.parse(blob:) ⇒ Object
Parse VTT blob and return array of cues
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/captive/formats/vtt.rb', line 14 def self.parse(blob:) cue_list = [] lines = blob.split("\n") cue_count = 1 state = :new_cue cue = nil raise InvalidSubtitle, 'Invalid VTT Signature' unless validate_header(lines.shift) lines.each_with_index do |line, index| line.strip! case state when :new_cue next if line.empty? if (line) state = :metadata next end # If its not metadata, and its not an empty line, it should be a timestamp or an identifier unless time?(line) # If this line is an identifier the next line should be a timecode next if time?(lines[index + 1]) raise InvalidSubtitle, "Invalid Time Format at line #{index + 1}" unless time?(line) end elements = line.split start_time = elements[0] end_time = elements[2] cue = Cue.new(cue_number: cue_count, start_time: start_time, end_time: end_time) cue_count += 1 state = :text when :text if line.empty? ## end of previous cue cue_list << cue cue = nil state = :new_cue else cue.add_text(line) end when :metadata next unless line.empty? # Line is empty which means metadata block is over state = :new_cue end end # Check to make sure we add the last cue if for some reason the file lacks an empty line at the end cue_list << cue unless cue.nil? # Return the cue_list cue_list end |
.time?(text) ⇒ Boolean
VTT Timecode matcher
99 100 101 |
# File 'lib/captive/formats/vtt.rb', line 99 def self.time?(text) !!text.match(/^(\d{2}:)?\d{2}:\d{2}.\d{3}.*(\d{2}:)?\d{2}:\d{2}.\d{3}/) end |
.validate_header(line) ⇒ Object
VTT Header tag matcher
88 89 90 91 |
# File 'lib/captive/formats/vtt.rb', line 88 def self.validate_header(line) # Make sure BOM does not interfere with header detection !!line.force_encoding('UTF-8').delete("\xEF\xBB\xBF").strip.match(/^#{VTT_HEADER}/) end |
Instance Method Details
#to_s ⇒ Object
Dump contents to String
73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/captive/formats/vtt.rb', line 73 def to_s string = VTT_HEADER.dup string << "\n\n" cues.each do |cue| string << milliseconds_to_timecode(cue.start_time) string << ' --> ' string << milliseconds_to_timecode(cue.end_time) string << "\n" string << cue.text string << "\n\n" end string end |