This commit is contained in:
Anna Sobiepanek 2011-03-08 14:28:51 -05:00
Родитель 4fe3f0f398
Коммит 0400d8ae11
20 изменённых файлов: 1387 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<title>Popcorn 0.3 SBV parser Plug-in Demo</title>
<script src="../../popcorn.js"></script>
<script src="../../test/jquery.js"></script>
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
<script src="popcorn.parseSBV.js"></script>
<script>
document.addEventListener( 'DOMContentLoaded', function () {
var p = Popcorn( '#video' )
.volume( 0 )
.play();
}, false);
</script>
</head>
<body>
<h1 id="qunit-header">Popcorn 0.3 SBV parser Plug-in Demo</h1>
<p>From 2.4 to 7.2 seconds, "Senator, we're making our final approach into Coruscant." is shown
<br />From 9.712 to 13.399 seconds, "Very good, Lieutenant." is shown
<br />From 15.042 to 18.042 seconds, "It's a trap!" is shown</p>
<div>
<div>
<video id='video'
controls
width= '250px'
data-timeline-sources="data/data.sbv"
poster="../../test/poster.png">
<source id='mp4'
src="../../test/trailer.mp4"
type='video/mp4; codecs="avc1, mp4a"'>
<source id='ogv'
src="../../test/trailer.ogv"
type='video/ogg; codecs="theora, vorbis"'>
<p>Your user agent does not support the HTML5 Video element.</p>
</video>
</div>
<h4>Subtitle Source<h4>
<iframe id="srcDisplay" src="data/data.sbv"></iframe>
</body>
</html>

Просмотреть файл

@ -0,0 +1,100 @@
// PARSER: 0.1 SBV
(function (Popcorn) {
/**
* SBV popcorn parser plug-in
* Parses subtitle files in the SBV format.
* Times are expected in H:MM:SS.MIL format, with hours optional
* Subtitles which don't match expected format are ignored
* Data parameter is given by Popcorn, will need a text.
* Text is the file contents to be parsed
*
* @param {Object} data
*
* Example:
0:00:02.400,0:00:07.200
Senator, we're making our final approach into Coruscant.
*/
Popcorn.parser( "parseSBV", function( data ) {
// declare needed variables
var retObj = {
title: "",
remote: "",
data: []
},
subs = [],
lines,
i = 0,
len = 0,
idx = 0;
// [H:]MM:SS.MIL string to SS.MIL
// Will thrown exception on bad time format
var toSeconds = function( t_in ) {
var t = t_in.split( ":" ),
l = t.length-1,
time;
try {
time = parseInt( t[l-1], 10 )*60 + parseFloat( t[l], 10 );
// Hours optionally given
if ( l === 2 ) {
time += parseInt( t[0], 10 )*3600;
}
} catch ( e ) {
throw "Bad cue";
}
return time;
};
var createTrack = function( name, attributes ) {
var track = {};
track[name] = attributes;
return track;
};
// Here is where the magic happens
// Split on line breaks
lines = data.text.split( /(?:\r\n|\r|\n)/gm );
len = lines.length;
while ( i < len ) {
var sub = {},
text = [],
time = lines[i++].split( "," );
try {
sub.start = toSeconds( time[0] );
sub.end = toSeconds( time[1] );
// Gather all lines of text
while ( i < len && lines[i] ) {
text.push( lines[i++] );
}
// Join line breaks in text
sub.text = text.join( "<br />" );
subs.push( createTrack( "subtitle", sub ) );
} catch ( e ) {
// Bad cue, advance to end of cue
while ( i < len && lines[i] ) {
i++;
}
}
// Consume empty whitespace
while ( i < len && !lines[i] ) {
i++;
}
}
retObj.data = subs;
return retObj;
});
})( Popcorn );

Просмотреть файл

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<head>
<title>Popcorn 0.3 SBV parser Plug-in Test</title>
<link rel="stylesheet" href="../../test/qunit/qunit.css" type="text/css" media="screen">
<script src="../../test/qunit/qunit.js"></script>
<!--
do not move - this must be called immediately prior to
popcorn-api-draft.js
-->
<script src="../../popcorn.js"></script>
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
<script src="popcorn.parseSBV.js"></script>
<script src="popcorn.parseSBV.unit.js"></script>
</head>
<body>
<h1 id="qunit-header">Popcorn 0.3 SBV parser Plug-in Test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"> </div>
<video id='video'
controls
width= '250px'
data-timeline-sources="data/data.sbv"
poster="../../test/poster.png">
<source id='mp4'
src="../../test/trailer.mp4"
type='video/mp4; codecs="avc1, mp4a"'>
<source id='ogv'
src="../../test/trailer.ogv"
type='video/ogg; codecs="theora, vorbis"'>
<p>Your user agent does not support the HTML5 Video element.</p>
</video>
</body>
</html>

