TTXT Subtitling for BBB Video Player

In my last blogging I discussed the research I’d made into forcing XML-formatted plain text to being DOM-parsed. This became an essential task for the BBB Video Player as TTXT subtitle files are just that: XML-structured documents which were coming across as plain text. This could be fixed server-side by associating extension “ttxt” with “text/xml”, but given our work with Video.js I went for the client-side approach to ensure TTXT subtitling would always be possible and extended Video.js to ensure the data will be structured into an XML DOM tree client-side. I’ve posted a demo and my implementation code below:

function XHRFormatter(request, type) {
  var canForce = request.overrideMimeType;
  var forceToXML = canForce && type === 'ttxt';
  var isXml = forceToXML || type === 'xml';

  if (forceToXML) {
    request.overrideMimeType('text/xml');
  }

  return {
    // Select elements from aRef element tree based on expression aExpr
    // aExpr is a query string (delimiter to split on for text, XPath for xml)
    select: function(aRef, aExpr) {
      if (isXml) {
        var xpe = aRef.ownerDocument || aRef;
 
        if (xpe.createNSResolver && xpe.evaluate) {
          // Thanks to https://developer.mozilla.org/en/Using_XPath
          var nsResolver = xpe.createNSResolver(xpe.documentElement);
          var result = xpe.evaluate(aExpr, aRef, nsResolver, 0, null);  
          var found = [];  
          var res;  
          while (res = result.iterateNext())  
            found.push(res);  
          return found;  
        } else if (xpe.selectNodes) { // IE
          return xpe.selectNodes(aExpr);
        }
      } else if (isText) {
        return aRef.split(aExpr);
      }
    },
 
    getType: function() { return type; },
 
    format: function(str) {
      if (isXml) { // Return str as xml
        // Mime type has been overridden as XML or is XML by default
        if (canForce || !forceToXML) {
          return request.responseXML;
        // IE, mime type not overridden, must parse into XML
        } else if (typeof ActiveXObject !== 'undefined') { 
          var doc = new ActiveXObject("MSXML.DomDocument");
          doc.loadXML(str);
          return doc;
        } else {
          throw new Error("Can not process as XML!");
        }
      } else if (isText) {
        return request.responseText;
      }
    }
  }
}

My goal was to decouple the (potentially browser-specific) code that formats and selects data from xml from the code that works with that data. In use, it could work like this:

var request = new XmlHttpRequest();
var formatter = XHRFormatter(request, 'ttxt');
...
// Further work here
..
request.send();
var nodeTree = formatter.format(request.responseText);
var wantedNodes = formatter.select(nodeTree, "//My/XPath/Query/");
...

I’ve recently submitted a patch back to the Video.js team integrating this code into their player. Keep an eye out for their future releases, it may have official support for multiple subtitling formats 😉

Comments

Leave a Reply

Discover more from Software by Steven

Subscribe now to keep reading and get access to the full archive.

Continue reading