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
101 102 103 |
# File 'lib/captive/formats/vtt.rb', line 101 def self.integer?(val) val.to_i.to_s == val end |
.metadata?(text) ⇒ Boolean
VTT Metadata tag matcher
92 93 94 |
# File 'lib/captive/formats/vtt.rb', line 92 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 |
# File 'lib/captive/formats/vtt.rb', line 14 def self.parse(blob:) cue_list = [] lines = blob.split("\n") 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(start_time: start_time, end_time: end_time) 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
97 98 99 |
# File 'lib/captive/formats/vtt.rb', line 97 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
86 87 88 89 |
# File 'lib/captive/formats/vtt.rb', line 86 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
71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/captive/formats/vtt.rb', line 71 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 |