Просмотреть файл

@ -0,0 +1,58 @@
test( "Popcorn 0.3 SBV Parser Plugin", function () {
var count = 0,
numSubs = 0,
sub,
poppercorn = Popcorn( "#video" ),
subs = [
{
text: "Senator, we're making our final approach into Coruscant.",
start: 2.4,
end: 7.2
},
{
text: "Very good, Lieutenant.",
start: 9.712,
end: 13.399
},
{
text: "It's a trap!",
start: 15.042,
end: 18.042
}
],
expects = subs.length*3 + 1;
function plus() {
if ( ++count === expects ) {
start();
}
}
poppercorn.parseSBV( document.getElementById( "video" ).getAttribute( "data-timeline-sources" ) );
expect(expects);
stop( 5000 );
// Allow load time
setTimeout(function () {
Popcorn.forEach( poppercorn.getTrackEvents(), function(evt) {
if( evt._natives.type === "subtitle" ) {
sub = subs[numSubs++];
equals( evt.start, sub.start, "Correctly parsed start of " + evt.start );
plus();
equals( evt.text, sub.text, "Correctly parsed text of " + evt.start );
plus();
equals( evt.end, sub.end, "Correctly parsed end at " + evt.start );
plus();
}
});
equals( subs.length, numSubs, "Parsed all subtitles" );
plus();
}, 500);
});

Просмотреть файл

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<title>Popcorn 0.3 SSA parser Plug-in Demo</title>
<script src="../../popcorn.js"></script>
<script src="../../test/jquery.js"></script>
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
<script src="popcorn.parseSSA.js"></script>
<script>
document.addEventListener( 'DOMContentLoaded', function () {
var p = Popcorn( '#video' )
.volume( 0 )
.play();
}, false);
</script>
</head>
<body>
<h1 id="qunit-header">Popcorn 0.3 SSA parser Plug-in Demo</h1>
<p>From 2.4 to 7.2 seconds, "Senator, we're making our final approach into Coruscant." is shown
<br />From 9.71 to 13.39 seconds, "Very good, Lieutenant." is shown
<br />From 15.04 to 18.04 seconds, "It's a trap!" is shown</p>
<div>
<video id='video'
controls
width= '250px'
data-timeline-sources="data/data.ssa"
poster="../../test/poster.png">
<source id='mp4'
src="../../test/trailer.mp4"
type='video/mp4; codecs="avc1, mp4a"'>
<source id='ogv'
src="../../test/trailer.ogv"
type='video/ogg; codecs="theora, vorbis"'>
<p>Your user agent does not support the HTML5 Video element.</p>
</video>
</div>
<h4>Subtitle Source<h4>
<iframe id="srcDisplay" src="data/data.ssa"></iframe>
</body>
</html>

Просмотреть файл

