29 Oct 2012

WebVTT Cue Text Parser

UPDATE Nov 5:

I'm working on a cue text algorithm that follows the W3C specification. Didn't know why I wasn't doing this before as I followed the specification for all other parts of the parser.

I'll write a new blog post on it when we get it done.


UPDATE Oct 29:

I realized this morning that this won't work for cases such as ' text more text '.

I thought of a better algorithm and will post later.


My partner and I have been agonizing over creating an algorithm that will parse cue text. We've debated how to do it recursively, iteratively, etc. I think we've come up with a fairly good algorithm tonight.

We've only done it in pseudocode so far. Hopefully, we will be able to turn this into real code sometime soon. Feel free to mention any errors or inconsistencies you find in it.

It leaves out a couple edge cases such as 'ruby' and 'rt' text tags, time stamp text tags, as well as ignore parser logging. It also makes use of convenient collection methods such as add() and other things. Turning this into C code would involve a lot of leg work.

Anyways, here it is:

(June 2013) Please note that the code got messed up when transferring my blog. It might not make sense.
int find_end_tag(text, min_index ,*max_index, expected, *leaf_node) {

  for (i = max_index; text[i] != '>' && i > min_index; i++);

    if (i == 0 || text[--i] != expected || text[--i] != '/' || text[--i] != '<')
      return 0;

    if (i < max_index - 3) {
      leaf_node = new leaf_node();
      leaf_node.type = text;
      leaf_node.text = substring(text, i, max_index);
      max_index = i;
    }

    return 1;
  }

int parse_cue_text(text, node, min, max) {

  lead_node_start, leaf_node_end;
  char expected = '';

  for (i = min; i < max; i++) {
    if (text[i] == '<') { 
      switch (text[++i]) {
        case 'i':
          expected = 'i';
        case 'u':
          expected = 'u';
        case else:
          return 0;
        } 
      if (text[++i] != '>')
        return 0;

  //If it cannot find end tag
  if (!find_end_tag(text, i, &max, expected, &leaf_node_end))
    return 0;
  //If there is text between the start of min and where the found tag starts then  create a leaf node of text
  if (min < i)
    leaf_node_start = new leaf_node(text_type_enum, text.substring(min, i));

  node.node_list.add(leaf_node_start);

  //Create a new internal node with the type of expected
  node.node_list.add(new internal_node(expected));

  //Parse the next part of the cue text
  if (!parse_cue_text(text, node.node_list[node.node_list.length()], &min, &max))
    return 0;
  node.node_list.add(leaf_node_end);

  if (min < max) 
    node.node_list.add(new leaf_node(text_type_enum, text.substring(min, max))); 
  return 1; 
}

int parse_text(cue) {
  //Failed cue text
  if (!parse_cue_text(cue_text_line, cue->head, 0, cue_text_line.length())
    return 0;
  //Captured no cue text
  if (cue.head.node_list.length())
    return 0;
  return 1;
}
- Tagged in open-source, mozilla, and seneca college.

comments powered by Disqus

Wow coding Copyleft Richard Eyre 2013

Code for this site can be found on GitHub.