The Dark Old Days of TTML

How to caption the web using TTML and why you might not want to

Brightcove

Video.js

@gkatsev

http://slides.com/gkatsev/ttml/

Gary Katsevman

TTML

Timed Text Markup Language

Originally, DFXP

Distribution Format Exchange Profile

Standardized by W3C

Related Standards

WebVTT

SMPTE-EE

CFF-TT

Common File Format

Uses SMPTE-TT in UltraViolet

SMPTE-TT?

Society of Motion Picture and Television Engineers

Standards, Recommended Practices, Engineering Guidelines

  • TV Production

  • Filmmaking

  • Digital cinema

  • Audio Recording

  • Information Technology

  • Medical Imaging

Superset of TTML

Maintaining Legacy

CEA-706

CEA-608

DVB

FCC's CVAA

21st Century Communications and Video Accessibility Act

Safe Harbor for SMPTE-TT

2012

WHATWG chose WebVTT in 2010

TTML

Industry Standard

Ingestion Systems

  • YouTube

  • Netflix

  • Amazon

Google Cast

Internet Explorer

Microsoft Edge

Like Html, CSS

But worse

Much worse

<tt xml:lang="en"
xmlns="http://www.w3.org/ns/ttml"
xmlns:tts="http://www.w3.org/ns/ttml#styling">
 <head>
    <metadata xmlns:ttm="http://www.w3.org/ns/ttml#metadata">
     <ttm:title>TTML Example</ttm:title>
     <ttm:copyright>Thierry Michel 2015</ttm:copyright>
    </metadata>

    <styling xmlns:tts="http://www.w3.org/ns/ttml#styling">
     <style xml:id="s1" tts:color="red" tts:textAlign="center"  />
    </styling>
</head>

 <body>
    <div>
        <p xml:id="c1" begin="00:00:00" end="00:00:10">            
            Hello I am your first line.</p>
        <p xml:id="c2" begin="00:00:02" end="00:00:10">
            I am your second captions<br/>but with two lines.</p>
        <p xml:id="c3" xml:lang="fr" begin="00:00:04" end="00:00:10">
            Je suis le troisième sous-titre.</p>
        <p xml:id="c4" begin="00:00:06" end="00:00:10" >
            I am another caption with <span tts:fontWeight="bold">Bold</span> and <span tts:fontStyle="italic">Italic</span> styles.</p>
        <p xml:id="c5" begin="00:00:08" end="00:00:10" style="s1">
            I am the last caption displayed in red and centered.</p>

    </div>
 </body>
</tt>

TTML

WEBVTT
title:  Web-VTT Example
copyright: Thierry Michel 2015
 
NOTE to style this document, CSS color font must be the specified in the HTML hosting page in the <style> element.

c1
00:00.000 --> 00:10.000
Hello I am your first line.

c2
00:02.000 --> 00:10.000
I am your second captions
but with two lines.

c3
00:04.000 --> 00:10.000
<lang fr>Je suis le troisième sous-titre.</lang>

c4
00:06.000 --> 00:10.000
I am another caption with <b>Bold</b> and <i>Italic</i> styles.

c5
00:08.000 --> 00:10.000 align:middle 
<c.red>I am the last caption displayed in red and centered.</c>

--------------------------------------
In the HTML 5, CSS style:
<style>  ::cue(.red) {color:red;} </style>

VTT

<tt xml:lang="en"
xmlns="http://www.w3.org/ns/ttml"
xmlns:tts="http://www.w3.org/ns/ttml#styling">
<head>
  <metadata xmlns:ttm="http://www.w3.org/ns/ttml#metadata">
    <ttm:title>TTML Example</ttm:title>
    <ttm:copyright>Thierry Michel 2015</ttm:copyright>
  </metadata>

  <styling xmlns:tts="http://www.w3.org/ns/ttml#styling">
    <style xml:id="s1" tts:color="red" tts:textAlign="center"/>
  </styling>
</head>
<body>
<div>
  <p xml:id="c1" begin="00:00:00" end="00:00:10">            
    Hello I am your first line.</p>
  <p xml:id="c2" begin="00:00:02" end="00:00:10">
    I am your second captions<br/>but with two lines.</p>
</div>
</body>

<body>
<div>
<p xml:id="c3" xml:lang="fr" begin="00:00:04" end="00:00:10">
  Je suis le troisième sous-titre.</p>
<p xml:id="c4" begin="00:00:06" end="00:00:10" >
  I am another caption with
  <span tts:fontWeight="bold">Bold</span> and 
  <span tts:fontStyle="italic">Italic</span> styles.</p>
</div>
</body>
<head>
<styling xmlns:tts="http://www.w3.org/ns/ttml#styling">
  <style xml:id="s1" tts:color="red" tts:textAlign="center"  />
</styling>
</head>

<body>
<div>
  <p xml:id="c5" begin="00:00:08" end="00:00:10" style="s1">
    I am the last caption displayed in red and centered.</p>
</div>
</body>

videojs-ttml

player.ttml({
  src: 'test/fixtures/full.xml',
  label: 'English',
  srclang: 'en-us'
});
videojs.plugin('ttml', function(options) {
  const player = this;
  let ttmlDisplay;

  const dfxpurl = options.src;
  videojs.xhr({
    uri: dfxpurl
  }, function(err, res, body) {
    if (res.statusCode >= 400) {
      return videojs.error(err);
    }

    const styleParser = parseTtml(body, player.currentHeight());
    player.ttml.styleParser = styleParser;

    ttmlDisplay = player.addChild('ttmlDisplay');
  });
document.querySelector('.on-button')
.addEventListener('click', function() {
  ttmlDisplay.enable();
});
document.querySelector('.off-button')
.addEventListener('click', function() {
  ttmlDisplay.disable();
});

document.querySelector('.en-button')
.addEventListener('click', function() {
  ttmlDisplay.setLanguage('en');
  ttmlDisplay.enable();
});
document.querySelector('.fr-button')
.addEventListener('click', function() {
  ttmlDisplay.setLanguage('fr');
  ttmlDisplay.enable();
});
const parseTtml = function(ttml, height) {
  const dom = (new DOMParser())
    .parseFromString(ttml, 'text/xml');
  if (!dom || dom.querySelector('parsererror')) {
    videojs.error('failed to parse the TTML');
  }

  // remove all potential <script> elements
  const domScripts = dom.querySelectorAll('script');
  for (let i = 0; i < domScripts; i++) {
    const domScript = domScripts[i];
    domScript.parentNode.removeChild(domScript);
  }

  const language = dom.documentElement.getAttribute('xml:lang');
  const body = dom.querySelector('body');

  const styleParser = new TtmlDomParser(dom, {}, height);

  return styleParser;
};
const TtmlDomParser = function(dom, styleOptions, height) {
  /* various other setup */

  this.setNamespaces(dom);
  this.parseHead(dom);
  this.parseBody(dom);
};

Brightcove

Video.js

@gkatsev

http://slides.com/gkatsev/ttml/

Gary Katsevman

Thanks!

Made with Slides.com