@ -0,0 +1,132 @@
// PARSER: 0.3 SSA/ASS
(function (Popcorn) {
/**
* SSA/ASS popcorn parser plug-in
* Parses subtitle files in the identical SSA and ASS formats.
* Style information is ignored, and may be found in these
* formats: (\N \n {\pos(400,570)} {\kf89})
* Out of the [Script Info], [V4 Styles], [Events], [Pictures],
* and [Fonts] sections, only [Events] is processed.
* Data parameter is given by Popcorn, will need a text.
* Text is the file contents to be parsed
*
* @param {Object} data
*
* Example:
[Script Info]
Title: Testing subtitles for the SSA Format
[V4 Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding
Style: Default,Arial,20,65535,65535,65535,-2147483640,-1,0,1,3,0,2,30,30,30,0,0
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:02.40,0:00:07.20,Default,,0000,0000,0000,,Senator, {\kf89}we're \Nmaking our final \napproach into Coruscant.
Dialogue: 0,0:00:09.71,0:00:13.39,Default,,0000,0000,0000,,{\pos(400,570)}Very good, Lieutenant.
Dialogue: 0,0:00:15.04,0:00:18.04,Default,,0000,0000,0000,,It's \Na \ntrap!
*
*/
// Register for SSA extensions
Popcorn.parser( "parseSSA", function( data ) {
// declare needed variables
var retObj = {
title: "",
remote: "",
data: []
},
subs = [],
startIdx,
endIdx,
textIdx,
lines,
fields,
numFields,
sub,
text,
i = 0,
j = 0,
len = 0,
fieldLen = 0;
// h:mm:ss.cc (centisec) string to SS.mmm
// Returns -1 if invalid
var toSeconds = function( t_in ) {
var t = t_in.split( ":" ),
l = t.length - 1;
// Not all there
if ( t_in.length !== 10 ) {
return -1;
}
return parseInt( t[0], 10 )*3600 + parseInt( t[l-1], 10 )*60 + parseFloat( t[l], 10 );
};
var createTrack = function( name, attributes ) {
var track = {};
track[name] = attributes;
return track;
};
// Here is where the magic happens
// Split on line breaks
lines = data.text.split( /(?:\r\n|\r|\n)/gm );
len = lines.length;
// Ignore non-textual info
while ( i < len && lines[i] !== "[Events]" ) {
i++;
}
fields = lines[++i].substr( 8 ).split( ", " ); // Trim 'Format: ' off front, split on delim
numFields = fields.length;
//Find where in Dialogue string the start, end and text info is
for ( ; j < numFields; j++ ) {
if ( fields[j] === "Start" ) {
startIdx = j;
} else if ( fields[j] === "End" ) {
endIdx = j;
} else if ( fields[j] === "Text" ) {
textIdx = j;
}
}
while ( ++i < len && lines[i] && lines[i][0] !== "[" ) {
sub = {};
// Trim beginning 'Dialogue: ' and split on delim
fields = lines[i].substr( 10 ).split( "," );
sub.start = toSeconds( fields[startIdx] );
sub.end = toSeconds( fields[endIdx] );
// Invalid time, skip
if ( sub.start === -1 || sub.end === -1 ) {
continue;
}
if ( ( fieldLen = fields.length ) === numFields ) {
sub.text = fields[textIdx];
} else {
// There were commas in the text which were split, append back together into one line
text = [];
for( j = textIdx; j < fieldLen; j++ ) {
text.push( fields[j] );
}
sub.text = text.join( "," );
}
// Eliminate advanced styles and convert forced line breaks
sub.text = sub.text.replace( /\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}/gi, "" ).replace( /\\N/gi, "<br />" );
subs.push( createTrack( "subtitle", sub ) );
}
retObj.data = subs;
return retObj;
});
})( Popcorn );

Просмотреть файл

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<title>Popcorn 0.3 SSA parser Plug-in Test</title>
<link rel="stylesheet" href="../../test/qunit/qunit.css" type="text/css" media="screen">
<script src="../../test/qunit/qunit.js"></script>
<!--
do not move - this must be called immediately prior to
popcorn-api-draft.js
-->
<script src="../../popcorn.js"></script>
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
<script src="popcorn.parseSSA.js"></script>
<script src="popcorn.parseSSA.unit.js"></script>
</head>
<body>
<h1 id="qunit-header">Popcorn 0.3 SSA parser Plug-in Test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"> </div>
<video id='video'
controls
width= '250px'
data-timeline-sources="data/data.ssa"
poster="../../test/poster.png">
<source id='mp4'
src="../../test/trailer.mp4"
type='video/mp4; codecs="avc1, mp4a"'>
<source id='ogv'
src="../../test/trailer.ogv"
type='video/ogg; codecs="theora, vorbis"'>
<p>Your user agent does not support the HTML5 Video element.</p>
</video>
</body>
</html>

Просмотреть файл

@ -0,0 +1,57 @@
test( "Popcorn 0.3 SSA/ASS Parser Plugin", function () {
var count = 0,
numSubs = 0,
sub,
poppercorn = Popcorn( "#video" ),
subs = [
{
text: "Senator, we're <br />making our final <br />approach into Coruscant.",
start: 2.4,
end: 7.2
},
{
text: "Very good, Lieutenant.",
start: 9.71,
end: 13.39
},
{
text: "It's <br />a <br />trap!",
start: 15.04,
end: 18.04
}
],
expects = subs.length*3 + 1;
function plus() {
if ( ++count === expects ) {
start();
}
}
poppercorn.parseSSA( document.getElementById( "video" ).getAttribute( "data-timeline-sources" ) );
expect( expects );
stop( 5000 );
// Allow load time
setTimeout(function () {
Popcorn.forEach( poppercorn.getTrackEvents(), function(evt) {
if( evt._natives.type === "subtitle" ) {
sub = subs[numSubs++];
equals( evt.start, sub.start, "Correctly parsed start of " + evt.start );
plus();
equals( evt.text, sub.text, "Correctly parsed text of " + evt.start );
plus();
equals( evt.end, sub.end, "Correctly parsed end at " + evt.start );
plus();
}
});
equals( subs.length, numSubs, "Parsed all subtitles" );
plus();
}, 500);
});

