Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to TTAF1 subtitles #3864

Merged
merged 3 commits into from Jan 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
33 changes: 20 additions & 13 deletions lib/text/ttml_text_parser.js
Expand Up @@ -86,16 +86,17 @@ shaka.text.TtmlTextParser = class {
}

// Get the framerate, subFrameRate and frameRateMultiplier if applicable.
const frameRate = XmlUtils.getAttributeNS(tt, ttpNs, 'frameRate');
const subFrameRate = XmlUtils.getAttributeNS(tt, ttpNs, 'subFrameRate');
const frameRate = XmlUtils.getAttributeNSList(tt, ttpNs, 'frameRate');
const subFrameRate = XmlUtils.getAttributeNSList(
tt, ttpNs, 'subFrameRate');
const frameRateMultiplier =
XmlUtils.getAttributeNS(tt, ttpNs, 'frameRateMultiplier');
const tickRate = XmlUtils.getAttributeNS(tt, ttpNs, 'tickRate');
XmlUtils.getAttributeNSList(tt, ttpNs, 'frameRateMultiplier');
const tickRate = XmlUtils.getAttributeNSList(tt, ttpNs, 'tickRate');

const cellResolution = XmlUtils.getAttributeNS(
const cellResolution = XmlUtils.getAttributeNSList(
tt, ttpNs, 'cellResolution');
const spaceStyle = tt.getAttribute('xml:space') || 'default';
const extent = XmlUtils.getAttributeNS(tt, ttsNs, 'extent');
const extent = XmlUtils.getAttributeNSList(tt, ttsNs, 'extent');

if (spaceStyle != 'default' && spaceStyle != 'preserve') {
throw new shaka.util.Error(
Expand Down Expand Up @@ -787,7 +788,7 @@ shaka.text.TtmlTextParser = class {
return null;
}

const attr = XmlUtils.getAttributeNS(region, ttsNs, attribute);
const attr = XmlUtils.getAttributeNSList(region, ttsNs, attribute);
if (attr) {
return attr;
}
Expand All @@ -812,7 +813,7 @@ shaka.text.TtmlTextParser = class {

// Styling on elements should take precedence
// over the main styling attributes
const elementAttribute = XmlUtils.getAttributeNS(
const elementAttribute = XmlUtils.getAttributeNSList(
cueElement,
ttsNs,
attribute);
Expand Down Expand Up @@ -855,7 +856,7 @@ shaka.text.TtmlTextParser = class {

if (!styleAttributeValue) {
// Fall back to tts namespace.
styleAttributeValue = XmlUtils.getAttributeNS(
styleAttributeValue = XmlUtils.getAttributeNSList(
inheritedStyles[i],
ttsNs,
attribute);
Expand Down Expand Up @@ -1310,20 +1311,26 @@ shaka.text.TtmlTextParser.textAlignToPositionAlign_ = {
* document, not just "ttp:", so we use this with getAttributeNS() to ensure
* that we support arbitrary namespace names.
*
* @const {string}
* @const {!Array.<string>}
* @private
*/
shaka.text.TtmlTextParser.parameterNs_ = 'http://www.w3.org/ns/ttml#parameter';
shaka.text.TtmlTextParser.parameterNs_ = [
'http://www.w3.org/ns/ttml#parameter',
'http://www.w3.org/2006/10/ttaf1#parameter',
];

/**
* The namespace URL for TTML styles. Can be assigned any name in the TTML
* document, not just "tts:", so we use this with getAttributeNS() to ensure
* that we support arbitrary namespace names.
*
* @const {string}
* @const {!Array.<string>}
* @private
*/
shaka.text.TtmlTextParser.styleNs_ = 'http://www.w3.org/ns/ttml#styling';
shaka.text.TtmlTextParser.styleNs_ = [
'http://www.w3.org/ns/ttml#styling',
'http://www.w3.org/2006/10/ttaf1#styling',
];

/**
* The namespace URL for EBU TTML styles. Can be assigned any name in the TTML
Expand Down
19 changes: 19 additions & 0 deletions lib/util/xml_utils.js
Expand Up @@ -103,6 +103,25 @@ shaka.util.XmlUtils = class {
}


/**
* Gets a namespace-qualified attribute.
* @param {!Element} elem The element to get from.
* @param {!Array.<string>} nsList The lis of namespace URIs.
* @param {string} name The local name of the attribute.
* @return {?string} The attribute's value, or null if not present.
*/
static getAttributeNSList(elem, nsList, name) {
// Some browsers return the empty string when the attribute is missing,
// so check if it exists first. See: https://mzl.la/2L7F0UK
for (const ns of nsList) {
if (elem.hasAttributeNS(ns, name)) {
return elem.getAttributeNS(ns, name);
}
}
return null;
}


/**
* Gets the text contents of a node.
* @param {!Node} elem The XML element.
Expand Down
27 changes: 27 additions & 0 deletions test/text/ttml_text_parser_unit.js
Expand Up @@ -1227,6 +1227,33 @@ describe('TtmlTextParser', () => {
{periodStart: 0, segmentStart: 0, segmentEnd: 0});
});

it('allows old-standard namespace', () => {
verifyHelper(
[
{
startTime: 1,
endTime: 2,
payload: 'Test',
cellResolution: {
columns: 60,
rows: 20,
},
fontSize: '67%',
},
],
'<tt ' +
'xmlns:ttp="http://www.w3.org/2006/10/ttaf1#parameter" ' +
'xmlns:tts="http://www.w3.org/2006/10/ttaf1#styling" ' +
'ttp:cellResolution="60 20">' +
'<styling>' +
'<style xml:id="s1" tts:fontSize="67%"/>' +
'</styling>' +
'<body><div>' +
'<p begin="00:01.00" end="00:02.00" style="s1">Test</p>' +
'</div></body></tt>',
{periodStart: 0, segmentStart: 0, segmentEnd: 0});
});

it('parses cue alignment from textAlign attribute', () => {
verifyHelper(
[
Expand Down