source: branches/captions/src/com/longtailvideo/plugins/captions/DFXP.as @ 1769

Revision 1769, 6.1 KB checked in by jeroen, 2 years ago (diff)

added multitrack SRT/DFXP support, cookying of language and multitrack styling. Updated tests and docs.

Line 
1package com.longtailvideo.plugins.captions {
2
3
4    import com.longtailvideo.jwplayer.utils.Strings;
5    import flash.external.ExternalInterface;
6
7
8    /** Parse styling and contents of W3C Timed Text XML files. **/
9    public class DFXP {
10
11
12        /** Name of the main XMl node. **/
13        public static const NAME:String = 'tt';
14
15
16        /** Parse stylesheets from the head. */
17        public static function parseStyles(data:XML,defaults:Object):Object {
18            var styles:Object = {};
19            for each (var i:XML in data.children()) {
20                if (i.localName() == "head") {
21                    for each (var node:XML in i.children()[0].children()) {
22                        if (node.localName() == 'style') {
23                            // Set the defaults.
24                            var rules:Object = {};
25                            for(var rule:String in defaults) {
26                                rules[rule] = defaults[rule];
27                            }
28                            // Loop through all attributes for overrides.
29                            for each (var attrib:XML in node.attributes()) {
30                                var name:String = attrib.name();
31                                if (name.indexOf("::") > -1) {
32                                    name = name.substring(name.indexOf("::") + 2);
33                                }
34                                rules[name] = attrib.toString();
35                            }
36                            // Save to listing
37                            if (node.@id) {
38                                styles[node.@id] = rules;
39                            }
40                        }
41                    }
42                }
43            }
44            return styles;
45        };
46
47
48        /** Parse captions from the TT XML, returning a list with {begin:Number,text:String} objects. **/
49        public static function parseCaptions(data:XML,style:Object):Array {
50            var styles:Object = DFXP.parseStyles(data,style);
51            var array:Array = new Array({begin:0,text:''});
52            for each (var i:XML in data.children()) {
53                if (i.localName() == "body") {
54                    for each (var j:XML in i.children()) {
55                        for each (var k:XML in j.children()) {
56                            // Paragraphs are single captions. They live inside dividers.
57                            if (k.localName() == 'p') {
58                                var entry:Object = DFXP.parseCaption(k);
59                                array.push(entry);
60                                // Amend global styling.
61                                if(entry.style && styles[entry.style]) {
62                                    entry.style = styles[entry.style];
63                                } else {
64                                    entry.style = style;
65                                }
66                                // Convert inline styles to HTML.
67                                while (entry.text.indexOf("<span") > -1) {
68                                    entry.text = DFXP.parseSpan(entry.text,styles,entry.style);
69                                }
70                                // End with a new, empty caption, accounting for duration or end set.
71                                if (entry['end']) {
72                                    array.push({begin:entry['end'],text:''});
73                                    delete entry['end'];
74                                } else if (entry['dur']) {
75                                    array.push({begin:entry['begin']+entry['dur'],text:''});
76                                    delete entry['dur'];
77                                }
78                            }
79                        }
80                    }
81                }
82            }
83            return array;
84        };
85
86
87        /** Parse a single captions entry. **/
88        private static function parseCaption(data:XML):Object {
89            var pattern:RegExp = /(\n)+/;
90            var entry:Object = {
91                begin:Strings.seconds(data.@begin),
92                dur:Strings.seconds(data.@dur),
93                end:Strings.seconds(data.@end),
94                style:data.@style.toString(),
95                text:data.children().toXMLString().replace(/\n/g,' ')
96            };
97            return entry;
98        };
99
100
101        /** Convert a span entry into HTML. **/
102        private static function parseSpan(text:String,styles:Object,defaults:Object):String {
103            var rules:Object = {};
104            var newtext:String = '';
105            // Find the span bounds and convert to XML.
106            var left:Number = text.indexOf("<span ");
107            var right:Number = text.indexOf("</span>",left);
108            if (left > -1 && right > -1) {
109                var span:XML = new XML(text.substring(left,right+7));
110                // Use style if defined, else set defaults.
111                var style:String = span.@style;
112                if(style && styles[style]) {
113                    for(var i:String in styles[style]) { rules[i] = styles[style][i]; }
114                } else {
115                    for(var j:String in defaults) { rules[j] = defaults[j]; }
116                }
117                // Override style with inline declarations
118                for each (var attrib:XML in span.@*) {
119                    var name:String = attrib.localName().toString();
120                    if (rules[name]) {
121                        rules[name] = attrib.toString();
122                    }
123                }
124                // Wrap plain text with font and b/i/u tags.
125                newtext = '<font family="'+rules.fontFamily+'" size="'+rules.fontSize+'" color="'+rules.color+'">';
126                newtext +=  text.substring(text.indexOf('>',left)+1, right);
127                newtext += "</font>";
128                if(rules.fontWeight == 'bold') { newtext = '<b>'+newtext+'</b>'; }
129                if(rules.fontStyle == 'italic') { newtext = '<i>'+newtext+'</i>'; }
130                if(rules.textDecoration == 'underline') { newtext = '<u>'+newtext+'</u>'; }
131            }
132            return text.substr(0,left)+newtext+text.substr(right+7);
133        };
134
135
136    }
137
138
139}
Note: See TracBrowser for help on using the repository browser.