Просмотреть файл

@ -0,0 +1,54 @@
<!DOCTYPE html>
<html>
<head>
<title>Popcorn 0.3 TTML parser Plug-in Demo</title>
<script src="../../popcorn.js"></script>
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
<script src="popcorn.parseTTML.js"></script>
<script>
document.addEventListener( 'DOMContentLoaded', function () {
var p = Popcorn( '#video' )
.volume( 0 )
.play();
}, false);
</script>
</head>
<body>
<h1 id="qunit-header">Popcorn 0.3 TTML parser Plug-in Demo</h1>
<p>From 0.76 to 3.45 seconds, "It seems a paradox, does it not," is shown
<br />From 5 to 10 seconds, "that the image formed on the Retina should be inverted?" is shown
<br />From 10 to 16 seconds, "It is puzzling, why is it we do not see things upside-down?" is shown
<br />From 17.2 to 23 seconds, "You have never heard the Theory, then, that the Brain also is inverted?" is shown
<br />From 23 to 27 seconds, "No indeed! What a beautiful fact!" is shown
<br />From 27.76 to 30.45 seconds, "It seems a paradox, does it not," is shown
<br />From 32 to 37 seconds, "that the image formed on the Retina should be inverted?" is shown
<br />From 37 to 43 seconds, "It is puzzling, why is it we do not see things upside-down?" is shown
<br />From 44.2 to 50 seconds, "You have never heard the Theory, then, that the Brain also is inverted?" is shown
<br />From 50 to 54 seconds, "No indeed! What a beautiful fact!" is shown</p>
<div>
<video id='video'
controls
width= '250px'
data-timeline-sources="data/data.ttml"
poster="../../test/poster.png">
<source id='mp4'
src="../../test/trailer.mp4"
type='video/mp4; codecs="avc1, mp4a"'>
<source id='ogv'
src="../../test/trailer.ogv"
type='video/ogg; codecs="theora, vorbis"'>
<p>Your user agent does not support the HTML5 Video element.</p>
</video>
</div>
<h4>Subtitle Source<h4>
<iframe id="srcDisplay" src="data/data.ttml"></iframe>
</body>
</html>

Просмотреть файл

