shaka-player 4.10.13 → 4.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/controls.css +3 -3
- package/dist/controls.css.map +1 -1
- package/dist/deps.js +11 -11
- package/dist/locales.js +38 -34
- package/dist/shaka-player.compiled.d.ts +68 -33
- package/dist/shaka-player.compiled.debug.d.ts +68 -33
- package/dist/shaka-player.compiled.debug.externs.js +584 -544
- package/dist/shaka-player.compiled.debug.js +715 -676
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +584 -544
- package/dist/shaka-player.compiled.js +1394 -1371
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +76 -34
- package/dist/shaka-player.ui.debug.d.ts +76 -34
- package/dist/shaka-player.ui.debug.externs.js +77 -26
- package/dist/shaka-player.ui.debug.js +774 -720
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +77 -26
- package/dist/shaka-player.ui.js +1649 -1617
- package/dist/shaka-player.ui.map +4 -4
- package/externs/mediasession.js +10 -1
- package/externs/shaka/ads.js +79 -2
- package/externs/shaka/manifest.js +6 -1
- package/externs/shaka/manifest_parser.js +6 -2
- package/externs/shaka/net.js +23 -2
- package/externs/shaka/player.js +414 -103
- package/externs/shaka/text.js +2 -1
- package/lib/abr/simple_abr_manager.js +5 -0
- package/lib/ads/ad_manager.js +45 -1
- package/lib/ads/ad_utils.js +124 -1
- package/lib/ads/interstitial_ad.js +9 -2
- package/lib/ads/interstitial_ad_manager.js +216 -101
- package/lib/ads/media_tailor_ad.js +1 -39
- package/lib/ads/media_tailor_ad_manager.js +32 -16
- package/lib/cea/cea608_data_channel.js +40 -8
- package/lib/cea/cea608_memory.js +28 -0
- package/lib/dash/dash_parser.js +162 -25
- package/lib/dash/segment_base.js +3 -2
- package/lib/dash/segment_list.js +6 -3
- package/lib/dash/segment_template.js +104 -20
- package/lib/hls/hls_parser.js +319 -215
- package/lib/media/drm_engine.js +11 -3
- package/lib/media/media_source_engine.js +0 -8
- package/lib/media/preload_manager.js +16 -4
- package/lib/media/segment_reference.js +3 -0
- package/lib/media/segment_utils.js +8 -1
- package/lib/media/streaming_engine.js +10 -6
- package/lib/mss/mss_parser.js +14 -2
- package/lib/net/http_fetch_plugin.js +12 -5
- package/lib/net/http_xhr_plugin.js +7 -3
- package/lib/net/networking_engine.js +21 -1
- package/lib/offline/manifest_converter.js +1 -0
- package/lib/offline/storage.js +1 -0
- package/lib/player.js +336 -121
- package/lib/text/cue.js +373 -0
- package/lib/text/mp4_ttml_parser.js +51 -1
- package/lib/text/mp4_vtt_parser.js +2 -5
- package/lib/text/sbv_text_parser.js +2 -31
- package/lib/text/srt_text_parser.js +1 -1
- package/lib/text/text_engine.js +1 -1
- package/lib/text/text_utils.js +1 -0
- package/lib/text/ttml_text_parser.js +14 -4
- package/lib/text/ui_text_displayer.js +0 -4
- package/lib/text/vtt_text_parser.js +10 -415
- package/lib/util/abortable_operation.js +8 -0
- package/lib/util/cmcd_manager.js +38 -0
- package/lib/util/error.js +16 -0
- package/lib/util/fake_event.js +1 -0
- package/lib/util/manifest_parser_utils.js +12 -3
- package/lib/util/player_configuration.js +4 -2
- package/lib/util/stream_utils.js +57 -2
- package/lib/util/tXml.js +2 -1
- package/lib/util/text_parser.js +46 -0
- package/lib/util/ts_parser.js +32 -3
- package/package.json +1 -1
- package/shaka-player.uncompiled.js +1 -1
- package/ui/chapter_selection.js +179 -0
- package/ui/controls.js +151 -0
- package/ui/enums.js +1 -0
- package/ui/externs/ui.js +7 -1
- package/ui/less/containers.less +3 -4
- package/ui/less/overflow_menu.less +5 -0
- package/ui/less/tooltip.less +1 -1
- package/ui/locales/en.json +1 -0
- package/ui/locales/es.json +1 -0
- package/ui/locales/fr.json +1 -0
- package/ui/locales/source.json +4 -0
- package/ui/seek_bar.js +3 -2
- package/ui/ui.js +2 -0
- package/lib/polyfill/abort_controller.js +0 -158
|
@@ -15,7 +15,6 @@ goog.require('shaka.text.TextEngine');
|
|
|
15
15
|
goog.require('shaka.util.Error');
|
|
16
16
|
goog.require('shaka.util.StringUtils');
|
|
17
17
|
goog.require('shaka.util.TextParser');
|
|
18
|
-
goog.require('shaka.util.TXml');
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
/**
|
|
@@ -106,9 +105,9 @@ shaka.text.VttTextParser = class {
|
|
|
106
105
|
}
|
|
107
106
|
}
|
|
108
107
|
|
|
109
|
-
/** @type {!Map.<string, shaka.text.Cue>} */
|
|
108
|
+
/** @type {!Map.<string, !shaka.text.Cue>} */
|
|
110
109
|
const styles = new Map();
|
|
111
|
-
|
|
110
|
+
shaka.text.Cue.addDefaultTextColor(styles);
|
|
112
111
|
|
|
113
112
|
// Parse cues.
|
|
114
113
|
const ret = [];
|
|
@@ -151,8 +150,7 @@ shaka.text.VttTextParser = class {
|
|
|
151
150
|
shaka.util.Error.Code.INVALID_TEXT_HEADER);
|
|
152
151
|
}
|
|
153
152
|
|
|
154
|
-
const
|
|
155
|
-
const cueTime = shaka.text.VttTextParser.parseTime_(parser);
|
|
153
|
+
const cueTime = shaka.util.TextParser.parseTime(cueTimeMatch[1]);
|
|
156
154
|
if (cueTime == null) {
|
|
157
155
|
throw new shaka.util.Error(
|
|
158
156
|
shaka.util.Error.Severity.CRITICAL,
|
|
@@ -174,28 +172,6 @@ shaka.text.VttTextParser = class {
|
|
|
174
172
|
return time.periodStart + mpegTime / mpegTimescale - cueTime;
|
|
175
173
|
}
|
|
176
174
|
|
|
177
|
-
/**
|
|
178
|
-
* Add default color
|
|
179
|
-
*
|
|
180
|
-
* @param {!Map.<string, shaka.text.Cue>} styles
|
|
181
|
-
* @private
|
|
182
|
-
*/
|
|
183
|
-
static addDefaultTextColor_(styles) {
|
|
184
|
-
const textColor = shaka.text.Cue.defaultTextColor;
|
|
185
|
-
for (const [key, value] of Object.entries(textColor)) {
|
|
186
|
-
const cue = new shaka.text.Cue(0, 0, '');
|
|
187
|
-
cue.color = value;
|
|
188
|
-
styles.set('.' + key, cue);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const bgColor = shaka.text.Cue.defaultTextBackgroundColor;
|
|
192
|
-
for (const [key, value] of Object.entries(bgColor)) {
|
|
193
|
-
const cue = new shaka.text.Cue(0, 0, '');
|
|
194
|
-
cue.backgroundColor = value;
|
|
195
|
-
styles.set('.' + key, cue);
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
175
|
/**
|
|
200
176
|
* Parses a string into a Region object.
|
|
201
177
|
*
|
|
@@ -233,7 +209,7 @@ shaka.text.VttTextParser = class {
|
|
|
233
209
|
* Parses a style block into a Cue object.
|
|
234
210
|
*
|
|
235
211
|
* @param {!Array.<string>} text
|
|
236
|
-
* @param {!Map.<string, shaka.text.Cue>} styles
|
|
212
|
+
* @param {!Map.<string, !shaka.text.Cue>} styles
|
|
237
213
|
* @private
|
|
238
214
|
*/
|
|
239
215
|
static parseStyle_(text, styles) {
|
|
@@ -380,7 +356,7 @@ shaka.text.VttTextParser = class {
|
|
|
380
356
|
* @param {!Array.<string>} text
|
|
381
357
|
* @param {number} timeOffset
|
|
382
358
|
* @param {!Array.<!shaka.text.CueRegion>} regions
|
|
383
|
-
* @param {!Map.<string, shaka.text.Cue>} styles
|
|
359
|
+
* @param {!Map.<string, !shaka.text.Cue>} styles
|
|
384
360
|
* @return {shaka.text.Cue}
|
|
385
361
|
* @private
|
|
386
362
|
*/
|
|
@@ -410,9 +386,9 @@ shaka.text.VttTextParser = class {
|
|
|
410
386
|
|
|
411
387
|
// Parse the times.
|
|
412
388
|
const parser = new shaka.util.TextParser(text[0]);
|
|
413
|
-
let start =
|
|
389
|
+
let start = parser.parseTime();
|
|
414
390
|
const expect = parser.readRegex(/[ \t]+-->[ \t]+/g);
|
|
415
|
-
let end =
|
|
391
|
+
let end = parser.parseTime();
|
|
416
392
|
|
|
417
393
|
if (start == null || expect == null || end == null) {
|
|
418
394
|
shaka.log.alwaysWarn(
|
|
@@ -431,9 +407,9 @@ shaka.text.VttTextParser = class {
|
|
|
431
407
|
cue = styles.get('global').clone();
|
|
432
408
|
cue.startTime = start;
|
|
433
409
|
cue.endTime = end;
|
|
434
|
-
cue.payload =
|
|
410
|
+
cue.payload = payload;
|
|
435
411
|
} else {
|
|
436
|
-
cue = new shaka.text.Cue(start, end,
|
|
412
|
+
cue = new shaka.text.Cue(start, end, payload);
|
|
437
413
|
}
|
|
438
414
|
|
|
439
415
|
// Parse optional settings.
|
|
@@ -449,7 +425,7 @@ shaka.text.VttTextParser = class {
|
|
|
449
425
|
word = parser.readWord();
|
|
450
426
|
}
|
|
451
427
|
|
|
452
|
-
|
|
428
|
+
shaka.text.Cue.parseCuePayload(cue, styles);
|
|
453
429
|
|
|
454
430
|
if (id != null) {
|
|
455
431
|
cue.id = id;
|
|
@@ -457,353 +433,6 @@ shaka.text.VttTextParser = class {
|
|
|
457
433
|
return cue;
|
|
458
434
|
}
|
|
459
435
|
|
|
460
|
-
/**
|
|
461
|
-
* Parses a WebVTT styles from the given payload.
|
|
462
|
-
*
|
|
463
|
-
* @param {string} payload
|
|
464
|
-
* @param {!shaka.text.Cue} rootCue
|
|
465
|
-
* @param {!Map.<string, shaka.text.Cue>} styles
|
|
466
|
-
*/
|
|
467
|
-
static parseCueStyles(payload, rootCue, styles) {
|
|
468
|
-
const VttTextParser = shaka.text.VttTextParser;
|
|
469
|
-
const StringUtils = shaka.util.StringUtils;
|
|
470
|
-
const TXml = shaka.util.TXml;
|
|
471
|
-
// Optimization for unstyled payloads.
|
|
472
|
-
if (!payload.includes('<')) {
|
|
473
|
-
rootCue.payload = StringUtils.htmlUnescape(payload);
|
|
474
|
-
return;
|
|
475
|
-
}
|
|
476
|
-
if (styles.size === 0) {
|
|
477
|
-
VttTextParser.addDefaultTextColor_(styles);
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
payload = VttTextParser.replaceKaraokeStylePayload_(payload);
|
|
481
|
-
payload = VttTextParser.replaceVoiceStylePayload_(payload);
|
|
482
|
-
payload = VttTextParser.escapeInvalidChevrons_(payload);
|
|
483
|
-
const xmlPayload = '<span>' + payload + '</span>';
|
|
484
|
-
let element;
|
|
485
|
-
try {
|
|
486
|
-
element = TXml.parseXmlString(xmlPayload, 'span');
|
|
487
|
-
} catch (e) {
|
|
488
|
-
shaka.log.warning('cue parse fail: ', e);
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
if (element) {
|
|
492
|
-
const childNodes = element.children;
|
|
493
|
-
if (childNodes.length == 1) {
|
|
494
|
-
const childNode = childNodes[0];
|
|
495
|
-
if (!TXml.isNode(childNode)) {
|
|
496
|
-
rootCue.payload = StringUtils.htmlUnescape(payload);
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
for (const childNode of childNodes) {
|
|
501
|
-
VttTextParser.generateCueFromElement_(childNode, rootCue, styles);
|
|
502
|
-
}
|
|
503
|
-
} else {
|
|
504
|
-
shaka.log.warning('The cue\'s markup could not be parsed: ', payload);
|
|
505
|
-
rootCue.payload = StringUtils.htmlUnescape(payload);
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
/**
|
|
510
|
-
* This method converts invalid > chevrons to HTML entities.
|
|
511
|
-
* It also removes < chevrons as per spec.
|
|
512
|
-
*
|
|
513
|
-
* @param {!string} input
|
|
514
|
-
* @return {string}
|
|
515
|
-
* @private
|
|
516
|
-
*/
|
|
517
|
-
static escapeInvalidChevrons_(input) {
|
|
518
|
-
// Used to map HTML entities to characters.
|
|
519
|
-
const htmlEscapes = {
|
|
520
|
-
'< ': '',
|
|
521
|
-
' >': ' >',
|
|
522
|
-
};
|
|
523
|
-
|
|
524
|
-
const reEscapedHtml = /(< +>|<\s|\s>)/g;
|
|
525
|
-
const reHasEscapedHtml = RegExp(reEscapedHtml.source);
|
|
526
|
-
// This check is an optimization, since replace always makes a copy
|
|
527
|
-
if (input && reHasEscapedHtml.test(input)) {
|
|
528
|
-
return input.replace(reEscapedHtml, (entity) => {
|
|
529
|
-
return htmlEscapes[entity] || '';
|
|
530
|
-
});
|
|
531
|
-
}
|
|
532
|
-
return input || '';
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
/**
|
|
536
|
-
* Converts voice style tag to be valid for xml parsing
|
|
537
|
-
* For example,
|
|
538
|
-
* input: <v Shaka>Test
|
|
539
|
-
* output: <v.voice-Shaka>Test</v.voice-Shaka>
|
|
540
|
-
*
|
|
541
|
-
* @param {string} payload
|
|
542
|
-
* @return {string} processed payload
|
|
543
|
-
* @private
|
|
544
|
-
*/
|
|
545
|
-
static replaceVoiceStylePayload_(payload) {
|
|
546
|
-
const voiceTag = 'v';
|
|
547
|
-
const names = [];
|
|
548
|
-
let nameStart = -1;
|
|
549
|
-
let newPayload = '';
|
|
550
|
-
let hasVoiceEndTag = false;
|
|
551
|
-
for (let i = 0; i < payload.length; i++) {
|
|
552
|
-
// This condition is used to manage tags that have end tags.
|
|
553
|
-
if (payload[i] === '/') {
|
|
554
|
-
const end = payload.indexOf('>', i);
|
|
555
|
-
if (end === -1) {
|
|
556
|
-
return payload;
|
|
557
|
-
}
|
|
558
|
-
const tagEnd = payload.substring(i + 1, end);
|
|
559
|
-
if (!tagEnd || tagEnd != voiceTag) {
|
|
560
|
-
newPayload += payload[i];
|
|
561
|
-
continue;
|
|
562
|
-
}
|
|
563
|
-
hasVoiceEndTag = true;
|
|
564
|
-
let tagStart = null;
|
|
565
|
-
if (names.length) {
|
|
566
|
-
tagStart = names[names.length -1];
|
|
567
|
-
}
|
|
568
|
-
if (!tagStart) {
|
|
569
|
-
newPayload += payload[i];
|
|
570
|
-
} else if (tagStart === tagEnd) {
|
|
571
|
-
newPayload += '/' + tagEnd + '>';
|
|
572
|
-
i += tagEnd.length + 1;
|
|
573
|
-
} else {
|
|
574
|
-
if (!tagStart.startsWith(voiceTag)) {
|
|
575
|
-
newPayload += payload[i];
|
|
576
|
-
continue;
|
|
577
|
-
}
|
|
578
|
-
newPayload += '/' + tagStart + '>';
|
|
579
|
-
i += tagEnd.length + 1;
|
|
580
|
-
}
|
|
581
|
-
} else {
|
|
582
|
-
// Here we only want the tag name, not any other payload.
|
|
583
|
-
if (payload[i] === '<') {
|
|
584
|
-
nameStart = i + 1;
|
|
585
|
-
if (payload[nameStart] != voiceTag) {
|
|
586
|
-
nameStart = -1;
|
|
587
|
-
}
|
|
588
|
-
} else if (payload[i] === '>') {
|
|
589
|
-
if (nameStart > 0) {
|
|
590
|
-
names.push(payload.substr(nameStart, i - nameStart));
|
|
591
|
-
nameStart = -1;
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
newPayload += payload[i];
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
for (const name of names) {
|
|
598
|
-
const newName = name.replace(' ', '.voice-');
|
|
599
|
-
newPayload = newPayload.replace(`<${name}>`, `<${newName}>`);
|
|
600
|
-
newPayload = newPayload.replace(`</${name}>`, `</${newName}>`);
|
|
601
|
-
if (!hasVoiceEndTag) {
|
|
602
|
-
newPayload += `</${newName}>`;
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
return newPayload;
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
/**
|
|
609
|
-
* Converts karaoke style tag to be valid for xml parsing
|
|
610
|
-
* For example,
|
|
611
|
-
* input: Text <00:00:00.450> time <00:00:01.450> 1
|
|
612
|
-
* output: Text <div time="00:00:00.450"> time
|
|
613
|
-
* <div time="00:00:01.450"> 1</div></div>
|
|
614
|
-
*
|
|
615
|
-
* @param {string} payload
|
|
616
|
-
* @return {string} processed payload
|
|
617
|
-
* @private
|
|
618
|
-
*/
|
|
619
|
-
static replaceKaraokeStylePayload_(payload) {
|
|
620
|
-
const names = [];
|
|
621
|
-
let nameStart = -1;
|
|
622
|
-
for (let i = 0; i < payload.length; i++) {
|
|
623
|
-
if (payload[i] === '<') {
|
|
624
|
-
nameStart = i + 1;
|
|
625
|
-
} else if (payload[i] === '>') {
|
|
626
|
-
if (nameStart > 0) {
|
|
627
|
-
const name = payload.substr(nameStart, i - nameStart);
|
|
628
|
-
if (name.match(shaka.text.VttTextParser.timeFormat_)) {
|
|
629
|
-
names.push(name);
|
|
630
|
-
}
|
|
631
|
-
nameStart = -1;
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
let newPayload = payload;
|
|
636
|
-
for (const name of names) {
|
|
637
|
-
const replaceTag = '<' + name + '>';
|
|
638
|
-
const startTag = '<div time="' + name + '">';
|
|
639
|
-
const endTag = '</div>';
|
|
640
|
-
newPayload = newPayload.replace(replaceTag, startTag);
|
|
641
|
-
newPayload += endTag;
|
|
642
|
-
}
|
|
643
|
-
return newPayload;
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
/**
|
|
647
|
-
* @param {string} value
|
|
648
|
-
* @param {string} defaultValue
|
|
649
|
-
* @private
|
|
650
|
-
*/
|
|
651
|
-
static getOrDefault_(value, defaultValue) {
|
|
652
|
-
if (value && value.length > 0) {
|
|
653
|
-
return value;
|
|
654
|
-
}
|
|
655
|
-
return defaultValue;
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
/**
|
|
659
|
-
* Merges values created in parseStyle_
|
|
660
|
-
* @param {!shaka.text.Cue} cue
|
|
661
|
-
* @param {shaka.text.Cue} refCue
|
|
662
|
-
* @private
|
|
663
|
-
*/
|
|
664
|
-
static mergeStyle_(cue, refCue) {
|
|
665
|
-
if (!refCue) {
|
|
666
|
-
return;
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
const VttTextParser = shaka.text.VttTextParser;
|
|
670
|
-
// Overwrites if new value string length > 0
|
|
671
|
-
cue.backgroundColor = VttTextParser.getOrDefault_(
|
|
672
|
-
refCue.backgroundColor, cue.backgroundColor);
|
|
673
|
-
cue.color = VttTextParser.getOrDefault_(
|
|
674
|
-
refCue.color, cue.color);
|
|
675
|
-
cue.fontFamily = VttTextParser.getOrDefault_(
|
|
676
|
-
refCue.fontFamily, cue.fontFamily);
|
|
677
|
-
cue.fontSize = VttTextParser.getOrDefault_(
|
|
678
|
-
refCue.fontSize, cue.fontSize);
|
|
679
|
-
cue.textShadow = VttTextParser.getOrDefault_(
|
|
680
|
-
refCue.textShadow, cue.textShadow);
|
|
681
|
-
|
|
682
|
-
// Overwrite with new values as unable to determine
|
|
683
|
-
// if new value is set or not
|
|
684
|
-
cue.fontWeight = refCue.fontWeight;
|
|
685
|
-
cue.fontStyle = refCue.fontStyle;
|
|
686
|
-
cue.opacity = refCue.opacity;
|
|
687
|
-
cue.rubyTag = refCue.rubyTag;
|
|
688
|
-
cue.textCombineUpright = refCue.textCombineUpright;
|
|
689
|
-
cue.wrapLine = refCue.wrapLine;
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
/**
|
|
693
|
-
* @param {!shaka.extern.xml.Node} element
|
|
694
|
-
* @param {!shaka.text.Cue} rootCue
|
|
695
|
-
* @param {!Map.<string, shaka.text.Cue>} styles
|
|
696
|
-
* @private
|
|
697
|
-
*/
|
|
698
|
-
static generateCueFromElement_(element, rootCue, styles) {
|
|
699
|
-
const VttTextParser = shaka.text.VttTextParser;
|
|
700
|
-
const TXml = shaka.util.TXml;
|
|
701
|
-
const nestedCue = rootCue.clone();
|
|
702
|
-
// We don't want propagate some properties.
|
|
703
|
-
nestedCue.nestedCues = [];
|
|
704
|
-
nestedCue.payload = '';
|
|
705
|
-
nestedCue.rubyTag = '';
|
|
706
|
-
// We don't want propagate some position settings
|
|
707
|
-
nestedCue.line = null;
|
|
708
|
-
nestedCue.region = new shaka.text.CueRegion();
|
|
709
|
-
nestedCue.position = null;
|
|
710
|
-
nestedCue.size = 0;
|
|
711
|
-
|
|
712
|
-
if (shaka.util.TXml.isNode(element)) {
|
|
713
|
-
const bold = shaka.text.Cue.fontWeight.BOLD;
|
|
714
|
-
const italic = shaka.text.Cue.fontStyle.ITALIC;
|
|
715
|
-
const underline = shaka.text.Cue.textDecoration.UNDERLINE;
|
|
716
|
-
const tags = element.tagName.split(/(?=[ .])+/g);
|
|
717
|
-
for (const tag of tags) {
|
|
718
|
-
let styleTag = tag;
|
|
719
|
-
// White blanks at start indicate that the style is a voice
|
|
720
|
-
if (styleTag.startsWith('.voice-')) {
|
|
721
|
-
const voice = styleTag.split('-').pop();
|
|
722
|
-
styleTag = `v[voice="${voice}"]`;
|
|
723
|
-
// The specification allows to have quotes and not, so we check to
|
|
724
|
-
// see which one is being used.
|
|
725
|
-
if (!styles.has(styleTag)) {
|
|
726
|
-
styleTag = `v[voice=${voice}]`;
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
if (styles.has(styleTag)) {
|
|
730
|
-
VttTextParser.mergeStyle_(nestedCue, styles.get(styleTag));
|
|
731
|
-
}
|
|
732
|
-
switch (tag) {
|
|
733
|
-
case 'br': {
|
|
734
|
-
const lineBreakCue = shaka.text.Cue.lineBreak(
|
|
735
|
-
nestedCue.startTime, nestedCue.endTime);
|
|
736
|
-
rootCue.nestedCues.push(lineBreakCue);
|
|
737
|
-
return;
|
|
738
|
-
}
|
|
739
|
-
case 'b':
|
|
740
|
-
nestedCue.fontWeight = bold;
|
|
741
|
-
break;
|
|
742
|
-
case 'i':
|
|
743
|
-
nestedCue.fontStyle = italic;
|
|
744
|
-
break;
|
|
745
|
-
case 'u':
|
|
746
|
-
nestedCue.textDecoration.push(underline);
|
|
747
|
-
break;
|
|
748
|
-
case 'font': {
|
|
749
|
-
const color = element.attributes['color'];
|
|
750
|
-
if (color) {
|
|
751
|
-
nestedCue.color = color;
|
|
752
|
-
}
|
|
753
|
-
break;
|
|
754
|
-
}
|
|
755
|
-
case 'div': {
|
|
756
|
-
const time = element.attributes['time'];
|
|
757
|
-
if (!time) {
|
|
758
|
-
break;
|
|
759
|
-
}
|
|
760
|
-
const parser = new shaka.util.TextParser(time);
|
|
761
|
-
const cueTime = shaka.text.VttTextParser.parseTime_(parser);
|
|
762
|
-
if (cueTime) {
|
|
763
|
-
nestedCue.startTime = cueTime;
|
|
764
|
-
}
|
|
765
|
-
break;
|
|
766
|
-
}
|
|
767
|
-
case 'ruby':
|
|
768
|
-
case 'rp':
|
|
769
|
-
case 'rt':
|
|
770
|
-
nestedCue.rubyTag = tag;
|
|
771
|
-
break;
|
|
772
|
-
default:
|
|
773
|
-
break;
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
const isTextNode = (item) => shaka.util.TXml.isText(item);
|
|
779
|
-
const childNodes = element.children;
|
|
780
|
-
if (isTextNode(element) ||
|
|
781
|
-
(childNodes.length == 1 && isTextNode(childNodes[0]))) {
|
|
782
|
-
// Trailing line breaks may lost when convert cue to HTML tag
|
|
783
|
-
// Need to insert line break cue to preserve line breaks
|
|
784
|
-
const textArr = TXml.getTextContents(element).split('\n');
|
|
785
|
-
let isFirst = true;
|
|
786
|
-
for (const text of textArr) {
|
|
787
|
-
if (!isFirst) {
|
|
788
|
-
const lineBreakCue = shaka.text.Cue.lineBreak(
|
|
789
|
-
nestedCue.startTime, nestedCue.endTime);
|
|
790
|
-
rootCue.nestedCues.push(lineBreakCue);
|
|
791
|
-
}
|
|
792
|
-
if (text.length > 0) {
|
|
793
|
-
const textCue = nestedCue.clone();
|
|
794
|
-
textCue.payload = shaka.util.StringUtils.htmlUnescape(text);
|
|
795
|
-
rootCue.nestedCues.push(textCue);
|
|
796
|
-
}
|
|
797
|
-
isFirst = false;
|
|
798
|
-
}
|
|
799
|
-
} else {
|
|
800
|
-
rootCue.nestedCues.push(nestedCue);
|
|
801
|
-
for (const childNode of childNodes) {
|
|
802
|
-
VttTextParser.generateCueFromElement_(childNode, nestedCue, styles);
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
|
|
807
436
|
/**
|
|
808
437
|
* Parses a WebVTT setting from the given word.
|
|
809
438
|
*
|
|
@@ -982,31 +611,6 @@ shaka.text.VttTextParser = class {
|
|
|
982
611
|
|
|
983
612
|
return true;
|
|
984
613
|
}
|
|
985
|
-
|
|
986
|
-
/**
|
|
987
|
-
* Parses a WebVTT time from the given parser.
|
|
988
|
-
*
|
|
989
|
-
* @param {!shaka.util.TextParser} parser
|
|
990
|
-
* @return {?number}
|
|
991
|
-
* @private
|
|
992
|
-
*/
|
|
993
|
-
static parseTime_(parser) {
|
|
994
|
-
const results = parser.readRegex(shaka.text.VttTextParser.timeFormat_);
|
|
995
|
-
if (results == null) {
|
|
996
|
-
return null;
|
|
997
|
-
}
|
|
998
|
-
// This capture is optional, but will still be in the array as undefined,
|
|
999
|
-
// in which case it is 0.
|
|
1000
|
-
const hours = Number(results[1]) || 0;
|
|
1001
|
-
const minutes = Number(results[2]);
|
|
1002
|
-
const seconds = Number(results[3]);
|
|
1003
|
-
const milliseconds = Number(results[4]);
|
|
1004
|
-
if (minutes > 59 || seconds > 59) {
|
|
1005
|
-
return null;
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
return (milliseconds / 1000) + seconds + (minutes * 60) + (hours * 3600);
|
|
1009
|
-
}
|
|
1010
614
|
};
|
|
1011
615
|
|
|
1012
616
|
/**
|
|
@@ -1022,15 +626,6 @@ shaka.text.VttTextParser.MPEG_TIMESCALE_ = 90000;
|
|
|
1022
626
|
*/
|
|
1023
627
|
shaka.text.VttTextParser.TS_ROLLOVER_ = 0x200000000;
|
|
1024
628
|
|
|
1025
|
-
/**
|
|
1026
|
-
* @const
|
|
1027
|
-
* @private {!RegExp}
|
|
1028
|
-
* @example 00:00.000 or 00:00:00.000 or 0:00:00.000 or
|
|
1029
|
-
* 00:00.00 or 00:00:00.00 or 0:00:00.00
|
|
1030
|
-
*/
|
|
1031
|
-
shaka.text.VttTextParser.timeFormat_ =
|
|
1032
|
-
/(?:(\d{1,}):)?(\d{2}):(\d{2})\.(\d{2,3})/g;
|
|
1033
|
-
|
|
1034
629
|
shaka.text.TextEngine.registerParser(
|
|
1035
630
|
'text/vtt', () => new shaka.text.VttTextParser());
|
|
1036
631
|
|
|
@@ -43,6 +43,14 @@ shaka.util.AbortableOperation = class {
|
|
|
43
43
|
this.aborted_ = false;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* @return {boolean} True if the operation has been aborted.
|
|
48
|
+
* @export
|
|
49
|
+
*/
|
|
50
|
+
get aborted() {
|
|
51
|
+
return this.aborted_;
|
|
52
|
+
}
|
|
53
|
+
|
|
46
54
|
/**
|
|
47
55
|
* @param {!shaka.util.Error} error
|
|
48
56
|
* @return {!shaka.util.AbortableOperation} An operation which has already
|
package/lib/util/cmcd_manager.js
CHANGED
|
@@ -51,6 +51,11 @@ shaka.util.CmcdManager = class {
|
|
|
51
51
|
* @private {boolean}
|
|
52
52
|
*/
|
|
53
53
|
this.starved_ = false;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @private {boolean}
|
|
57
|
+
*/
|
|
58
|
+
this.lowLatency_ = false;
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
/**
|
|
@@ -71,6 +76,7 @@ shaka.util.CmcdManager = class {
|
|
|
71
76
|
this.playbackStarted_ = false;
|
|
72
77
|
this.buffering_ = true;
|
|
73
78
|
this.starved_ = false;
|
|
79
|
+
this.lowLatency_ = false;
|
|
74
80
|
}
|
|
75
81
|
|
|
76
82
|
/**
|
|
@@ -90,6 +96,30 @@ shaka.util.CmcdManager = class {
|
|
|
90
96
|
this.buffering_ = buffering;
|
|
91
97
|
}
|
|
92
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Set the low latency
|
|
101
|
+
*
|
|
102
|
+
* @param {boolean} lowLatency
|
|
103
|
+
*/
|
|
104
|
+
setLowLatency(lowLatency) {
|
|
105
|
+
this.lowLatency_ = lowLatency;
|
|
106
|
+
|
|
107
|
+
const StreamingFormat = shaka.util.CmcdManager.StreamingFormat;
|
|
108
|
+
if (this.lowLatency_) {
|
|
109
|
+
if (this.sf_ == StreamingFormat.DASH) {
|
|
110
|
+
this.sf_ = StreamingFormat.LOW_LATENCY_DASH;
|
|
111
|
+
} else if (this.sf_ == StreamingFormat.HLS) {
|
|
112
|
+
this.sf_ = StreamingFormat.LOW_LATENCY_HLS;
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
if (this.sf_ == StreamingFormat.LOW_LATENCY_DASH) {
|
|
116
|
+
this.sf_ = StreamingFormat.DASH;
|
|
117
|
+
} else if (this.sf_ == StreamingFormat.LOW_LATENCY_HLS) {
|
|
118
|
+
this.sf_ = StreamingFormat.HLS;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
93
123
|
/**
|
|
94
124
|
* Apply CMCD data to a request.
|
|
95
125
|
*
|
|
@@ -624,10 +654,16 @@ shaka.util.CmcdManager = class {
|
|
|
624
654
|
|
|
625
655
|
switch (type) {
|
|
626
656
|
case AdvancedRequestType.MPD:
|
|
657
|
+
if (this.lowLatency_) {
|
|
658
|
+
return shaka.util.CmcdManager.StreamingFormat.LOW_LATENCY_DASH;
|
|
659
|
+
}
|
|
627
660
|
return shaka.util.CmcdManager.StreamingFormat.DASH;
|
|
628
661
|
|
|
629
662
|
case AdvancedRequestType.MASTER_PLAYLIST:
|
|
630
663
|
case AdvancedRequestType.MEDIA_PLAYLIST:
|
|
664
|
+
if (this.lowLatency_) {
|
|
665
|
+
return shaka.util.CmcdManager.StreamingFormat.LOW_LATENCY_HLS;
|
|
666
|
+
}
|
|
631
667
|
return shaka.util.CmcdManager.StreamingFormat.HLS;
|
|
632
668
|
|
|
633
669
|
case AdvancedRequestType.MSS:
|
|
@@ -887,7 +923,9 @@ shaka.util.CmcdManager.StreamType = {
|
|
|
887
923
|
*/
|
|
888
924
|
shaka.util.CmcdManager.StreamingFormat = {
|
|
889
925
|
DASH: 'd',
|
|
926
|
+
LOW_LATENCY_DASH: 'ld',
|
|
890
927
|
HLS: 'h',
|
|
928
|
+
LOW_LATENCY_HLS: 'lh',
|
|
891
929
|
SMOOTH: 's',
|
|
892
930
|
OTHER: 'o',
|
|
893
931
|
};
|
package/lib/util/error.js
CHANGED
|
@@ -779,6 +779,11 @@ shaka.util.Error.Code = {
|
|
|
779
779
|
*/
|
|
780
780
|
'DASH_INVALID_PATCH': 4052,
|
|
781
781
|
|
|
782
|
+
/**
|
|
783
|
+
* The media playlist has not segments or all segments are gap.
|
|
784
|
+
*/
|
|
785
|
+
'HLS_EMPTY_MEDIA_PLAYLIST': 4053,
|
|
786
|
+
|
|
782
787
|
|
|
783
788
|
// RETIRED: 'INCONSISTENT_BUFFER_STATE': 5000,
|
|
784
789
|
// RETIRED: 'INVALID_SEGMENT_INDEX': 5001,
|
|
@@ -1143,4 +1148,15 @@ shaka.util.Error.Code = {
|
|
|
1143
1148
|
* Ad Insertion. Call adManager.initMediaTailor() to do it.
|
|
1144
1149
|
*/
|
|
1145
1150
|
'MT_AD_MANAGER_NOT_INITIALIZED': 10005,
|
|
1151
|
+
|
|
1152
|
+
/**
|
|
1153
|
+
* Interstitial Ad Manager needs to be initialized to enable interstitial
|
|
1154
|
+
* Ad Insertion. Call adManager.initInterstitial() to do it.
|
|
1155
|
+
*/
|
|
1156
|
+
'INTERSTITIAL_AD_MANAGER_NOT_INITIALIZED': 10006,
|
|
1157
|
+
|
|
1158
|
+
/**
|
|
1159
|
+
* The VAST contained invalid XML markup.
|
|
1160
|
+
*/
|
|
1161
|
+
'VAST_INVALID_XML': 4001,
|
|
1146
1162
|
};
|
package/lib/util/fake_event.js
CHANGED
|
@@ -173,6 +173,7 @@ shaka.util.FakeEvent.EventName = {
|
|
|
173
173
|
ManifestParsed: 'manifestparsed',
|
|
174
174
|
ManifestUpdated: 'manifestupdated',
|
|
175
175
|
MediaQualityChanged: 'mediaqualitychanged',
|
|
176
|
+
MediaSourceRecovered: 'mediasourcerecovered',
|
|
176
177
|
Metadata: 'metadata',
|
|
177
178
|
Midpoint: 'midpoint',
|
|
178
179
|
NoSpatialVideoInfoEvent: 'nospatialvideoinfo',
|
|
@@ -26,9 +26,10 @@ shaka.util.ManifestParserUtils = class {
|
|
|
26
26
|
*
|
|
27
27
|
* @param {!Array.<string>} baseUris
|
|
28
28
|
* @param {!Array.<string>} relativeUris
|
|
29
|
+
* @param {string=} extraQueryParams
|
|
29
30
|
* @return {!Array.<string>}
|
|
30
31
|
*/
|
|
31
|
-
static resolveUris(baseUris, relativeUris) {
|
|
32
|
+
static resolveUris(baseUris, relativeUris, extraQueryParams = '') {
|
|
32
33
|
if (relativeUris.length == 0) {
|
|
33
34
|
return baseUris;
|
|
34
35
|
}
|
|
@@ -36,7 +37,11 @@ shaka.util.ManifestParserUtils = class {
|
|
|
36
37
|
if (baseUris.length == 1 && relativeUris.length == 1) {
|
|
37
38
|
const baseUri = new goog.Uri(baseUris[0]);
|
|
38
39
|
const relativeUri = new goog.Uri(relativeUris[0]);
|
|
39
|
-
|
|
40
|
+
const resolvedUri = baseUri.resolve(relativeUri);
|
|
41
|
+
if (extraQueryParams) {
|
|
42
|
+
resolvedUri.setQueryData(extraQueryParams);
|
|
43
|
+
}
|
|
44
|
+
return [resolvedUri.toString()];
|
|
40
45
|
}
|
|
41
46
|
|
|
42
47
|
const relativeAsGoog = relativeUris.map((uri) => new goog.Uri(uri));
|
|
@@ -47,7 +52,11 @@ shaka.util.ManifestParserUtils = class {
|
|
|
47
52
|
for (const baseStr of baseUris) {
|
|
48
53
|
const base = new goog.Uri(baseStr);
|
|
49
54
|
for (const relative of relativeAsGoog) {
|
|
50
|
-
|
|
55
|
+
const resolvedUri = base.resolve(relative);
|
|
56
|
+
if (extraQueryParams) {
|
|
57
|
+
resolvedUri.setQueryData(extraQueryParams);
|
|
58
|
+
}
|
|
59
|
+
resolvedUris.push(resolvedUri.toString());
|
|
51
60
|
}
|
|
52
61
|
}
|
|
53
62
|
|