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
package/lib/player.js
CHANGED
|
@@ -38,6 +38,7 @@ goog.require('shaka.net.NetworkingUtils');
|
|
|
38
38
|
goog.require('shaka.text.SimpleTextDisplayer');
|
|
39
39
|
goog.require('shaka.text.StubTextDisplayer');
|
|
40
40
|
goog.require('shaka.text.TextEngine');
|
|
41
|
+
goog.require('shaka.text.Utils');
|
|
41
42
|
goog.require('shaka.text.UITextDisplayer');
|
|
42
43
|
goog.require('shaka.text.WebVttGenerator');
|
|
43
44
|
goog.require('shaka.util.BufferUtils');
|
|
@@ -50,6 +51,7 @@ goog.require('shaka.util.Error');
|
|
|
50
51
|
goog.require('shaka.util.EventManager');
|
|
51
52
|
goog.require('shaka.util.FakeEvent');
|
|
52
53
|
goog.require('shaka.util.FakeEventTarget');
|
|
54
|
+
goog.require('shaka.util.Functional');
|
|
53
55
|
goog.require('shaka.util.IDestroyable');
|
|
54
56
|
goog.require('shaka.util.LanguageUtils');
|
|
55
57
|
goog.require('shaka.util.ManifestParserUtils');
|
|
@@ -118,9 +120,9 @@ goog.requireType('shaka.media.PresentationTimeline');
|
|
|
118
120
|
/**
|
|
119
121
|
* @event shaka.Player.DownloadHeadersReceived
|
|
120
122
|
* @description Fired when the networking engine has received the headers for
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
123
|
+
* a download, but before the body has been downloaded.
|
|
124
|
+
* If the HTTP plugin being used does not track this information, this event
|
|
125
|
+
* will default to being fired when the body is received, instead.
|
|
124
126
|
* @property {!Object.<string, string>} headers
|
|
125
127
|
* @property {!shaka.extern.Request} request
|
|
126
128
|
* @property {!shaka.net.NetworkingEngine.RequestType} type
|
|
@@ -173,8 +175,8 @@ goog.requireType('shaka.media.PresentationTimeline');
|
|
|
173
175
|
/**
|
|
174
176
|
* @event shaka.Player.MediaQualityChangedEvent
|
|
175
177
|
* @description Fired when the media quality changes at the playhead.
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
+
* That may be caused by an adaptation change or a DASH period transition.
|
|
179
|
+
* Separate events are emitted for audio and video contentTypes.
|
|
178
180
|
* @property {string} type
|
|
179
181
|
* 'mediaqualitychanged'
|
|
180
182
|
* @property {shaka.extern.MediaQualityInfo} mediaQuality
|
|
@@ -184,10 +186,19 @@ goog.requireType('shaka.media.PresentationTimeline');
|
|
|
184
186
|
* @exportDoc
|
|
185
187
|
*/
|
|
186
188
|
|
|
189
|
+
/**
|
|
190
|
+
* @event shaka.Player.MediaSourceRecoveredEvent
|
|
191
|
+
* @description Fired when MediaSource has been successfully recovered
|
|
192
|
+
* after occurrence of video error.
|
|
193
|
+
* @property {string} type
|
|
194
|
+
* 'mediasourcerecovered'
|
|
195
|
+
* @exportDoc
|
|
196
|
+
*/
|
|
197
|
+
|
|
187
198
|
/**
|
|
188
199
|
* @event shaka.Player.AudioTrackChangedEvent
|
|
189
200
|
* @description Fired when the audio track changes at the playhead.
|
|
190
|
-
*
|
|
201
|
+
* That may be caused by a user requesting to chang audio tracks.
|
|
191
202
|
* @property {string} type
|
|
192
203
|
* 'audiotrackchanged'
|
|
193
204
|
* @property {shaka.extern.MediaQualityInfo} mediaQuality
|
|
@@ -243,6 +254,8 @@ goog.requireType('shaka.media.PresentationTimeline');
|
|
|
243
254
|
/**
|
|
244
255
|
* @event shaka.Player.TextTrackVisibilityEvent
|
|
245
256
|
* @description Fired when text track visibility changes.
|
|
257
|
+
* An app may want to look at <code>getStats()</code> or
|
|
258
|
+
* <code>getVariantTracks()</code> to see what happened.
|
|
246
259
|
* @property {string} type
|
|
247
260
|
* 'texttrackvisibility'
|
|
248
261
|
* @exportDoc
|
|
@@ -253,6 +266,8 @@ goog.requireType('shaka.media.PresentationTimeline');
|
|
|
253
266
|
* @event shaka.Player.TracksChangedEvent
|
|
254
267
|
* @description Fired when the list of tracks changes. For example, this will
|
|
255
268
|
* happen when new tracks are added/removed or when track restrictions change.
|
|
269
|
+
* An app may want to look at <code>getVariantTracks()</code> to see what
|
|
270
|
+
* happened.
|
|
256
271
|
* @property {string} type
|
|
257
272
|
* 'trackschanged'
|
|
258
273
|
* @exportDoc
|
|
@@ -276,9 +291,11 @@ goog.requireType('shaka.media.PresentationTimeline');
|
|
|
276
291
|
/**
|
|
277
292
|
* @event shaka.Player.VariantChangedEvent
|
|
278
293
|
* @description Fired when a call from the application caused a variant change.
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
294
|
+
* Can be triggered by calls to <code>selectVariantTrack()</code> or
|
|
295
|
+
* <code>selectAudioLanguage()</code>. Does not fire when an automatic
|
|
296
|
+
* adaptation causes a variant change.
|
|
297
|
+
* An app may want to look at <code>getStats()</code> or
|
|
298
|
+
* <code>getVariantTracks()</code> to see what happened.
|
|
282
299
|
* @property {string} type
|
|
283
300
|
* 'variantchanged'
|
|
284
301
|
* @property {shaka.extern.Track} oldTrack
|
|
@@ -290,8 +307,10 @@ goog.requireType('shaka.media.PresentationTimeline');
|
|
|
290
307
|
/**
|
|
291
308
|
* @event shaka.Player.TextChangedEvent
|
|
292
309
|
* @description Fired when a call from the application caused a text stream
|
|
293
|
-
*
|
|
294
|
-
*
|
|
310
|
+
* change. Can be triggered by calls to <code>selectTextTrack()</code> or
|
|
311
|
+
* <code>selectTextLanguage()</code>.
|
|
312
|
+
* An app may want to look at <code>getStats()</code> or
|
|
313
|
+
* <code>getTextTracks()</code> to see what happened.
|
|
295
314
|
* @property {string} type
|
|
296
315
|
* 'textchanged'
|
|
297
316
|
* @exportDoc
|
|
@@ -370,8 +389,8 @@ goog.requireType('shaka.media.PresentationTimeline');
|
|
|
370
389
|
* @property {string} type
|
|
371
390
|
* 'abrstatuschanged'
|
|
372
391
|
* @property {boolean} newStatus
|
|
373
|
-
*
|
|
374
|
-
*
|
|
392
|
+
* The new status of the application. True for 'is enabled' and
|
|
393
|
+
* false otherwise.
|
|
375
394
|
* @exportDoc
|
|
376
395
|
*/
|
|
377
396
|
|
|
@@ -425,7 +444,8 @@ goog.requireType('shaka.media.PresentationTimeline');
|
|
|
425
444
|
/**
|
|
426
445
|
* @event shaka.Player.StallDetectedEvent
|
|
427
446
|
* @description Fired when a stall in playback is detected by the StallDetector.
|
|
428
|
-
*
|
|
447
|
+
* Not all stalls are caused by gaps in the buffered ranges.
|
|
448
|
+
* An app may want to look at <code>getStats()</code> to see what happened.
|
|
429
449
|
* @property {string} type
|
|
430
450
|
* 'stalldetected'
|
|
431
451
|
* @exportDoc
|
|
@@ -435,7 +455,8 @@ goog.requireType('shaka.media.PresentationTimeline');
|
|
|
435
455
|
/**
|
|
436
456
|
* @event shaka.Player.GapJumpedEvent
|
|
437
457
|
* @description Fired when the GapJumpingController jumps over a gap in the
|
|
438
|
-
*
|
|
458
|
+
* buffered ranges.
|
|
459
|
+
* An app may want to look at <code>getStats()</code> to see what happened.
|
|
439
460
|
* @property {string} type
|
|
440
461
|
* 'gapjumped'
|
|
441
462
|
* @exportDoc
|
|
@@ -475,7 +496,7 @@ goog.requireType('shaka.media.PresentationTimeline');
|
|
|
475
496
|
/**
|
|
476
497
|
* @event shaka.Player.FirstQuartile
|
|
477
498
|
* @description Fires when the content playhead crosses first quartile.
|
|
478
|
-
*
|
|
499
|
+
* Only for VoD.
|
|
479
500
|
* @property {string} type
|
|
480
501
|
* 'firstquartile'
|
|
481
502
|
* @exportDoc
|
|
@@ -485,7 +506,7 @@ goog.requireType('shaka.media.PresentationTimeline');
|
|
|
485
506
|
/**
|
|
486
507
|
* @event shaka.Player.Midpoint
|
|
487
508
|
* @description Fires when the content playhead crosses midpoint.
|
|
488
|
-
*
|
|
509
|
+
* Only for VoD.
|
|
489
510
|
* @property {string} type
|
|
490
511
|
* 'midpoint'
|
|
491
512
|
* @exportDoc
|
|
@@ -495,7 +516,7 @@ goog.requireType('shaka.media.PresentationTimeline');
|
|
|
495
516
|
/**
|
|
496
517
|
* @event shaka.Player.ThirdQuartile
|
|
497
518
|
* @description Fires when the content playhead crosses third quartile.
|
|
498
|
-
*
|
|
519
|
+
* Only for VoD.
|
|
499
520
|
* @property {string} type
|
|
500
521
|
* 'thirdquartile'
|
|
501
522
|
* @exportDoc
|
|
@@ -505,7 +526,7 @@ goog.requireType('shaka.media.PresentationTimeline');
|
|
|
505
526
|
/**
|
|
506
527
|
* @event shaka.Player.Complete
|
|
507
528
|
* @description Fires when the content completes playing.
|
|
508
|
-
*
|
|
529
|
+
* Only for VoD.
|
|
509
530
|
* @property {string} type
|
|
510
531
|
* 'complete'
|
|
511
532
|
* @exportDoc
|
|
@@ -547,10 +568,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
547
568
|
* When provided, the player will attach to <code>mediaElement</code>,
|
|
548
569
|
* similar to calling <code>attach</code>. When not provided, the player
|
|
549
570
|
* will remain detached.
|
|
571
|
+
* @param {HTMLElement=} videoContainer
|
|
572
|
+
* The videoContainer to construct UITextDisplayer
|
|
550
573
|
* @param {function(shaka.Player)=} dependencyInjector Optional callback
|
|
551
574
|
* which is called to inject mocks into the Player. Used for testing.
|
|
552
575
|
*/
|
|
553
|
-
constructor(mediaElement, dependencyInjector) {
|
|
576
|
+
constructor(mediaElement, videoContainer = null, dependencyInjector) {
|
|
554
577
|
super();
|
|
555
578
|
|
|
556
579
|
/** @private {shaka.Player.LoadMode} */
|
|
@@ -560,7 +583,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
560
583
|
this.video_ = null;
|
|
561
584
|
|
|
562
585
|
/** @private {HTMLElement} */
|
|
563
|
-
this.videoContainer_ =
|
|
586
|
+
this.videoContainer_ = videoContainer;
|
|
564
587
|
|
|
565
588
|
/**
|
|
566
589
|
* Since we may not always have a text displayer created (e.g. before |load|
|
|
@@ -790,6 +813,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
790
813
|
this.networkingEngine_ = this.createNetworkingEngine();
|
|
791
814
|
this.networkingEngine_.setForceHTTP(this.config_.streaming.forceHTTP);
|
|
792
815
|
this.networkingEngine_.setForceHTTPS(this.config_.streaming.forceHTTPS);
|
|
816
|
+
this.networkingEngine_.setMinBytesForProgressEvents(
|
|
817
|
+
this.config_.streaming.minBytesForProgressEvents);
|
|
793
818
|
|
|
794
819
|
/** @private {shaka.extern.IAdManager} */
|
|
795
820
|
this.adManager_ = null;
|
|
@@ -887,6 +912,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
887
912
|
'use the attach method instead.');
|
|
888
913
|
this.attach(mediaElement, /* initializeMediaSource= */ true);
|
|
889
914
|
}
|
|
915
|
+
|
|
916
|
+
/** @private {?shaka.extern.TextDisplayer} */
|
|
917
|
+
this.textDisplayer_ = null;
|
|
890
918
|
}
|
|
891
919
|
|
|
892
920
|
/**
|
|
@@ -1410,6 +1438,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1410
1438
|
this.cmsdManager_.reset();
|
|
1411
1439
|
}
|
|
1412
1440
|
|
|
1441
|
+
if (this.textDisplayer_) {
|
|
1442
|
+
await this.textDisplayer_.destroy();
|
|
1443
|
+
this.textDisplayer_ = null;
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1413
1446
|
if (this.video_) {
|
|
1414
1447
|
// Remove all track nodes
|
|
1415
1448
|
shaka.util.Dom.removeAllChildren(this.video_);
|
|
@@ -1623,6 +1656,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1623
1656
|
preloadManager = await this.preloadInner_(
|
|
1624
1657
|
assetUri, startTime, mimeType, /* standardLoad= */ true);
|
|
1625
1658
|
if (preloadManager) {
|
|
1659
|
+
preloadManager.markIsLoad();
|
|
1626
1660
|
preloadManager.setEventHandoffTarget(this);
|
|
1627
1661
|
this.stats_ = preloadManager.getStats();
|
|
1628
1662
|
preloadManager.start();
|
|
@@ -1967,6 +2001,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1967
2001
|
this.createdPreloadManagers_.push(preloadManager);
|
|
1968
2002
|
return preloadManager;
|
|
1969
2003
|
});
|
|
2004
|
+
} else {
|
|
2005
|
+
preloadManagerPromise = preloadManagerPromise.then((preloadManager) => {
|
|
2006
|
+
preloadManager.markIsLoad();
|
|
2007
|
+
return preloadManager;
|
|
2008
|
+
});
|
|
1970
2009
|
}
|
|
1971
2010
|
return preloadManagerPromise;
|
|
1972
2011
|
}
|
|
@@ -2088,7 +2127,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2088
2127
|
let metadataType = type;
|
|
2089
2128
|
if (type == 'com.apple.hls.interstitial') {
|
|
2090
2129
|
metadataType = 'com.apple.quicktime.HLS';
|
|
2091
|
-
/** @type {shaka.extern.
|
|
2130
|
+
/** @type {shaka.extern.HLSInterstitial} */
|
|
2092
2131
|
const interstitial = {
|
|
2093
2132
|
startTime,
|
|
2094
2133
|
endTime,
|
|
@@ -2096,11 +2135,14 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2096
2135
|
};
|
|
2097
2136
|
if (this.adManager_) {
|
|
2098
2137
|
goog.asserts.assert(this.video_, 'Must have video');
|
|
2099
|
-
this.adManager_.
|
|
2138
|
+
this.adManager_.onHLSInterstitialMetadata(
|
|
2100
2139
|
this, this.video_, interstitial);
|
|
2101
2140
|
}
|
|
2102
2141
|
}
|
|
2103
2142
|
for (const payload of values) {
|
|
2143
|
+
if (payload.name == 'ID') {
|
|
2144
|
+
continue;
|
|
2145
|
+
}
|
|
2104
2146
|
preloadManager.addQueuedOperation(false, () => {
|
|
2105
2147
|
this.dispatchMetadataEvent_(
|
|
2106
2148
|
startTime, endTime, metadataType, payload);
|
|
@@ -2109,6 +2151,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2109
2151
|
},
|
|
2110
2152
|
disableStream: (stream) => this.disableStream(
|
|
2111
2153
|
stream, this.config_.streaming.maxDisabledTime),
|
|
2154
|
+
addFont: (name, url) => this.addFont(name, url),
|
|
2112
2155
|
};
|
|
2113
2156
|
const regionTimeline =
|
|
2114
2157
|
new shaka.media.RegionTimeline(() => this.seekRange());
|
|
@@ -2122,6 +2165,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2122
2165
|
preloadManager.addQueuedOperation(false, () => {
|
|
2123
2166
|
if (this.adManager_) {
|
|
2124
2167
|
this.adManager_.onDashTimedMetadata(region);
|
|
2168
|
+
goog.asserts.assert(this.video_, 'Must have video');
|
|
2169
|
+
this.adManager_.onDASHInterstitialMetadata(
|
|
2170
|
+
this, this.video_, region);
|
|
2125
2171
|
}
|
|
2126
2172
|
});
|
|
2127
2173
|
});
|
|
@@ -2304,6 +2350,30 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2304
2350
|
return false;
|
|
2305
2351
|
}
|
|
2306
2352
|
|
|
2353
|
+
/**
|
|
2354
|
+
* @private
|
|
2355
|
+
*/
|
|
2356
|
+
createTextDisplayer_() {
|
|
2357
|
+
// When changing text visibility we need to update both the text displayer
|
|
2358
|
+
// and streaming engine because we don't always stream text. To ensure
|
|
2359
|
+
// that the text displayer and streaming engine are always in sync, wait
|
|
2360
|
+
// until they are both initialized before setting the initial value.
|
|
2361
|
+
const textDisplayerFactory = this.config_.textDisplayFactory;
|
|
2362
|
+
if (textDisplayerFactory === this.lastTextFactory_) {
|
|
2363
|
+
return;
|
|
2364
|
+
}
|
|
2365
|
+
this.textDisplayer_ = textDisplayerFactory();
|
|
2366
|
+
if (this.textDisplayer_.configure) {
|
|
2367
|
+
this.textDisplayer_.configure(this.config_.textDisplayer);
|
|
2368
|
+
} else {
|
|
2369
|
+
shaka.Deprecate.deprecateFeature(5,
|
|
2370
|
+
'Text displayer w/ configure',
|
|
2371
|
+
'Text displayer should have a "configure" method!');
|
|
2372
|
+
}
|
|
2373
|
+
this.lastTextFactory_ = textDisplayerFactory;
|
|
2374
|
+
this.textDisplayer_.setTextVisibility(this.isTextVisible_);
|
|
2375
|
+
}
|
|
2376
|
+
|
|
2307
2377
|
/**
|
|
2308
2378
|
* Initializes the media source engine.
|
|
2309
2379
|
*
|
|
@@ -2324,24 +2394,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2324
2394
|
|
|
2325
2395
|
this.makeStateChangeEvent_('media-source');
|
|
2326
2396
|
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
// until they are both initialized before setting the initial value.
|
|
2331
|
-
const textDisplayerFactory = this.config_.textDisplayFactory;
|
|
2332
|
-
const textDisplayer = textDisplayerFactory();
|
|
2333
|
-
if (textDisplayer.configure) {
|
|
2334
|
-
textDisplayer.configure(this.config_.textDisplayer);
|
|
2335
|
-
} else {
|
|
2336
|
-
shaka.Deprecate.deprecateFeature(5,
|
|
2337
|
-
'Text displayer w/ configure',
|
|
2338
|
-
'Text displayer should have a "configure" method!');
|
|
2339
|
-
}
|
|
2340
|
-
this.lastTextFactory_ = textDisplayerFactory;
|
|
2341
|
-
|
|
2397
|
+
this.createTextDisplayer_();
|
|
2398
|
+
goog.asserts.assert(this.textDisplayer_,
|
|
2399
|
+
'Text displayer should be created already');
|
|
2342
2400
|
const mediaSourceEngine = this.createMediaSourceEngine(
|
|
2343
2401
|
this.video_,
|
|
2344
|
-
|
|
2402
|
+
this.textDisplayer_,
|
|
2345
2403
|
{
|
|
2346
2404
|
getKeySystem: () => this.keySystem(),
|
|
2347
2405
|
onMetadata: (metadata, offset, endTime) => {
|
|
@@ -2487,6 +2545,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2487
2545
|
'https://bit.ly/3clctcj for details.');
|
|
2488
2546
|
}
|
|
2489
2547
|
|
|
2548
|
+
if (this.cmcdManager_) {
|
|
2549
|
+
this.cmcdManager_.setLowLatency(
|
|
2550
|
+
this.manifest_.isLowLatency && this.config_.streaming.lowLatencyMode);
|
|
2551
|
+
}
|
|
2552
|
+
|
|
2490
2553
|
shaka.Player.applyPlayRange_(this.manifest_.presentationTimeline,
|
|
2491
2554
|
this.config_.playRangeStart,
|
|
2492
2555
|
this.config_.playRangeEnd);
|
|
@@ -2509,7 +2572,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2509
2572
|
};
|
|
2510
2573
|
|
|
2511
2574
|
if (!this.config_.streaming.startAtSegmentBoundary) {
|
|
2512
|
-
|
|
2575
|
+
let startTime = this.startTime_;
|
|
2576
|
+
if (startTime == null && this.manifest_.startTime) {
|
|
2577
|
+
startTime = this.manifest_.startTime;
|
|
2578
|
+
}
|
|
2579
|
+
setupPlayhead(startTime);
|
|
2513
2580
|
}
|
|
2514
2581
|
|
|
2515
2582
|
// Now we can switch to the initial variant.
|
|
@@ -2522,6 +2589,9 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2522
2589
|
if (this.config_.streaming.startAtSegmentBoundary) {
|
|
2523
2590
|
const timeline = this.manifest_.presentationTimeline;
|
|
2524
2591
|
let initialTime = this.startTime_ || this.video_.currentTime;
|
|
2592
|
+
if (this.startTime_ == null && this.manifest_.startTime) {
|
|
2593
|
+
initialTime = this.manifest_.startTime;
|
|
2594
|
+
}
|
|
2525
2595
|
const seekRangeStart = timeline.getSeekRangeStart();
|
|
2526
2596
|
const seekRangeEnd = timeline.getSeekRangeEnd();
|
|
2527
2597
|
if (initialTime < seekRangeStart) {
|
|
@@ -2841,6 +2911,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2841
2911
|
}
|
|
2842
2912
|
|
|
2843
2913
|
if (mediaElement.textTracks) {
|
|
2914
|
+
this.createTextDisplayer_();
|
|
2844
2915
|
this.loadEventManager_.listen(
|
|
2845
2916
|
mediaElement.textTracks, 'addtrack', (e) => {
|
|
2846
2917
|
const trackEvent = /** @type {!TrackEvent} */(e);
|
|
@@ -2871,6 +2942,22 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2871
2942
|
this.loadEventManager_.listen(
|
|
2872
2943
|
mediaElement.textTracks, 'change',
|
|
2873
2944
|
() => this.onTracksChanged_());
|
|
2945
|
+
this.loadEventManager_.listen(
|
|
2946
|
+
mediaElement, 'enterpictureinpicture', () => {
|
|
2947
|
+
const track = this.getFilteredTextTracks_()
|
|
2948
|
+
.find((t) => t.mode !== 'disabled');
|
|
2949
|
+
if (track) {
|
|
2950
|
+
track.mode = 'showing';
|
|
2951
|
+
}
|
|
2952
|
+
});
|
|
2953
|
+
this.loadEventManager_.listen(
|
|
2954
|
+
mediaElement, 'leavepictureinpicture', () => {
|
|
2955
|
+
const track = this.getFilteredTextTracks_()
|
|
2956
|
+
.find((t) => t.mode !== 'disabled');
|
|
2957
|
+
if (track) {
|
|
2958
|
+
track.mode = 'hidden';
|
|
2959
|
+
}
|
|
2960
|
+
});
|
|
2874
2961
|
}
|
|
2875
2962
|
|
|
2876
2963
|
// By setting |src| we are done "loading" with src=. We don't need to set
|
|
@@ -2955,6 +3042,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2955
3042
|
});
|
|
2956
3043
|
} else if (textTracks.length > 0) {
|
|
2957
3044
|
this.isTextVisible_ = true;
|
|
3045
|
+
this.textDisplayer_.setTextVisibility(true);
|
|
2958
3046
|
}
|
|
2959
3047
|
|
|
2960
3048
|
// If we have moved on to another piece of content while waiting for
|
|
@@ -2962,6 +3050,20 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
2962
3050
|
if (unloaded) {
|
|
2963
3051
|
return;
|
|
2964
3052
|
}
|
|
3053
|
+
let enabledNativeTrack = false;
|
|
3054
|
+
for (const track of textTracks) {
|
|
3055
|
+
if (track.mode !== 'disabled') {
|
|
3056
|
+
if (!enabledNativeTrack) {
|
|
3057
|
+
this.enableNativeTrack_(track);
|
|
3058
|
+
enabledNativeTrack = true;
|
|
3059
|
+
} else {
|
|
3060
|
+
track.mode = 'disabled';
|
|
3061
|
+
shaka.log.alwaysWarn(
|
|
3062
|
+
'Found more than one enabled text track, disabling it',
|
|
3063
|
+
track);
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
2965
3067
|
|
|
2966
3068
|
this.setupPreferredTextOnSrc_();
|
|
2967
3069
|
});
|
|
@@ -3083,55 +3185,58 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3083
3185
|
// Hidden mode is required for the cuechange event to launch correctly
|
|
3084
3186
|
track.mode = 'hidden';
|
|
3085
3187
|
this.loadEventManager_.listen(track, 'cuechange', () => {
|
|
3086
|
-
if (
|
|
3087
|
-
|
|
3088
|
-
|
|
3188
|
+
if (track.activeCues) {
|
|
3189
|
+
for (const cue of track.activeCues) {
|
|
3190
|
+
this.dispatchMetadataEvent_(cue.startTime, cue.endTime,
|
|
3191
|
+
cue.type, cue.value);
|
|
3089
3192
|
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
for (const cue of track.activeCues) {
|
|
3094
|
-
this.dispatchMetadataEvent_(cue.startTime, cue.endTime,
|
|
3095
|
-
cue.type, cue.value);
|
|
3096
|
-
|
|
3097
|
-
if (this.adManager_) {
|
|
3098
|
-
this.adManager_.onCueMetadataChange(cue.value);
|
|
3099
|
-
}
|
|
3100
|
-
if (cue.type == 'com.apple.quicktime.HLS' && cue.startTime != null) {
|
|
3101
|
-
let interstitial = interstitials.find((i) => {
|
|
3102
|
-
return i.startTime == cue.startTime && i.endTime == cue.endTime;
|
|
3103
|
-
});
|
|
3104
|
-
if (!interstitial) {
|
|
3105
|
-
interstitial = /** @type {shaka.extern.Interstitial} */ ({
|
|
3106
|
-
startTime: cue.startTime,
|
|
3107
|
-
endTime: cue.endTime,
|
|
3108
|
-
values: [],
|
|
3109
|
-
});
|
|
3110
|
-
interstitials.push(interstitial);
|
|
3193
|
+
if (this.adManager_) {
|
|
3194
|
+
this.adManager_.onCueMetadataChange(cue.value);
|
|
3111
3195
|
}
|
|
3112
|
-
interstitial.values.push(cue.value);
|
|
3113
3196
|
}
|
|
3114
3197
|
}
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3198
|
+
if (track.cues) {
|
|
3199
|
+
/** @type {!Array.<shaka.extern.HLSInterstitial>} */
|
|
3200
|
+
const interstitials = [];
|
|
3201
|
+
|
|
3202
|
+
for (const cue of track.cues) {
|
|
3203
|
+
if (cue.type == 'com.apple.quicktime.HLS' && cue.startTime != null) {
|
|
3204
|
+
let interstitial = interstitials.find((i) => {
|
|
3205
|
+
return i.startTime == cue.startTime && i.endTime == cue.endTime;
|
|
3206
|
+
});
|
|
3207
|
+
if (!interstitial) {
|
|
3208
|
+
interstitial = /** @type {shaka.extern.HLSInterstitial} */ ({
|
|
3209
|
+
startTime: cue.startTime,
|
|
3210
|
+
endTime: cue.endTime,
|
|
3211
|
+
values: [],
|
|
3212
|
+
});
|
|
3213
|
+
interstitials.push(interstitial);
|
|
3214
|
+
}
|
|
3215
|
+
interstitial.values.push(cue.value);
|
|
3216
|
+
}
|
|
3121
3217
|
}
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
interstitial.values.push({
|
|
3126
|
-
key: 'CUE',
|
|
3127
|
-
description: '',
|
|
3128
|
-
data: 'ONCE',
|
|
3129
|
-
mimeType: null,
|
|
3130
|
-
pictureType: null,
|
|
3218
|
+
for (const interstitial of interstitials) {
|
|
3219
|
+
const isValidInterstitial = interstitial.values.some((value) => {
|
|
3220
|
+
return value.key == 'X-ASSET-URI' || value.key == 'X-ASSET-LIST';
|
|
3131
3221
|
});
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3222
|
+
if (!isValidInterstitial) {
|
|
3223
|
+
continue;
|
|
3224
|
+
}
|
|
3225
|
+
if (this.adManager_) {
|
|
3226
|
+
const isPreRoll = interstitial.startTime == 0;
|
|
3227
|
+
// It seems that CUE is natively omitted, by default we use CUE=ONCE
|
|
3228
|
+
// to avoid repeating them.
|
|
3229
|
+
interstitial.values.push({
|
|
3230
|
+
key: 'CUE',
|
|
3231
|
+
description: '',
|
|
3232
|
+
data: isPreRoll ? 'ONCE,PRE' : 'ONCE',
|
|
3233
|
+
mimeType: null,
|
|
3234
|
+
pictureType: null,
|
|
3235
|
+
});
|
|
3236
|
+
goog.asserts.assert(this.video_, 'Must have video');
|
|
3237
|
+
this.adManager_.onHLSInterstitialMetadata(
|
|
3238
|
+
this, this.video_, interstitial);
|
|
3239
|
+
}
|
|
3135
3240
|
}
|
|
3136
3241
|
}
|
|
3137
3242
|
});
|
|
@@ -3836,6 +3941,15 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3836
3941
|
delete config['mediaSource']['sourceBufferExtraFeatures'];
|
|
3837
3942
|
}
|
|
3838
3943
|
|
|
3944
|
+
// Deprecate 'manifest.hls.useSafariBehaviorForLive' configuration.
|
|
3945
|
+
if (config['manifest'] && config['manifest']['hls'] &&
|
|
3946
|
+
'useSafariBehaviorForLive' in config['manifest']['hls']) {
|
|
3947
|
+
shaka.Deprecate.deprecateFeature(5,
|
|
3948
|
+
'manifest.hls.useSafariBehaviorForLive configuration',
|
|
3949
|
+
'Please Use liveSync config to keep on live Edge instead.');
|
|
3950
|
+
delete config['manifest']['hls']['useSafariBehaviorForLive'];
|
|
3951
|
+
}
|
|
3952
|
+
|
|
3839
3953
|
// If lowLatencyMode is enabled, and inaccurateManifestTolerance and
|
|
3840
3954
|
// rebufferingGoal and segmentPrefetchLimit and baseDelay and
|
|
3841
3955
|
// autoCorrectDrift and maxDisabledTime are not specified, set
|
|
@@ -3950,6 +4064,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3950
4064
|
if (this.networkingEngine_) {
|
|
3951
4065
|
this.networkingEngine_.setForceHTTP(this.config_.streaming.forceHTTP);
|
|
3952
4066
|
this.networkingEngine_.setForceHTTPS(this.config_.streaming.forceHTTPS);
|
|
4067
|
+
this.networkingEngine_.setMinBytesForProgressEvents(
|
|
4068
|
+
this.config_.streaming.minBytesForProgressEvents);
|
|
3953
4069
|
}
|
|
3954
4070
|
|
|
3955
4071
|
if (this.mediaSourceEngine_) {
|
|
@@ -3957,18 +4073,25 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3957
4073
|
const {segmentRelativeVttTiming} = this.config_.manifest;
|
|
3958
4074
|
this.mediaSourceEngine_.setSegmentRelativeVttTiming(
|
|
3959
4075
|
segmentRelativeVttTiming);
|
|
4076
|
+
}
|
|
3960
4077
|
|
|
4078
|
+
if (this.textDisplayer_) {
|
|
3961
4079
|
const textDisplayerFactory = this.config_.textDisplayFactory;
|
|
3962
4080
|
if (this.lastTextFactory_ != textDisplayerFactory) {
|
|
3963
|
-
const
|
|
3964
|
-
|
|
3965
|
-
|
|
4081
|
+
const oldDisplayer = this.textDisplayer_;
|
|
4082
|
+
this.textDisplayer_ = textDisplayerFactory();
|
|
4083
|
+
if (this.textDisplayer_.configure) {
|
|
4084
|
+
this.textDisplayer_.configure(this.config_.textDisplayer);
|
|
3966
4085
|
} else {
|
|
3967
4086
|
shaka.Deprecate.deprecateFeature(5,
|
|
3968
4087
|
'Text displayer w/ configure',
|
|
3969
4088
|
'Text displayer should have a "configure" method!');
|
|
3970
4089
|
}
|
|
3971
|
-
this.
|
|
4090
|
+
this.textDisplayer_.setTextVisibility(oldDisplayer.isTextVisible());
|
|
4091
|
+
oldDisplayer.destroy();
|
|
4092
|
+
if (this.mediaSourceEngine_) {
|
|
4093
|
+
this.mediaSourceEngine_.setTextDisplayer(this.textDisplayer_);
|
|
4094
|
+
}
|
|
3972
4095
|
this.lastTextFactory_ = textDisplayerFactory;
|
|
3973
4096
|
|
|
3974
4097
|
if (this.streamingEngine_) {
|
|
@@ -3976,12 +4099,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3976
4099
|
this.streamingEngine_.reloadTextStream();
|
|
3977
4100
|
}
|
|
3978
4101
|
} else {
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
displayer.configure(this.config_.textDisplayer);
|
|
4102
|
+
if (this.textDisplayer_.configure) {
|
|
4103
|
+
this.textDisplayer_.configure(this.config_.textDisplayer);
|
|
3982
4104
|
}
|
|
3983
4105
|
}
|
|
3984
4106
|
}
|
|
4107
|
+
|
|
3985
4108
|
if (this.abrManager_) {
|
|
3986
4109
|
this.abrManager_.configure(this.config_.abr);
|
|
3987
4110
|
// Simply enable/disable ABR with each call, since multiple calls to these
|
|
@@ -4829,20 +4952,42 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4829
4952
|
this.currentTextLanguage_ = stream.language;
|
|
4830
4953
|
} else if (this.video_ && this.video_.src && this.video_.textTracks) {
|
|
4831
4954
|
const textTracks = this.getFilteredTextTracks_();
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4955
|
+
const oldTrack = textTracks.find((textTrack) =>
|
|
4956
|
+
textTrack.mode !== 'disabled');
|
|
4957
|
+
const newTrack = textTracks.find((textTrack) =>
|
|
4958
|
+
shaka.util.StreamUtils.html5TrackId(textTrack) === track.id);
|
|
4959
|
+
if (oldTrack !== newTrack) {
|
|
4960
|
+
if (oldTrack) {
|
|
4961
|
+
oldTrack.mode = 'disabled';
|
|
4962
|
+
this.loadEventManager_.unlisten(oldTrack, 'cuechange');
|
|
4963
|
+
this.textDisplayer_.remove(0, Infinity);
|
|
4964
|
+
}
|
|
4965
|
+
if (newTrack) {
|
|
4966
|
+
this.enableNativeTrack_(newTrack);
|
|
4840
4967
|
}
|
|
4841
4968
|
}
|
|
4842
4969
|
this.onTextChanged_();
|
|
4843
4970
|
}
|
|
4844
4971
|
}
|
|
4845
4972
|
|
|
4973
|
+
/**
|
|
4974
|
+
* @param {!TextTrack} track
|
|
4975
|
+
* @private
|
|
4976
|
+
*/
|
|
4977
|
+
enableNativeTrack_(track) {
|
|
4978
|
+
this.loadEventManager_.listen(track, 'cuechange', () => {
|
|
4979
|
+
// Always remove cues from the past to avoid memory grow.
|
|
4980
|
+
const removeEnd = Math.max(0,
|
|
4981
|
+
this.video_.currentTime - this.config_.streaming.bufferBehind);
|
|
4982
|
+
this.textDisplayer_.remove(0, removeEnd);
|
|
4983
|
+
const cues = Array.from(track.activeCues || [])
|
|
4984
|
+
.map(shaka.text.Utils.mapNativeCueToShakaCue)
|
|
4985
|
+
.filter(shaka.util.Functional.isNotNull);
|
|
4986
|
+
this.textDisplayer_.append(cues);
|
|
4987
|
+
});
|
|
4988
|
+
track.mode = document.pictureInPictureElement ? 'showing' : 'hidden';
|
|
4989
|
+
}
|
|
4990
|
+
|
|
4846
4991
|
/**
|
|
4847
4992
|
* Select a specific variant track to play. <code>track</code> should come
|
|
4848
4993
|
* from a call to <code>getVariantTracks</code>. If <code>track</code> cannot
|
|
@@ -5159,20 +5304,14 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5159
5304
|
*/
|
|
5160
5305
|
isTextTrackVisible() {
|
|
5161
5306
|
const expected = this.isTextVisible_;
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
this.loadMode_ == shaka.Player.LoadMode.MEDIA_SOURCE) {
|
|
5165
|
-
// Make sure our values are still in-sync.
|
|
5166
|
-
const actual = this.mediaSourceEngine_.getTextDisplayer().isTextVisible();
|
|
5307
|
+
if (this.textDisplayer_) {
|
|
5308
|
+
const actual = this.textDisplayer_.isTextVisible();
|
|
5167
5309
|
goog.asserts.assert(
|
|
5168
5310
|
actual == expected, 'text visibility has fallen out of sync');
|
|
5169
5311
|
|
|
5170
5312
|
// Always return the actual value so that the app has the most accurate
|
|
5171
5313
|
// information (in the case that the values come out of sync in prod).
|
|
5172
5314
|
return actual;
|
|
5173
|
-
} else if (this.video_ && this.video_.src && this.video_.textTracks) {
|
|
5174
|
-
const textTracks = this.getFilteredTextTracks_();
|
|
5175
|
-
return textTracks.some((t) => t.mode == 'showing');
|
|
5176
5315
|
}
|
|
5177
5316
|
|
|
5178
5317
|
return expected;
|
|
@@ -5301,8 +5440,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5301
5440
|
// Hold of on setting the text visibility until we have all the components
|
|
5302
5441
|
// we need. This ensures that they stay in-sync.
|
|
5303
5442
|
if (this.loadMode_ == shaka.Player.LoadMode.MEDIA_SOURCE) {
|
|
5304
|
-
this.
|
|
5305
|
-
.setTextVisibility(newVisibility);
|
|
5443
|
+
this.textDisplayer_.setTextVisibility(newVisibility);
|
|
5306
5444
|
|
|
5307
5445
|
// When the user wants to see captions, we stream captions. When the user
|
|
5308
5446
|
// doesn't want to see captions, we don't stream captions. This is to
|
|
@@ -5332,15 +5470,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5332
5470
|
}
|
|
5333
5471
|
}
|
|
5334
5472
|
} else if (this.video_ && this.video_.src && this.video_.textTracks) {
|
|
5335
|
-
|
|
5336
|
-
// Find the active track by looking for one which is not disabled. This
|
|
5337
|
-
// is the only way to identify the track which is currently displayed.
|
|
5338
|
-
// Set it to 'showing' or 'hidden' based on newVisibility.
|
|
5339
|
-
for (const textTrack of textTracks) {
|
|
5340
|
-
if (textTrack.mode != 'disabled') {
|
|
5341
|
-
textTrack.mode = newVisibility ? 'showing' : 'hidden';
|
|
5342
|
-
}
|
|
5343
|
-
}
|
|
5473
|
+
this.textDisplayer_.setTextVisibility(newVisibility);
|
|
5344
5474
|
}
|
|
5345
5475
|
|
|
5346
5476
|
// We need to fire the event after we have updated everything so that
|
|
@@ -5795,7 +5925,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
5795
5925
|
vttOffset: 0,
|
|
5796
5926
|
};
|
|
5797
5927
|
const data = shaka.util.BufferUtils.toUint8(buffer);
|
|
5798
|
-
const cues = TextParser.parseMedia(data, time, uri);
|
|
5928
|
+
const cues = TextParser.parseMedia(data, time, uri, /* images= */ []);
|
|
5799
5929
|
|
|
5800
5930
|
const references = [];
|
|
5801
5931
|
for (const cue of cues) {
|
|
@@ -6062,7 +6192,8 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
6062
6192
|
vttOffset: 0,
|
|
6063
6193
|
};
|
|
6064
6194
|
const data = shaka.util.BufferUtils.toUint8(buffer);
|
|
6065
|
-
const cues = obj.parseMedia(
|
|
6195
|
+
const cues = obj.parseMedia(
|
|
6196
|
+
data, time, /* uri= */ null, /* images= */ []);
|
|
6066
6197
|
return shaka.text.WebVttGenerator.convert(cues, adCuePoints);
|
|
6067
6198
|
}
|
|
6068
6199
|
throw new shaka.util.Error(
|
|
@@ -6141,6 +6272,50 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
6141
6272
|
return this.parserFactory_;
|
|
6142
6273
|
}
|
|
6143
6274
|
|
|
6275
|
+
/**
|
|
6276
|
+
* Gets information about the currently fetched video, audio, and text.
|
|
6277
|
+
* In the case of a multi-codec or multi-mimeType manifest, this can let you
|
|
6278
|
+
* determine the exact codecs and mimeTypes being fetched at the moment.
|
|
6279
|
+
*
|
|
6280
|
+
* @return {!shaka.extern.PlaybackInfo}
|
|
6281
|
+
*/
|
|
6282
|
+
getFetchedPlaybackInfo() {
|
|
6283
|
+
const output = /** @type {!shaka.extern.PlaybackInfo} */ ({
|
|
6284
|
+
'video': null,
|
|
6285
|
+
'audio': null,
|
|
6286
|
+
'text': null,
|
|
6287
|
+
});
|
|
6288
|
+
if (this.loadMode_ != shaka.Player.LoadMode.MEDIA_SOURCE) {
|
|
6289
|
+
return output;
|
|
6290
|
+
}
|
|
6291
|
+
const ContentType = shaka.util.ManifestParserUtils.ContentType;
|
|
6292
|
+
const variant = this.streamingEngine_.getCurrentVariant();
|
|
6293
|
+
const textStream = this.streamingEngine_.getCurrentTextStream();
|
|
6294
|
+
const currentTime = this.video_.currentTime;
|
|
6295
|
+
for (const stream of [variant.video, variant.audio, textStream]) {
|
|
6296
|
+
if (!stream || !stream.segmentIndex) {
|
|
6297
|
+
continue;
|
|
6298
|
+
}
|
|
6299
|
+
const position = stream.segmentIndex.find(currentTime);
|
|
6300
|
+
const reference = stream.segmentIndex.get(position);
|
|
6301
|
+
const info = /** @type {!shaka.extern.PlaybackStreamInfo} */ ({
|
|
6302
|
+
'codecs': reference.codecs || stream.codecs,
|
|
6303
|
+
'mimeType': reference.mimeType || stream.mimeType,
|
|
6304
|
+
'bandwidth': reference.bandwidth || stream.bandwidth,
|
|
6305
|
+
});
|
|
6306
|
+
if (stream.type == ContentType.VIDEO) {
|
|
6307
|
+
info['width'] = stream.width;
|
|
6308
|
+
info['height'] = stream.height;
|
|
6309
|
+
output['video'] = info;
|
|
6310
|
+
} else if (stream.type == ContentType.AUDIO) {
|
|
6311
|
+
output['audio'] = info;
|
|
6312
|
+
} else if (stream.type == ContentType.TEXT) {
|
|
6313
|
+
output['text'] = info;
|
|
6314
|
+
}
|
|
6315
|
+
}
|
|
6316
|
+
return output;
|
|
6317
|
+
}
|
|
6318
|
+
|
|
6144
6319
|
/**
|
|
6145
6320
|
* @param {shaka.extern.Variant} variant
|
|
6146
6321
|
* @param {boolean} fromAdaptation
|
|
@@ -6953,7 +7128,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
6953
7128
|
if (this.isTextVisible_) {
|
|
6954
7129
|
// If the cached value says to show text, then update the text displayer
|
|
6955
7130
|
// since it defaults to not shown.
|
|
6956
|
-
this.
|
|
7131
|
+
this.textDisplayer_.setTextVisibility(true);
|
|
6957
7132
|
goog.asserts.assert(this.shouldStreamText_(),
|
|
6958
7133
|
'Should be streaming text');
|
|
6959
7134
|
}
|
|
@@ -7335,6 +7510,11 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
7335
7510
|
try {
|
|
7336
7511
|
const ret = await this.streamingEngine_.resetMediaSource();
|
|
7337
7512
|
fireError = !ret;
|
|
7513
|
+
if (ret) {
|
|
7514
|
+
const event = shaka.Player.makeEvent_(
|
|
7515
|
+
shaka.util.FakeEvent.EventName.MediaSourceRecovered);
|
|
7516
|
+
this.dispatchEvent(event);
|
|
7517
|
+
}
|
|
7338
7518
|
} catch (e) {
|
|
7339
7519
|
fireError = true;
|
|
7340
7520
|
}
|
|
@@ -7357,6 +7537,41 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
7357
7537
|
}
|
|
7358
7538
|
}
|
|
7359
7539
|
|
|
7540
|
+
/**
|
|
7541
|
+
* Load a new font on the page. If the font was already loaded, it does
|
|
7542
|
+
* nothing.
|
|
7543
|
+
*
|
|
7544
|
+
* @param {string} name
|
|
7545
|
+
* @param {string} url
|
|
7546
|
+
* @export
|
|
7547
|
+
*/
|
|
7548
|
+
async addFont(name, url) {
|
|
7549
|
+
if ('fonts' in document && 'FontFace' in window ) {
|
|
7550
|
+
await document.fonts.ready;
|
|
7551
|
+
if (!('entries' in document.fonts)) {
|
|
7552
|
+
return;
|
|
7553
|
+
}
|
|
7554
|
+
const fontFaceSetIteratorToArray = (target) => {
|
|
7555
|
+
const iterable = target.entries();
|
|
7556
|
+
const results = [];
|
|
7557
|
+
let iterator = iterable.next();
|
|
7558
|
+
while (iterator.done === false) {
|
|
7559
|
+
results.push(iterator.value);
|
|
7560
|
+
iterator = iterable.next();
|
|
7561
|
+
}
|
|
7562
|
+
return results;
|
|
7563
|
+
};
|
|
7564
|
+
for (const fontFace of fontFaceSetIteratorToArray(document.fonts)) {
|
|
7565
|
+
if (fontFace.family == name && fontFace.display == 'swap') {
|
|
7566
|
+
// Font already loaded.
|
|
7567
|
+
return;
|
|
7568
|
+
}
|
|
7569
|
+
}
|
|
7570
|
+
const fontFace = new FontFace(name, `url(${url})`, {display: 'swap'});
|
|
7571
|
+
document.fonts.add(fontFace);
|
|
7572
|
+
}
|
|
7573
|
+
}
|
|
7574
|
+
|
|
7360
7575
|
/**
|
|
7361
7576
|
* When we fire region events, we need to copy the information out of the
|
|
7362
7577
|
* region to break the connection with the player's internal data. We do the
|
|
@@ -7848,7 +8063,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
7848
8063
|
* @export
|
|
7849
8064
|
*/
|
|
7850
8065
|
// eslint-disable-next-line no-useless-concat
|
|
7851
|
-
shaka.Player.version = 'v4.
|
|
8066
|
+
shaka.Player.version = 'v4.11.0' + '-uncompiled'; // x-release-please-version
|
|
7852
8067
|
|
|
7853
8068
|
// Initialize the deprecation system using the version string we just set
|
|
7854
8069
|
// on the player.
|