@ -0,0 +1,171 @@
// PARSER: 0.3 TTML
(function (Popcorn) {
/**
* TTML popcorn parser plug-in
* Parses subtitle files in the TTML format.
* Times may be absolute to the timeline or relative
* Absolute times are ISO 8601 format (hh:mm:ss[.mmm])
* Relative times are a fraction followed by a unit metric (d.ddu)
* Relative times are relative to the time given on the parent node
* Styling information is ignored
* Data parameter is given by Popcorn, will need an xml.
* Xml is the file contents to be processed
*
* @param {Object} data
*
* Example:
<tt xmlns:tts="http://www.w3.org/2006/04/ttaf1#styling" xmlns="http://www.w3.org/2006/04/ttaf1">
<body region="subtitleArea">
<div>
<p xml:id="subtitle1" begin="0.76s" end="3.45s">
It seems a paradox, does it not,
</p>
</div>
</body>
</tt>
*/
Popcorn.parser( "parseTTML", function( data ) {
// declare needed variables
var returnData = {
title: "",
remote: "",
data: []
},
node,
numTracks = 0,
region;
// Convert time expression to SS.mmm
// Expression may be absolute to timeline (hh:mm:ss.ms)
// or relative ( fraction followedd by metric ) ex: 3.4s, 5.7m
// Returns -1 if invalid
var toSeconds = function ( t_in, offset ) {
if ( !t_in ) {
return -1;
}
var t = t_in.split( ":" ),
l = t.length - 1,
metric,
multiplier,
i;
// Try clock time
if ( l >= 2 ) {
return parseInt( t[0], 10 )*3600 + parseInt( t[l-1], 10 )*60 + parseFloat( t[l], 10 );
}
// Was not clock time, assume relative time
// Take metric from end of string (may not be single character)
// First find metric
for( i = t_in.length - 1; i >= 0; i-- ) {
if ( t_in[i] <= "9" && t_in[i] >= "0" ) {
break;
}
}
// Point i at metric and normalize offsete time
i++;
metric = t_in.substr( i );
offset = offset || 0;
// Determine multiplier for metric relative to seconds
if ( metric === "h" ) {
multiplier = 3600;
} else if ( metric === "m" ) {
multiplier = 60;
} else if ( metric === "s" ) {
multiplier = 1;
} else if ( metric === "ms" ) {
multiplier = 0.001;
} else {
return -1;
}
// Valid multiplier
return parseFloat( t_in.substr( 0, i ) ) * multiplier + offset;
};
// creates an object of all atrributes keyd by name
var createTrack = function( name, attributes ) {
var track = {};
track[name] = attributes;
return track;
};
// Parse a node for text content
var parseNode = function( node, timeOffset ) {
var sub = {};
// Trim left and right whitespace from text and change non-explicit line breaks to spaces
sub.text = node.textContent.replace(/^[\s]+|[\s]+$/gm, "").replace(/(?:\r\n|\r|\n)/gm, "<br />");
sub.id = node.getAttribute( "xml:id" );
sub.start = toSeconds ( node.getAttribute( "begin" ), timeOffset );
sub.end = toSeconds( node.getAttribute( "end" ), timeOffset );
sub.target = region;
if ( sub.end < 0 ) {
// No end given, infer duration if possible
// Otherwise, give end as MAX_VALUE
sub.end = toSeconds( node.getAttribute( "duration" ), 0 );
if ( sub.end >= 0 ) {
sub.end += sub.start;
} else {
sub.end = Number.MAX_VALUE;
}
}
return sub;
};
// Parse the children of the given node
var parseChildren = function( node, timeOffset ) {
var currNode = node.firstChild,
sub,
newOffset;
while ( currNode ) {
if ( currNode.nodeType === 1 ) {
if ( currNode.nodeName === "p" ) {
// p is a teextual node, process contents as subtitle
sub = parseNode( currNode, timeOffset );
returnData.data.push( createTrack( "subtitle", sub ) );
numTracks++;
} else if ( currNode.nodeName === "div" ) {
// div is container for subtitles, recurse
newOffset = toSeconds( currNode.getAttribute("begin") );
if (newOffset < 0 ) {
newOffset = timeOffset;
}
parseChildren( currNode, newOffset );
}
}
currNode = currNode.nextSibling;
}
};
// Null checks
if ( !data.xml || !data.xml.documentElement || !( node = data.xml.documentElement.firstChild ) ) {
return returnData;
}
// Find body tag
while ( node.nodeName !== "body" ) {
node = node.nextSibling;
}
region = "";
parseChildren( node, 0 );
return returnData;
});
})( Popcorn );
;

Просмотреть файл

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<title>Popcorn 0.3 TTML parser Plug-in Test</title>
<link rel="stylesheet" href="../../test/qunit/qunit.css" type="text/css" media="screen">
<script src="../../test/qunit/qunit.js"></script>
<!--
do not move - this must be called immediately prior to
popcorn-api-draft.js
-->
<script src="../../popcorn.js"></script>
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
<script src="popcorn.parseTTML.js"></script>
<script src="popcorn.parseTTML.unit.js"></script>
</head>
<body>
<h1 id="qunit-header">Popcorn 0.3 TTML parser Plug-in Test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"> </div>
<video id='video'
controls
width= '250px'
data-timeline-sources="data/unit.ttml"
poster="../../test/poster.png">
<source id='mp4'
src="../../test/trailer.mp4"
type='video/mp4; codecs="avc1, mp4a"'>
<source id='ogv'
src="../../test/trailer.ogv"
type='video/ogg; codecs="theora, vorbis"'>
<p>Your user agent does not support the HTML5 Video element.</p>
</video>
</body>
</html>

Просмотреть файл

