WebVTT Cue Text Parser


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 ‘<i> text </i> more <b> text </b>’.

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:

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));


			//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;

	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;


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s