shaka-player 4.11.2 → 4.11.4
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/dist/locales.js +56 -56
- package/dist/shaka-player.compiled.d.ts +10 -1
- package/dist/shaka-player.compiled.debug.d.ts +10 -1
- package/dist/shaka-player.compiled.debug.externs.js +13 -0
- package/dist/shaka-player.compiled.debug.js +316 -310
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.externs.js +13 -0
- package/dist/shaka-player.compiled.js +1014 -1008
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.d.ts +10 -1
- package/dist/shaka-player.ui.debug.d.ts +10 -1
- package/dist/shaka-player.ui.debug.externs.js +13 -0
- package/dist/shaka-player.ui.debug.js +373 -365
- package/dist/shaka-player.ui.debug.map +3 -3
- package/dist/shaka-player.ui.externs.js +13 -0
- package/dist/shaka-player.ui.js +1266 -1259
- package/dist/shaka-player.ui.map +3 -3
- package/externs/shaka/player.js +10 -1
- package/lib/ads/interstitial_ad_manager.js +27 -5
- package/lib/dash/dash_parser.js +10 -7
- package/lib/dash/mpd_utils.js +0 -3
- package/lib/dash/segment_template.js +11 -2
- package/lib/media/gap_jumping_controller.js +4 -2
- package/lib/media/presentation_timeline.js +16 -0
- package/lib/media/segment_index.js +4 -4
- package/lib/media/streaming_engine.js +17 -10
- package/lib/net/networking_utils.js +5 -0
- package/lib/offline/storage.js +12 -10
- package/lib/player.js +13 -4
- package/lib/text/ttml_text_parser.js +1 -1
- package/lib/util/periods.js +56 -3
- package/lib/util/player_configuration.js +5 -0
- package/lib/util/tXml.js +17 -9
- package/package.json +1 -1
- package/ui/controls.js +14 -2
- package/ui/locales/README.md +16 -0
- package/ui/locales/ar-XB.json +1 -1
- package/ui/locales/ar.json +1 -1
- package/ui/locales/bg.json +1 -1
- package/ui/locales/ca.json +5 -5
- package/ui/locales/cs.json +1 -1
- package/ui/locales/da.json +1 -1
- package/ui/locales/de.json +1 -1
- package/ui/locales/el.json +1 -1
- package/ui/locales/en-GB.json +1 -1
- package/ui/locales/en-XA.json +1 -1
- package/ui/locales/es-419.json +4 -4
- package/ui/locales/es.json +4 -4
- package/ui/locales/fa.json +1 -1
- package/ui/locales/fi.json +1 -1
- package/ui/locales/fil.json +1 -1
- package/ui/locales/fr.json +5 -5
- package/ui/locales/hi.json +1 -1
- package/ui/locales/hr.json +1 -1
- package/ui/locales/hu.json +1 -1
- package/ui/locales/id.json +1 -1
- package/ui/locales/it.json +1 -1
- package/ui/locales/iw.json +1 -1
- package/ui/locales/ja.json +1 -1
- package/ui/locales/ko.json +1 -1
- package/ui/locales/lt.json +1 -1
- package/ui/locales/lv.json +1 -1
- package/ui/locales/nl.json +1 -1
- package/ui/locales/no.json +1 -1
- package/ui/locales/pl.json +5 -5
- package/ui/locales/pt-BR.json +7 -7
- package/ui/locales/pt-PT.json +8 -8
- package/ui/locales/ro.json +1 -1
- package/ui/locales/ru.json +1 -1
- package/ui/locales/sjn-translations.yaml +50 -4
- package/ui/locales/sjn.json +8 -1
- package/ui/locales/sk.json +1 -1
- package/ui/locales/sl.json +1 -1
- package/ui/locales/sr.json +1 -1
- package/ui/locales/sv.json +1 -1
- package/ui/locales/sync-sjn.py +41 -0
- package/ui/locales/th.json +1 -1
- package/ui/locales/tr.json +1 -1
- package/ui/locales/uk.json +1 -1
- package/ui/locales/vi.json +1 -1
- package/ui/locales/zh-HK.json +1 -1
- package/ui/locales/zh-TW.json +1 -1
- package/ui/locales/zh.json +1 -1
package/externs/shaka/player.js
CHANGED
|
@@ -1532,6 +1532,7 @@ shaka.extern.LiveSyncConfiguration;
|
|
|
1532
1532
|
* alwaysStreamText: boolean,
|
|
1533
1533
|
* startAtSegmentBoundary: boolean,
|
|
1534
1534
|
* gapDetectionThreshold: number,
|
|
1535
|
+
* gapPadding: number,
|
|
1535
1536
|
* gapJumpTimerTime: number,
|
|
1536
1537
|
* durationBackoff: number,
|
|
1537
1538
|
* safeSeekOffset: number,
|
|
@@ -1625,6 +1626,13 @@ shaka.extern.LiveSyncConfiguration;
|
|
|
1625
1626
|
* jump.
|
|
1626
1627
|
* <br>
|
|
1627
1628
|
* Defaults to <code>0.5</code>.
|
|
1629
|
+
* @property {number} gapPadding
|
|
1630
|
+
* Padding added only for Xbox, Legacy Edge and Tizen.
|
|
1631
|
+
* Based on our research (specific to Tizen), the gapPadding value must be
|
|
1632
|
+
* greater than your GOP length.
|
|
1633
|
+
* It’s crucial to verify this value according to your actual stream.
|
|
1634
|
+
* <br>
|
|
1635
|
+
* Defaults to <code>0.01</code> for Xbox and Legacy Edge, Tizen at 2.
|
|
1628
1636
|
* @property {number} gapJumpTimerTime
|
|
1629
1637
|
* The polling time in seconds to check for gaps in the media.
|
|
1630
1638
|
* <br>
|
|
@@ -2227,7 +2235,8 @@ shaka.extern.LcevcConfiguration;
|
|
|
2227
2235
|
* <br>
|
|
2228
2236
|
* Defaults to <code>true</code>.
|
|
2229
2237
|
* @property {number} numberOfParallelDownloads
|
|
2230
|
-
* Number of parallel downloads.
|
|
2238
|
+
* Number of parallel downloads. If the value is 0, downloads will be
|
|
2239
|
+
* sequential for each stream.
|
|
2231
2240
|
* Note: normally browsers limit to 5 request in parallel, so putting a
|
|
2232
2241
|
* number higher than this will not help it download faster.
|
|
2233
2242
|
* <br>
|
|
@@ -89,13 +89,23 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
89
89
|
/** @private {?number} */
|
|
90
90
|
this.lastTime_ = null;
|
|
91
91
|
|
|
92
|
+
/** @private {?shaka.extern.AdInterstitial} */
|
|
93
|
+
this.lastPlayedAd_ = null;
|
|
94
|
+
|
|
92
95
|
this.eventManager_.listen(this.baseVideo_, 'timeupdate', () => {
|
|
93
96
|
if (this.playingAd_) {
|
|
94
97
|
return;
|
|
95
98
|
}
|
|
96
99
|
const needPreRoll = this.lastTime_ == null || this.lastTime_ == 0;
|
|
97
100
|
this.lastTime_ = this.baseVideo_.currentTime;
|
|
98
|
-
|
|
101
|
+
// Remove last played add when the new time is before to the ad time.
|
|
102
|
+
if (this.lastPlayedAd_ &&
|
|
103
|
+
!this.lastPlayedAd_.pre && !this.lastPlayedAd_.post &&
|
|
104
|
+
this.lastTime_ < this.lastPlayedAd_.startTime) {
|
|
105
|
+
this.lastPlayedAd_ = null;
|
|
106
|
+
}
|
|
107
|
+
const currentInterstitial = this.getCurrentInterstitial_(
|
|
108
|
+
needPreRoll, /* numberToSkip= */ 0, this.lastPlayedAd_);
|
|
99
109
|
if (currentInterstitial) {
|
|
100
110
|
this.setupAd_(currentInterstitial, /* sequenceLength= */ 1,
|
|
101
111
|
/* adPosition= */ 1, /* initialTime= */ Date.now());
|
|
@@ -187,6 +197,7 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
187
197
|
this.player_.detach();
|
|
188
198
|
this.playingAd_ = false;
|
|
189
199
|
this.lastTime_ = null;
|
|
200
|
+
this.lastPlayedAd_ = null;
|
|
190
201
|
}
|
|
191
202
|
|
|
192
203
|
/** @override */
|
|
@@ -374,11 +385,12 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
374
385
|
|
|
375
386
|
/**
|
|
376
387
|
* @param {boolean} needPreRoll
|
|
377
|
-
* @param {number
|
|
388
|
+
* @param {number} numberToSkip
|
|
389
|
+
* @param {?shaka.extern.AdInterstitial=} lastPlayedAd
|
|
378
390
|
* @return {?shaka.extern.AdInterstitial}
|
|
379
391
|
* @private
|
|
380
392
|
*/
|
|
381
|
-
getCurrentInterstitial_(needPreRoll, numberToSkip
|
|
393
|
+
getCurrentInterstitial_(needPreRoll, numberToSkip, lastPlayedAd) {
|
|
382
394
|
let skipped = 0;
|
|
383
395
|
let currentInterstitial = null;
|
|
384
396
|
if (this.interstitials_.size && this.lastTime_ != null) {
|
|
@@ -398,8 +410,16 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
398
410
|
} else if (!interstitial.pre && !interstitial.post) {
|
|
399
411
|
const difference =
|
|
400
412
|
this.lastTime_ - roundDecimals(interstitial.startTime);
|
|
401
|
-
|
|
402
|
-
(difference <= 1 || !interstitial.canJump)
|
|
413
|
+
if (difference > 0 &&
|
|
414
|
+
(difference <= 1 || !interstitial.canJump)) {
|
|
415
|
+
if (difference > 1 && lastPlayedAd &&
|
|
416
|
+
!lastPlayedAd.pre && !lastPlayedAd.post &&
|
|
417
|
+
lastPlayedAd.startTime >= interstitial.startTime) {
|
|
418
|
+
isValid = false;
|
|
419
|
+
} else {
|
|
420
|
+
isValid = true;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
403
423
|
}
|
|
404
424
|
if (isValid) {
|
|
405
425
|
if (skipped == numberToSkip) {
|
|
@@ -426,6 +446,8 @@ shaka.ads.InterstitialAdManager = class {
|
|
|
426
446
|
oncePlayed = 0) {
|
|
427
447
|
goog.asserts.assert(this.video_, 'Must have video');
|
|
428
448
|
|
|
449
|
+
this.lastPlayedAd_ = interstitial;
|
|
450
|
+
|
|
429
451
|
const startTime = Date.now();
|
|
430
452
|
|
|
431
453
|
if (!this.video_.parentElement && this.adContainer_) {
|
package/lib/dash/dash_parser.js
CHANGED
|
@@ -192,6 +192,9 @@ shaka.dash.DashParser = class {
|
|
|
192
192
|
|
|
193
193
|
/** @private {function():boolean} */
|
|
194
194
|
this.isPreloadFn_ = () => false;
|
|
195
|
+
|
|
196
|
+
/** @private {?Array.<string>} */
|
|
197
|
+
this.lastCalculatedBaseUris_ = [];
|
|
195
198
|
}
|
|
196
199
|
|
|
197
200
|
/**
|
|
@@ -602,7 +605,6 @@ shaka.dash.DashParser = class {
|
|
|
602
605
|
}
|
|
603
606
|
|
|
604
607
|
const uriObjs = TXml.findChildren(mpd, 'BaseURL');
|
|
605
|
-
let calculatedBaseUris;
|
|
606
608
|
let someLocationValid = false;
|
|
607
609
|
if (this.contentSteeringManager_) {
|
|
608
610
|
for (const uriObj of uriObjs) {
|
|
@@ -615,9 +617,10 @@ shaka.dash.DashParser = class {
|
|
|
615
617
|
}
|
|
616
618
|
}
|
|
617
619
|
}
|
|
620
|
+
this.lastCalculatedBaseUris_ = null;
|
|
618
621
|
if (!someLocationValid || !this.contentSteeringManager_) {
|
|
619
622
|
const uris = uriObjs.map(TXml.getContents);
|
|
620
|
-
|
|
623
|
+
this.lastCalculatedBaseUris_ = shaka.util.ManifestParserUtils.resolveUris(
|
|
621
624
|
manifestBaseUris, uris);
|
|
622
625
|
}
|
|
623
626
|
|
|
@@ -625,8 +628,8 @@ shaka.dash.DashParser = class {
|
|
|
625
628
|
if (this.contentSteeringManager_ && someLocationValid) {
|
|
626
629
|
return this.contentSteeringManager_.getLocations('BaseURL');
|
|
627
630
|
}
|
|
628
|
-
if (
|
|
629
|
-
return
|
|
631
|
+
if (this.lastCalculatedBaseUris_) {
|
|
632
|
+
return this.lastCalculatedBaseUris_;
|
|
630
633
|
}
|
|
631
634
|
return [];
|
|
632
635
|
};
|
|
@@ -1492,14 +1495,14 @@ shaka.dash.DashParser = class {
|
|
|
1492
1495
|
*/
|
|
1493
1496
|
cleanStreamMap_() {
|
|
1494
1497
|
const oldPeriodIds = Object.keys(this.indexStreamMap_);
|
|
1495
|
-
if (oldPeriodIds.length === this.lastManifestUpdatePeriodIds_.length) {
|
|
1496
|
-
return;
|
|
1497
|
-
}
|
|
1498
1498
|
const diffPeriodsIDs = oldPeriodIds.filter((pId) => {
|
|
1499
1499
|
return !this.lastManifestUpdatePeriodIds_.includes(pId);
|
|
1500
1500
|
});
|
|
1501
1501
|
for (const pId of diffPeriodsIDs) {
|
|
1502
1502
|
for (const contextId of this.indexStreamMap_[pId]) {
|
|
1503
|
+
if (this.periodCombiner_) {
|
|
1504
|
+
this.periodCombiner_.deleteStream(this.streamMap_[contextId], pId);
|
|
1505
|
+
}
|
|
1503
1506
|
delete this.streamMap_[contextId];
|
|
1504
1507
|
}
|
|
1505
1508
|
delete this.indexStreamMap_[pId];
|
package/lib/dash/mpd_utils.js
CHANGED
|
@@ -481,9 +481,6 @@ shaka.dash.MpdUtils = class {
|
|
|
481
481
|
// Move the children of the loaded xml into the current element.
|
|
482
482
|
while (rootElem.children.length) {
|
|
483
483
|
const child = rootElem.children.shift();
|
|
484
|
-
if (TXml.isNode(child)) {
|
|
485
|
-
child.parent = element;
|
|
486
|
-
}
|
|
487
484
|
element.children.push(child);
|
|
488
485
|
}
|
|
489
486
|
|
|
@@ -86,10 +86,19 @@ shaka.dash.SegmentTemplate = class {
|
|
|
86
86
|
};
|
|
87
87
|
} else if (info.segmentDuration) {
|
|
88
88
|
if (!isUpdate && context.adaptationSet.contentType !== 'image') {
|
|
89
|
+
const periodStart = context.periodInfo.start;
|
|
90
|
+
const periodId = context.period.id;
|
|
91
|
+
const initialPeriodDuration = context.periodInfo.duration;
|
|
92
|
+
const periodDuration =
|
|
93
|
+
(periodId != null && periodDurationMap[periodId]) ||
|
|
94
|
+
initialPeriodDuration;
|
|
95
|
+
const periodEnd = periodDuration ?
|
|
96
|
+
(periodStart + periodDuration) : Infinity;
|
|
97
|
+
|
|
89
98
|
context.presentationTimeline.notifyMaxSegmentDuration(
|
|
90
99
|
info.segmentDuration);
|
|
91
|
-
context.presentationTimeline.
|
|
92
|
-
|
|
100
|
+
context.presentationTimeline.notifyPeriodDuration(
|
|
101
|
+
periodStart, periodEnd);
|
|
93
102
|
}
|
|
94
103
|
|
|
95
104
|
return {
|
|
@@ -223,8 +223,10 @@ shaka.media.GapJumpingController = class {
|
|
|
223
223
|
// often rounds value we want to set as currentTime and we are not able
|
|
224
224
|
// to jump over the gap.
|
|
225
225
|
if (shaka.util.Platform.isLegacyEdge() ||
|
|
226
|
-
shaka.util.Platform.isXboxOne()
|
|
227
|
-
|
|
226
|
+
shaka.util.Platform.isXboxOne() ||
|
|
227
|
+
shaka.util.Platform.isTizen()) {
|
|
228
|
+
const gapPadding = this.config_.gapPadding;
|
|
229
|
+
jumpTo = Math.ceil((jumpTo + gapPadding) * 100) / 100;
|
|
228
230
|
}
|
|
229
231
|
const seekEnd = this.timeline_.getSeekRangeEnd();
|
|
230
232
|
if (jumpTo >= seekEnd) {
|
|
@@ -331,6 +331,22 @@ shaka.media.PresentationTimeline = class {
|
|
|
331
331
|
}
|
|
332
332
|
|
|
333
333
|
|
|
334
|
+
/**
|
|
335
|
+
* Gives PresentationTimeline an startTime and endTime of the period.
|
|
336
|
+
* This should be only set for Dash.
|
|
337
|
+
*
|
|
338
|
+
* @param {number} startTime
|
|
339
|
+
* @param {number} endTime
|
|
340
|
+
* @export
|
|
341
|
+
*/
|
|
342
|
+
notifyPeriodDuration(startTime, endTime) {
|
|
343
|
+
this.notifyMinSegmentStartTime(startTime);
|
|
344
|
+
if (endTime != Infinity && !this.isLive()) {
|
|
345
|
+
this.maxSegmentEndTime_ = Math.max(this.maxSegmentEndTime_, endTime);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
|
|
334
350
|
/**
|
|
335
351
|
* Gets the end time of the last available segment.
|
|
336
352
|
*
|
|
@@ -834,10 +834,10 @@ shaka.media.MetaSegmentIndex = class extends shaka.media.SegmentIndex {
|
|
|
834
834
|
* @export
|
|
835
835
|
*/
|
|
836
836
|
evict(time) {
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
837
|
+
for (const index of this.indexes_) {
|
|
838
|
+
index.evict(time);
|
|
839
|
+
}
|
|
840
|
+
this.evictEmpty();
|
|
841
841
|
}
|
|
842
842
|
|
|
843
843
|
/**
|
|
@@ -1519,9 +1519,11 @@ shaka.media.StreamingEngine = class {
|
|
|
1519
1519
|
logPrefix, 'looking up segment from new stream endTime:', time);
|
|
1520
1520
|
|
|
1521
1521
|
const reverse = this.playerInterface_.getPlaybackRate() < 0;
|
|
1522
|
-
mediaState.
|
|
1523
|
-
|
|
1524
|
-
|
|
1522
|
+
if (mediaState.stream.segmentIndex) {
|
|
1523
|
+
mediaState.segmentIterator =
|
|
1524
|
+
mediaState.stream.segmentIndex.getIteratorForTime(
|
|
1525
|
+
time, /* allowNonIndepedent= */ false, reverse);
|
|
1526
|
+
}
|
|
1525
1527
|
const ref = mediaState.segmentIterator &&
|
|
1526
1528
|
mediaState.segmentIterator.next().value;
|
|
1527
1529
|
if (ref == null) {
|
|
@@ -1545,18 +1547,22 @@ shaka.media.StreamingEngine = class {
|
|
|
1545
1547
|
const reverse = this.playerInterface_.getPlaybackRate() < 0;
|
|
1546
1548
|
let ref = null;
|
|
1547
1549
|
if (inaccurateTolerance) {
|
|
1548
|
-
mediaState.
|
|
1549
|
-
|
|
1550
|
-
|
|
1550
|
+
if (mediaState.stream.segmentIndex) {
|
|
1551
|
+
mediaState.segmentIterator =
|
|
1552
|
+
mediaState.stream.segmentIndex.getIteratorForTime(
|
|
1553
|
+
lookupTime, /* allowNonIndepedent= */ false, reverse);
|
|
1554
|
+
}
|
|
1551
1555
|
ref = mediaState.segmentIterator &&
|
|
1552
1556
|
mediaState.segmentIterator.next().value;
|
|
1553
1557
|
}
|
|
1554
1558
|
if (!ref) {
|
|
1555
1559
|
// If we can't find a valid segment with the drifted time, look for a
|
|
1556
1560
|
// segment with the presentation time.
|
|
1557
|
-
mediaState.
|
|
1558
|
-
|
|
1559
|
-
|
|
1561
|
+
if (mediaState.stream.segmentIndex) {
|
|
1562
|
+
mediaState.segmentIterator =
|
|
1563
|
+
mediaState.stream.segmentIndex.getIteratorForTime(
|
|
1564
|
+
presentationTime, /* allowNonIndepedent= */ false, reverse);
|
|
1565
|
+
}
|
|
1560
1566
|
ref = mediaState.segmentIterator &&
|
|
1561
1567
|
mediaState.segmentIterator.next().value;
|
|
1562
1568
|
}
|
|
@@ -2505,7 +2511,8 @@ shaka.media.StreamingEngine = class {
|
|
|
2505
2511
|
async evict_(mediaState, presentationTime) {
|
|
2506
2512
|
const segmentIndex = mediaState.stream.segmentIndex;
|
|
2507
2513
|
if (segmentIndex instanceof shaka.media.MetaSegmentIndex) {
|
|
2508
|
-
segmentIndex.
|
|
2514
|
+
segmentIndex.evict(
|
|
2515
|
+
this.manifest_.presentationTimeline.getSeekRangeStart());
|
|
2509
2516
|
}
|
|
2510
2517
|
|
|
2511
2518
|
const logPrefix = shaka.media.StreamingEngine.logPrefix_(mediaState);
|
|
@@ -103,4 +103,9 @@ shaka.net.NetworkingUtils.EXTENSIONS_TO_MIME_TYPES_ = {
|
|
|
103
103
|
'lrc': 'application/x-subtitle-lrc',
|
|
104
104
|
'ssa': 'text/x-ssa',
|
|
105
105
|
'ass': 'text/x-ssa',
|
|
106
|
+
'jpg': 'image/jpeg',
|
|
107
|
+
'png': 'image/png',
|
|
108
|
+
'svg': 'image/svg+xml',
|
|
109
|
+
'webp': 'image/webp',
|
|
110
|
+
'avif': 'image/avif',
|
|
106
111
|
};
|
package/lib/offline/storage.js
CHANGED
|
@@ -1346,7 +1346,7 @@ shaka.offline.Storage = class {
|
|
|
1346
1346
|
manifest.presentationTimeline.getSegmentAvailabilityStart();
|
|
1347
1347
|
|
|
1348
1348
|
const numberOfParallelDownloads = config.offline.numberOfParallelDownloads;
|
|
1349
|
-
let groupId = 0;
|
|
1349
|
+
let groupId = numberOfParallelDownloads === 0 ? stream.id : 0;
|
|
1350
1350
|
|
|
1351
1351
|
shaka.offline.Storage.forEachSegment_(stream, startTime, (segment) => {
|
|
1352
1352
|
const pendingSegmentRefId =
|
|
@@ -1398,7 +1398,9 @@ shaka.offline.Storage = class {
|
|
|
1398
1398
|
codecs: segment.codecs,
|
|
1399
1399
|
};
|
|
1400
1400
|
streamDb.segments.push(segmentDB);
|
|
1401
|
-
|
|
1401
|
+
if (numberOfParallelDownloads !== 0) {
|
|
1402
|
+
groupId = (groupId + 1) % numberOfParallelDownloads;
|
|
1403
|
+
}
|
|
1402
1404
|
});
|
|
1403
1405
|
|
|
1404
1406
|
return streamDb;
|
|
@@ -1593,14 +1595,6 @@ shaka.offline.Storage = class {
|
|
|
1593
1595
|
/** @type {!Set.<shaka.extern.Stream>} */
|
|
1594
1596
|
const set = new Set();
|
|
1595
1597
|
|
|
1596
|
-
for (const text of manifest.textStreams) {
|
|
1597
|
-
set.add(text);
|
|
1598
|
-
}
|
|
1599
|
-
|
|
1600
|
-
for (const image of manifest.imageStreams) {
|
|
1601
|
-
set.add(image);
|
|
1602
|
-
}
|
|
1603
|
-
|
|
1604
1598
|
for (const variant of manifest.variants) {
|
|
1605
1599
|
if (variant.audio) {
|
|
1606
1600
|
set.add(variant.audio);
|
|
@@ -1610,6 +1604,14 @@ shaka.offline.Storage = class {
|
|
|
1610
1604
|
}
|
|
1611
1605
|
}
|
|
1612
1606
|
|
|
1607
|
+
for (const text of manifest.textStreams) {
|
|
1608
|
+
set.add(text);
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
for (const image of manifest.imageStreams) {
|
|
1612
|
+
set.add(image);
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1613
1615
|
return set;
|
|
1614
1616
|
}
|
|
1615
1617
|
|
package/lib/player.js
CHANGED
|
@@ -5962,6 +5962,13 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5962
5962
|
references.push(reference);
|
|
5963
5963
|
}
|
|
5964
5964
|
|
|
5965
|
+
let segmentMimeType = mimeType;
|
|
5966
|
+
if (references.length) {
|
|
5967
|
+
segmentMimeType = await shaka.net.NetworkingUtils.getMimeType(
|
|
5968
|
+
references[0].getUris()[0],
|
|
5969
|
+
this.networkingEngine_, this.config_.manifest.retryParameters);
|
|
5970
|
+
}
|
|
5971
|
+
|
|
5965
5972
|
/** @type {shaka.extern.Stream} */
|
|
5966
5973
|
const stream = {
|
|
5967
5974
|
id: this.nextExternalStreamId_++,
|
|
@@ -5969,7 +5976,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5969
5976
|
groupId: null,
|
|
5970
5977
|
createSegmentIndex: () => Promise.resolve(),
|
|
5971
5978
|
segmentIndex: new shaka.media.SegmentIndex(references),
|
|
5972
|
-
mimeType:
|
|
5979
|
+
mimeType: segmentMimeType || '',
|
|
5973
5980
|
codecs: '',
|
|
5974
5981
|
kind: '',
|
|
5975
5982
|
encrypted: false,
|
|
@@ -5993,7 +6000,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5993
6000
|
external: true,
|
|
5994
6001
|
fastSwitching: false,
|
|
5995
6002
|
fullMimeTypes: new Set([shaka.util.MimeUtils.getFullType(
|
|
5996
|
-
|
|
6003
|
+
segmentMimeType || '', '')]),
|
|
5997
6004
|
};
|
|
5998
6005
|
|
|
5999
6006
|
if (this.loadMode_ == shaka.Player.LoadMode.SRC_EQUALS) {
|
|
@@ -7231,11 +7238,13 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
7231
7238
|
this.playhead_.notifyOfBufferingChange();
|
|
7232
7239
|
// Skip the initial buffer gap
|
|
7233
7240
|
const startTime = this.mediaSourceEngine_.bufferStart(contentType);
|
|
7241
|
+
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
7234
7242
|
if (
|
|
7235
7243
|
!this.isLive() &&
|
|
7236
7244
|
// If not paused then GapJumpingController will handle this gap.
|
|
7237
7245
|
this.video_.paused &&
|
|
7238
7246
|
startTime != null &&
|
|
7247
|
+
contentType != ContentType.TEXT &&
|
|
7239
7248
|
startTime > 0 &&
|
|
7240
7249
|
this.playhead_.getTime() < startTime
|
|
7241
7250
|
) {
|
|
@@ -8062,8 +8071,8 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
8062
8071
|
* @define {string} A version number taken from git at compile time.
|
|
8063
8072
|
* @export
|
|
8064
8073
|
*/
|
|
8065
|
-
// eslint-disable-next-line no-useless-concat
|
|
8066
|
-
shaka.Player.version = 'v4.11.
|
|
8074
|
+
// eslint-disable-next-line no-useless-concat, max-len
|
|
8075
|
+
shaka.Player.version = 'v4.11.4' + '-uncompiled'; // x-release-please-version
|
|
8067
8076
|
|
|
8068
8077
|
// Initialize the deprecation system using the version string we just set
|
|
8069
8078
|
// on the player.
|
|
@@ -65,7 +65,7 @@ shaka.text.TtmlTextParser = class {
|
|
|
65
65
|
return cues;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
const tt = TXml.parseXmlString(str, 'tt');
|
|
68
|
+
const tt = TXml.parseXmlString(str, 'tt', /* includeParent= */ true);
|
|
69
69
|
if (!tt) {
|
|
70
70
|
throw new shaka.util.Error(
|
|
71
71
|
shaka.util.Error.Severity.CRITICAL,
|
package/lib/util/periods.js
CHANGED
|
@@ -107,6 +107,56 @@ shaka.util.PeriodCombiner = class {
|
|
|
107
107
|
return this.imageStreams_;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Deletes a stream from matchedStreams because it is no longer needed
|
|
112
|
+
*
|
|
113
|
+
* @param {?shaka.extern.Stream} stream
|
|
114
|
+
* @param {string} periodId
|
|
115
|
+
*
|
|
116
|
+
* @export
|
|
117
|
+
*/
|
|
118
|
+
deleteStream(stream, periodId) {
|
|
119
|
+
if (!stream) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
123
|
+
if (stream.type == ContentType.AUDIO) {
|
|
124
|
+
for (const audioStream of this.audioStreams_) {
|
|
125
|
+
audioStream.matchedStreams = audioStream.matchedStreams.filter((s) => {
|
|
126
|
+
return s !== stream;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
} else if (stream.type == ContentType.VIDEO) {
|
|
130
|
+
for (const videoStream of this.videoStreams_) {
|
|
131
|
+
videoStream.matchedStreams = videoStream.matchedStreams.filter((s) => {
|
|
132
|
+
return s !== stream;
|
|
133
|
+
});
|
|
134
|
+
if (videoStream.trickModeVideo) {
|
|
135
|
+
videoStream.trickModeVideo.matchedStreams =
|
|
136
|
+
videoStream.trickModeVideo.matchedStreams.filter((s) => {
|
|
137
|
+
return s !== stream;
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
} else if (stream.type == ContentType.TEXT) {
|
|
142
|
+
for (const textStream of this.textStreams_) {
|
|
143
|
+
textStream.matchedStreams = textStream.matchedStreams.filter((s) => {
|
|
144
|
+
return s !== stream;
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
} else if (stream.type == ContentType.IMAGE) {
|
|
148
|
+
for (const imageStream of this.imageStreams_) {
|
|
149
|
+
imageStream.matchedStreams = imageStream.matchedStreams.filter((s) => {
|
|
150
|
+
return s !== stream;
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (stream.segmentIndex) {
|
|
155
|
+
stream.closeSegmentIndex();
|
|
156
|
+
}
|
|
157
|
+
this.usedPeriodIds_.delete(periodId);
|
|
158
|
+
}
|
|
159
|
+
|
|
110
160
|
/**
|
|
111
161
|
* Returns an object that contains arrays of streams by type
|
|
112
162
|
* @param {!Array<shaka.extern.Period>} periods
|
|
@@ -600,7 +650,8 @@ shaka.util.PeriodCombiner = class {
|
|
|
600
650
|
const streams = outputStream.matchedStreams;
|
|
601
651
|
goog.asserts.assert(streams, 'matched streams should be valid');
|
|
602
652
|
|
|
603
|
-
for (
|
|
653
|
+
for (let i = firstNewPeriodIndex; i < streams.length; i++) {
|
|
654
|
+
const stream = streams[i];
|
|
604
655
|
operations.push(stream.createSegmentIndex());
|
|
605
656
|
if (stream.trickModeVideo && !stream.trickModeVideo.segmentIndex) {
|
|
606
657
|
operations.push(stream.trickModeVideo.createSegmentIndex());
|
|
@@ -783,7 +834,8 @@ shaka.util.PeriodCombiner = class {
|
|
|
783
834
|
clone.segmentIndex = null;
|
|
784
835
|
clone.emsgSchemeIdUris = [];
|
|
785
836
|
clone.keyIds = new Set();
|
|
786
|
-
clone.closedCaptions =
|
|
837
|
+
clone.closedCaptions = stream.closedCaptions ?
|
|
838
|
+
new Map(stream.closedCaptions) : null;
|
|
787
839
|
clone.trickModeVideo = null;
|
|
788
840
|
|
|
789
841
|
return clone;
|
|
@@ -808,7 +860,8 @@ shaka.util.PeriodCombiner = class {
|
|
|
808
860
|
clone.keyIds = new Set();
|
|
809
861
|
clone.segments = [];
|
|
810
862
|
clone.variantIds = [];
|
|
811
|
-
clone.closedCaptions =
|
|
863
|
+
clone.closedCaptions = streamDb.closedCaptions ?
|
|
864
|
+
new Map(streamDb.closedCaptions) : null;
|
|
812
865
|
|
|
813
866
|
return clone;
|
|
814
867
|
}
|
|
@@ -206,6 +206,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
206
206
|
alwaysStreamText: false,
|
|
207
207
|
startAtSegmentBoundary: false,
|
|
208
208
|
gapDetectionThreshold: 0.5,
|
|
209
|
+
gapPadding: 0.01,
|
|
209
210
|
gapJumpTimerTime: 0.25 /* seconds */,
|
|
210
211
|
durationBackoff: 1,
|
|
211
212
|
// Offset by 5 seconds since Chromecast takes a few seconds to start
|
|
@@ -283,6 +284,10 @@ shaka.util.PlayerConfiguration = class {
|
|
|
283
284
|
streaming.stallSkip = 0;
|
|
284
285
|
}
|
|
285
286
|
|
|
287
|
+
if (shaka.util.Platform.isTizen()) {
|
|
288
|
+
streaming.gapPadding = 2;
|
|
289
|
+
}
|
|
290
|
+
|
|
286
291
|
const offline = {
|
|
287
292
|
// We need to set this to a throw-away implementation for now as our
|
|
288
293
|
// default implementation will need to reference other fields in the
|
package/lib/util/tXml.js
CHANGED
|
@@ -44,11 +44,13 @@ shaka.util.TXml = class {
|
|
|
44
44
|
* Parse some data
|
|
45
45
|
* @param {BufferSource} data
|
|
46
46
|
* @param {string=} expectedRootElemName
|
|
47
|
+
* @param {boolean=} includeParent
|
|
47
48
|
* @return {shaka.extern.xml.Node | null}
|
|
48
49
|
*/
|
|
49
|
-
static parseXml(data, expectedRootElemName) {
|
|
50
|
+
static parseXml(data, expectedRootElemName, includeParent = false) {
|
|
50
51
|
const xmlString = shaka.util.StringUtils.fromBytesAutoDetect(data);
|
|
51
|
-
return shaka.util.TXml.parseXmlString(
|
|
52
|
+
return shaka.util.TXml.parseXmlString(
|
|
53
|
+
xmlString, expectedRootElemName, includeParent);
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
/**
|
|
@@ -57,8 +59,9 @@ shaka.util.TXml = class {
|
|
|
57
59
|
* @param {string=} expectedRootElemName
|
|
58
60
|
* @return {shaka.extern.xml.Node | null}
|
|
59
61
|
*/
|
|
60
|
-
static parseXmlString(xmlString, expectedRootElemName
|
|
61
|
-
|
|
62
|
+
static parseXmlString(xmlString, expectedRootElemName,
|
|
63
|
+
includeParent = false) {
|
|
64
|
+
const result = shaka.util.TXml.parse(xmlString, includeParent);
|
|
62
65
|
if (!expectedRootElemName && result.length) {
|
|
63
66
|
return result[0];
|
|
64
67
|
}
|
|
@@ -110,9 +113,10 @@ shaka.util.TXml = class {
|
|
|
110
113
|
* parseXML / html into a DOM Object,
|
|
111
114
|
* with no validation and some failure tolerance
|
|
112
115
|
* @param {string} S your XML to parse
|
|
116
|
+
* @param {boolean} includeParent
|
|
113
117
|
* @return {Array.<shaka.extern.xml.Node>}
|
|
114
118
|
*/
|
|
115
|
-
static parse(S) {
|
|
119
|
+
static parse(S, includeParent) {
|
|
116
120
|
let pos = 0;
|
|
117
121
|
|
|
118
122
|
const openBracket = '<';
|
|
@@ -287,9 +291,11 @@ shaka.util.TXml = class {
|
|
|
287
291
|
children,
|
|
288
292
|
parent: null,
|
|
289
293
|
};
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
children[i]
|
|
294
|
+
if (includeParent) {
|
|
295
|
+
for (let i = 0; i < children.length; i++) {
|
|
296
|
+
if (typeof children[i] !== 'string') {
|
|
297
|
+
children[i].parent = node;
|
|
298
|
+
}
|
|
293
299
|
}
|
|
294
300
|
}
|
|
295
301
|
return node;
|
|
@@ -331,7 +337,9 @@ shaka.util.TXml = class {
|
|
|
331
337
|
for (let i = 0; i < childrenLength; i++) {
|
|
332
338
|
const childrenValue = children[i];
|
|
333
339
|
if (typeof childrenValue !== 'string') {
|
|
334
|
-
|
|
340
|
+
if (includeParent) {
|
|
341
|
+
childrenValue.parent = node;
|
|
342
|
+
}
|
|
335
343
|
} else if (i == childrenLength - 1 && childrenValue == '\n') {
|
|
336
344
|
children.pop();
|
|
337
345
|
}
|
package/package.json
CHANGED
package/ui/controls.js
CHANGED
|
@@ -263,6 +263,16 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
|
|
|
263
263
|
this.castProxy_ = null;
|
|
264
264
|
}
|
|
265
265
|
|
|
266
|
+
if (this.spinnerContainer_) {
|
|
267
|
+
this.videoContainer_.removeChild(this.spinnerContainer_);
|
|
268
|
+
this.spinnerContainer_ = null;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (this.clientAdContainer_) {
|
|
272
|
+
this.videoContainer_.removeChild(this.clientAdContainer_);
|
|
273
|
+
this.clientAdContainer_ = null;
|
|
274
|
+
}
|
|
275
|
+
|
|
266
276
|
if (this.localPlayer_) {
|
|
267
277
|
await this.localPlayer_.destroy();
|
|
268
278
|
this.localPlayer_ = null;
|
|
@@ -524,6 +534,8 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
|
|
|
524
534
|
* @export
|
|
525
535
|
*/
|
|
526
536
|
getClientSideAdContainer() {
|
|
537
|
+
goog.asserts.assert(
|
|
538
|
+
this.clientAdContainer_, 'No client ad container after destruction!');
|
|
527
539
|
return this.clientAdContainer_;
|
|
528
540
|
}
|
|
529
541
|
|
|
@@ -982,7 +994,7 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
|
|
|
982
994
|
|
|
983
995
|
/** @private */
|
|
984
996
|
addBufferingSpinner_() {
|
|
985
|
-
/** @private {
|
|
997
|
+
/** @private {HTMLElement} */
|
|
986
998
|
this.spinnerContainer_ = shaka.util.Dom.createHTMLElement('div');
|
|
987
999
|
this.spinnerContainer_.classList.add('shaka-spinner-container');
|
|
988
1000
|
this.videoContainer_.appendChild(this.spinnerContainer_);
|
|
@@ -1139,7 +1151,7 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
|
|
|
1139
1151
|
* @private
|
|
1140
1152
|
*/
|
|
1141
1153
|
addClientAdContainer_() {
|
|
1142
|
-
/** @private {
|
|
1154
|
+
/** @private {HTMLElement} */
|
|
1143
1155
|
this.clientAdContainer_ = shaka.util.Dom.createHTMLElement('div');
|
|
1144
1156
|
this.clientAdContainer_.classList.add('shaka-client-side-ad-container');
|
|
1145
1157
|
shaka.ui.Utils.setDisplay(this.clientAdContainer_, false);
|