@ -0,0 +1,103 @@
test( "Popcorn 0.3 TTML Parser Plugin", function () {
var count = 0,
numSubs = 0,
sub,
poppercorn = Popcorn( "#video" ),
subs = [
{
id: "subtitle1",
text: "It seems a paradox, does it not,",
start: 0.76,
end: 3.45
},
{
id: "subtitle2",
text: "that the image formed on<br />the Retina should be inverted?",
start: 5,
end: 10
},
{
id: "subtitle3",
text: "It is puzzling, why is it<br />we do not see things upside-down?",
start: 10,
end: 16
},
{
id: "subtitle4",
text: "You have never heard the Theory,<br />then, that the Brain also is inverted?",
start: 17.2,
end: 23
},
{
id: "subtitle5",
text: "No indeed! What a beautiful fact!",
start: 23,
end: 27
},
{
id: "subtitle6",
text: "It seems a paradox, does it not,",
start: 27.76,
end: 30.45
},
{
id: "subtitle7",
text: "that the image formed on<br />the Retina should be inverted?",
start: 33,
end: 37
},
{
id: "subtitle8",
text: "It is puzzling, why is it<br />we do not see things upside-down?",
start: 37,
end: 43
},
{
id: "subtitle9",
text: "You have never heard the Theory,<br />then, that the Brain also is inverted?",
start: 44.2,
end: 50
},
{
id: "subtitle10",
text: "No indeed! What a beautiful fact!",
start: 50,
end: 54
}
],
expects = subs.length*4 + 1;
function plus() {
if ( ++count === expects ) {
start();
}
}
poppercorn.parseTTML( document.getElementById( 'video' ).getAttribute( "data-timeline-sources" ) );
expect( expects );
stop( 5000 );
// Allow load time
setTimeout(function () {
Popcorn.forEach( poppercorn.getTrackEvents(), function( evt ) {
if( evt._natives.type === "subtitle" ) {
sub = subs[numSubs++];
strictEqual( evt.id, sub.id, "Correctly parsed id of " + evt.id );
plus();
strictEqual( evt.start, sub.start, "Correctly parsed start of " + evt.id + " at " + evt.start );
plus();
strictEqual( evt.text, sub.text, "Correctly parsed text of " + evt.id + " at " + evt.start );
plus();
strictEqual( evt.end, sub.end, "Correctly parsed end of " + evt.id + " at " + evt.start );
plus();
}
});
strictEqual( subs.length, numSubs, "Parsed all subtitles" );
plus();
}, 500);
});

Просмотреть файл

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<title>Popcorn 0.3 TTXT parser Plug-in Demo</title>
<script src="../../popcorn.js"></script>
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
<script src="popcorn.parseTTXT.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
var p = Popcorn('#video')
.volume(0)
.play()
}, false);
</script>
</head>
<body>
<h1 id="qunit-header">Popcorn 0.3 TTXT parser Plug-in Demo</h1>
<p>Subtitles are processed from <a href="data/data.TTXT">here</a></p>
<p>From 2.4 to 5.2 seconds, "[Background Music Playing]" is shown
<br />From 15.712 to 17.399 seconds, "Heay!!" is shown
<br />From 25.712 to 30.399 seconds, "[Bird noises]" is shown</p>
<div>
<video id='video'
data-timeline-sources="data/data.TTXT"
controls
width= '250px'
poster="../../test/poster.png">
<source id='mp4'
src="../../test/trailer.mp4"
type='video/mp4; codecs="avc1, mp4a"'>
<source id='ogv'
src="../../test/trailer.ogv"
type='video/ogg; codecs="theora, vorbis"'>
<p>Your user agent does not support the HTML5 Video element.</p>
</video>
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,73 @@
// PARSER: 0.1 TTXT
(function (Popcorn) {
/**
* TTXT popcorn parser plug-in
* Parses subtitle files in the TTXT format.
* Style information is ignored.
* Data parameter is given by Popcorn, will need an xml.
* Xml is the file contents to be parsed as a DOM tree
*
* @param {Object} data
*
* Example:
<TextSample sampleTime="00:00:00.000" text=""></TextSample>
*/
Popcorn.parser( "parseTTXT", function( data ) {
// declare needed variables
var returnData = {
title: "",
remote: "",
data: []
};
// Simple function to convert HH:MM:SS.MMM to SS.MMM
// Assume valid, returns 0 on error
var toSeconds = function(t_in) {
var t = t_in.split(":");
var time = 0;
try {
return parseFloat(t[0], 10)*60*60 + parseFloat(t[1], 10)*60 + parseFloat(t[2], 10);
} catch (e) { time = 0; }
return time;
};
// creates an object of all atrributes keyed by name
var createTrack = function( name, attributes ) {
var track = {};
track[name] = attributes;
return track;
};
// this is where things actually start
var node = data.xml.lastChild.lastChild; // Last Child of TextStreamHeader
var lastStart = Number.MAX_VALUE;
var cmds = [];
// Work backwards through DOM, processing TextSample nodes
while (node) {
if ( node.nodeType === 1 && node.nodeName === "TextSample") {
var sub = {};
sub.start = toSeconds(node.getAttribute('sampleTime'));
sub.text = node.getAttribute('text');
if (sub.text) { // Only process if text to display
// Infer end time from prior element, ms accuracy
sub.end = lastStart - 0.001;
cmds.push( createTrack("subtitle", sub) );
}
lastStart = sub.start;
}
node = node.previousSibling;
}
returnData.data = cmds.reverse();
return returnData;
});
})( Popcorn );

