Subtitles or Closed Captions in Processing?

I’m building a prototype where I manipulate some subtitles (TTML/DFXP format) based on some interaction from the user.

Currently, I can read in a subtitle file using XML parsing, but I was looking to see if there was any library implementation someone had built that would make displaying each subtile easier in processing?

I would rather not build a custom subtitle presentation library if someone had already went to the effort. Has anyone come across or built an implementation?

I’m not sure about TTML specifically, but when i tried this:

https://www.google.com/search?q=processing+subtitles

These were some of the top results on processing code for subtitles:

It looks like maybe none of that is TTML. For TTML you might want to just search for a TTML Java Library

https://www.google.com/search?q=java+ttml

like these, perhaps the renderer:

https://android.googlesource.com/platform/frameworks/base/+/master/media/java/android/media/TtmlRenderer.java

Thanks! I ended up throwing it together myself. I found most of those links and they made it look fairly complicated. However, it wasn’t actually too bad as ttml is mostly just XML. Only issue I came across is that one of the tags:

ttm:br/

gets ignored by processing’s XML parser so line breaks are missing in each subtitle line, so it doesn’t fully work with all files without some manual work yet (replacing the tag with \n).

Here’s how I roughly did it:

XML[] subtitles;
XML response_xml;
response_xml = loadXML(“videos/parks_recs.dfxp”);

XML body = response_xml.getChild(“tt:body”);
XML div = body.getChild(“tt:div”);
subtitles = div.getChildren(“tt:p”);

if (subtitle_counter < subtitles.length-1)
{
float begin = convertTimeCodeToSeconds(subtitles[subtitle_counter].getString(“begin”), 30);
float end = convertTimeCodeToSeconds(subtitles[subtitle_counter].getString(“end”), 30);
String text = line(subtitles[subtitle_counter].getContent());

	if ((movieTime >= begin) && (movieTime <= end))
	{

		textAlign(CENTER, CENTER);
		fill(0);
		rect(width/2-10-(textWidth(text)/2),height-140,textWidth(text)+20, 120);
		fill(255);
       text(text, width/2,height-50);
    }
	else if (movieTime >= end)
	{
		subtitle_counter++;
	}

}

Could you share an example of what a valid file with ttm:br looks like?

Perhaps you could load the xml as a string, pre-parse by replacing those ttm:br/ with \n, and then use loadXML

Sure, that might work actually. Here’s an example:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<tt:tt xmlns:ttm=“http://www.w3.org/ns/ttml#metadata” xmlns:tt=“http://www.w3.org/ns/ttml” xmlns:ttp=“http://www.w3.org/ns/ttml#parameter” xmlns:tts=“http://www.w3.org/ns/ttml#styling” xml:lang=“en-US”>
<tt:head>
<tt:styling>
<tt:style xml:id=“AmazonDefaultStyle” tts:backgroundColor=“transparent” tts:color="#FFCC00" tts:displayAlign=“before” tts:extent=“80% 15%” tts:fontSize=“80%” tts:opacity=“1.00” tts:origin=“10% 80%” tts:overflow=“visible” tts:textAlign=“center” tts:textOutline="#000000 2px" tts:wrapOption=“wrap”/>
</tt:styling>
<tt:layout>
<tt:region xml:id=“AmazonDefaultRegion” style=“AmazonDefaultStyle”/>
</tt:layout>
</tt:head>
<tt:body region=“AmazonDefaultRegion”>
<tt:div>
<tt:p begin=“00:00:40.605” end=“00:00:43.391”> Let me tell you about my day so far. </tt:p>
<tt:p begin=“00:00:43.478” end=“00:00:45.436”> Coffee in Paris, surfed the Maldives, </tt:p>
<tt:p begin=“00:00:45.523” end=“00:00:48.004”> took a little nap on Mount Kilimanjaro. </tt:p>
<tt:p begin=“00:00:48.091” end=“00:00:50.833”> But you know what?<tt:br/>We all have to make sacrifices<tt:br/>once in a while. You know.</tt:p>
</tt:div>
</tt:body>
</tt:tt>

Yes, it looks like that would be a quick way to preparse your linebreak singleton XML tags:

  1. Load your XML file with loadStrings into String[] fStrings
  2. for st in FStrings: st = st.replace("<tt:br/>", "\n");
  3. load your joined string with parseXML: String xmlString = join(fStrings, "\n");
  4. parse it with parseXML: XML xml = parseXML(xmlString)