Просмотреть файл

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<head>
<title>Popcorn 0.3 TTXT parser Plug-in Test</title>
<link rel="stylesheet" href="../../test/qunit/qunit.css" type="text/css" media="screen">
<script src="../../test/qunit/qunit.js"></script>
<!--
do not move - this must be called immediately prior to
popcorn-api-draft.js
-->
<script src="../../popcorn.js"></script>
<script src="popcorn.parseTTXT.js"></script>
<script src="../../plugins/subtitle/popcorn.subtitle.js"></script>
<script src="popcorn.parseTTXT.unit.js"></script>
</head>
<body>
<h1 id="qunit-header">Popcorn 0.3 TTXT parser Plug-in Test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"> </div>
<video id='video'
controls
width= '250px'
data-timeline-sources="data/data.ttxt"
poster="../../test/poster.png">
<source id='mp4'
src="../../test/trailer.mp4"
type='video/mp4; codecs="avc1, mp4a"'>
<source id='ogv'
src="../../test/trailer.ogv"
type='video/ogg; codecs="theora, vorbis"'>
<p>Your user agent does not support the HTML5 Video element.</p>
</video>
</body>
</html>

Просмотреть файл

@ -0,0 +1,61 @@
test("Popcorn 0.3 TTXT Parser Plugin", function () {
var expects = 0,
count = 0,
sub = {},
numSubs = 0,
poppercorn = Popcorn( "#video" ),
subs = [ // Expected values
{
start: 2.4,
end: 5.199,
text: "[Background Music Playing]"
},
{
start: 15.712,
end: 17.398,
text: "Heay!!"
},
{
start: 25.712,
end: 30.398,
text: "[Bird noises]"
}
];
function plus() {
if ( ++count === expects ) {
start();
}
}
poppercorn.parseTTXT(document.getElementById('video').getAttribute('data-timeline-sources'));
expects = subs.length*3+1;
expect(expects);
stop( 5000 );
// Allow load time
setTimeout(function () {
Popcorn.forEach(poppercorn.getTrackEvents(), function(evt) {
if(evt._natives.type === "subtitle") {
sub = subs[numSubs++];
equals(sub.end, evt.end , "Correct end" );
plus();
equals(sub.start, evt.start , "Correct start" );
plus();
equals(sub.text, evt.text , "Correct text" );
plus();
}
});
equals(subs.length, numSubs , "Correctly parsed all subs" );
plus();
}, 500);
});

Просмотреть файл

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<title>Popcorn 0.1 parser Plug-in Demo</title>
<script src="../../popcorn.js"></script>
<script src="../../test/jquery.js"></script>
<script src="../../plugins/flickr/popcorn.flickr.js"></script>
<script src="popcorn.parseXML.js"></script>
</head>
<body>
<h1 id="qunit-header">Popcorn 0.1 parser Plug-in Demo</h1>
<p></p>
<div>
<video data-timeline-sources="data/data.XML"
controls
width= '250px'
poster="../../test/poster.png">
<source id='mp4'
src="../../test/trailer.mp4"
type='video/mp4; codecs="avc1, mp4a"'>
<source id='ogv'
src="../../test/trailer.ogv"
type='video/ogg; codecs="theora, vorbis"'>
<p>Your user agent does not support the HTML5 Video element.</p>
</video>
</div>
<div id="flickrdiv"></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,121 @@
// PARSER: 0.1 XML
(function (Popcorn) {
/**
*
*
*/
Popcorn.parser( "parseXML", "XML", function( data ) {
// declare needed variables
var returnData = {
title: "",
remote: "",
data: []
},
manifestData = {};
// Simple function to convert 0:05 to 0.5 in seconds
// acceptable formats are HH:MM:SS:MM, MM:SS:MM, SS:MM, SS
var toSeconds = function(time) {
var t = time.split(":");
if (t.length === 1) {
return parseFloat(t[0], 10);
} else if (t.length === 2) {
return parseFloat(t[0], 10) + parseFloat(t[1] / 12, 10);
} else if (t.length === 3) {
return parseInt(t[0] * 60, 10) + parseFloat(t[1], 10) + parseFloat(t[2] / 12, 10);
} else if (t.length === 4) {
return parseInt(t[0] * 3600, 10) + parseInt(t[1] * 60, 10) + parseFloat(t[2], 10) + parseFloat(t[3] / 12, 10);
}
};
// turns a node tree element into a straight up javascript object
// also converts in and out to start and end
// also links manifest data with ids
var objectifyAttributes = function ( nodeAttributes ) {
var returnObject = {};
for ( var i = 0, nal = nodeAttributes.length; i < nal; i++ ) {
var key = nodeAttributes.item(i).nodeName,
data = nodeAttributes.item(i).nodeValue;
// converts in into start
if (key === "in") {
returnObject.start = toSeconds( data );
// converts out into end
} else if ( key === "out" ){
returnObject.end = toSeconds( data );
// this is where ids in the manifest are linked
} else if ( key === "resourceid" ) {
Popcorn.extend( returnObject, manifestData[data] );
// everything else
} else {
returnObject[key] = data;
}
}
return returnObject;
};
// creates an object of all atrributes keyd by name
var createTrack = function( name, attributes ) {
var track = {};
track[name] = attributes;
return track;
};
// recursive function to process a node, or process the next child node
var parseNode = function ( node, allAttributes, manifest ) {
var attributes = {};
Popcorn.extend( attributes, allAttributes, objectifyAttributes( node.attributes ), { text: node.textContent } );
var childNodes = node.childNodes;
// processes the node
if ( childNodes.length < 1 || ( childNodes.length === 1 && childNodes[0].nodeType === 3 ) ) {
if ( !manifest ) {
returnData.data.push( createTrack( node.nodeName, attributes ) );
} else {
manifestData[attributes.id] = attributes;
}
// process the next child node
} else {
for ( var i = 0; i < childNodes.length; i++ ) {
if ( childNodes[i].nodeType === 1 ) {
parseNode( childNodes[i], attributes, manifest );
}
}
}
};
// this is where things actually start
var x = data.documentElement.childNodes;
for ( var i = 0, xl = x.length; i < xl; i++ ) {
if ( x[i].nodeType === 1 ) {
// start the process of each main node type, manifest or timeline
if ( x[i].nodeName === "manifest" ) {
parseNode( x[i], {}, true );
} else { // timeline
parseNode( x[i], {}, false );
}
}
}
return returnData;
});
})( Popcorn );

Просмотреть файл

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<title>Popcorn 0.1 parser Plug-in Test</title>
<link rel="stylesheet" href="../../test/qunit/qunit.css" type="text/css" media="screen">
<script src="../../test/qunit/qunit.js"></script>
<!--
do not move - this must be called immediately prior to
popcorn-api-draft.js
-->
<script src="../../popcorn.js"></script>
<script src="popcorn.parseXML.js"></script>
<script src="popcorn.parseXML.unit.js"></script>
</head>
<body>
<h1 id="qunit-header">Popcorn 0.1 parser Plug-in Test</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"> </div>
<video id='video'
controls
width= '250px'
poster="../../test/poster.png">
<source id='mp4'
src="../../test/trailer.mp4"
type='video/mp4; codecs="avc1, mp4a"'>
<source id='ogv'
src="../../test/trailer.ogv"
type='video/ogg; codecs="theora, vorbis"'>
<p>Your user agent does not support the HTML5 Video element.</p>
</video>
<div id="footnotediv"></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,63 @@
test("Popcorn 0.1 XML Parser Plugin", function () {
var expects = 7,
count = 0,
timeOut = 0,
interval,
poppercorn = Popcorn( "#video" );
function plus() {
if ( ++count === expects ) {
start();
// clean up added events after tests
clearInterval( interval );
}
}
expect(expects);
stop( 10000 );
Popcorn.plugin("parserTest1", {
start: function ( event, options ) {
ok( options.item2 === "item2", "parserTest1 has data directly from manifest" );
plus();
ok( options.item3 === "item3", "parserTest1 has cascading data from manifest" );
plus();
},
end: function ( event, options ) {}
});
Popcorn.plugin("parserTest2", {
start: function ( event, options ) {
ok( options.text === "item4", "parserTest2 has text data" );
plus();
ok( options.item1 === "item1", "parserTest2 has cascading data from parent" );
plus();
},
end: function ( event, options ) {}
});
Popcorn.plugin("parserTest3", {
start: function ( event, options ) {
ok( options.item1 === "item1", "parserTest3 has cascading data from parent" );
plus();
ok( options.item2 === "item2", "parserTest3 has data directly from manifest" );
plus();
ok( options.item3 === "item3", "parserTest3 has cascading data from manifest" );
plus();
},
end: function ( event, options ) {}
});
poppercorn.parseXML("data/unit.XML");
// interval used to wait for data to be parsed
interval = setInterval( function() {
poppercorn.currentTime(5).play().currentTime(6);
}, 2000);
});