shaka-player 4.9.13 → 4.10.1
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 +4 -0
- package/dist/controls.css +2 -2
- package/dist/controls.css.map +1 -1
- package/dist/deps.js +24 -19
- package/dist/locales.js +46 -35
- package/dist/shaka-player.compiled.d.ts +291 -12
- package/dist/shaka-player.compiled.debug.d.ts +291 -12
- package/dist/shaka-player.compiled.debug.externs.js +443 -6
- package/dist/shaka-player.compiled.debug.js +651 -556
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +443 -6
- package/dist/shaka-player.compiled.js +1325 -1270
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +306 -13
- package/dist/shaka-player.ui.debug.d.ts +306 -13
- package/dist/shaka-player.ui.debug.externs.js +477 -18
- package/dist/shaka-player.ui.debug.js +799 -681
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +477 -18
- package/dist/shaka-player.ui.js +1600 -1533
- package/dist/shaka-player.ui.map +4 -4
- package/externs/shaka/ads.js +21 -1
- package/externs/shaka/manifest.js +20 -1
- package/externs/shaka/manifest_parser.js +18 -1
- package/externs/shaka/player.js +164 -50
- package/lib/ads/ad_manager.js +225 -10
- package/lib/ads/ad_utils.js +323 -0
- package/lib/ads/ads_stats.js +24 -0
- package/lib/ads/client_side_ad_manager.js +42 -34
- package/lib/ads/interstitial_ad.js +292 -0
- package/lib/ads/interstitial_ad_manager.js +772 -0
- package/lib/ads/media_tailor_ad_manager.js +19 -22
- package/lib/ads/server_side_ad_manager.js +12 -15
- package/lib/cast/cast_utils.js +1 -0
- package/lib/cea/cea_utils.js +12 -0
- package/lib/cea/mp4_cea_parser.js +17 -0
- package/lib/dash/dash_parser.js +81 -28
- package/lib/dash/segment_base.js +3 -0
- package/lib/hls/hls_parser.js +429 -121
- package/lib/hls/manifest_text_parser.js +1 -0
- package/lib/media/adaptation_set_criteria.js +31 -1
- package/lib/media/drm_engine.js +16 -2
- package/lib/media/manifest_filterer.js +7 -5
- package/lib/media/preload_manager.js +8 -10
- package/lib/media/presentation_timeline.js +37 -5
- package/lib/media/quality_observer.js +68 -2
- package/lib/media/segment_reference.js +1 -1
- package/lib/media/segment_utils.js +33 -1
- package/lib/media/streaming_engine.js +120 -43
- package/lib/mss/mss_parser.js +13 -2
- package/lib/net/networking_engine.js +1 -0
- package/lib/offline/manifest_converter.js +3 -0
- package/lib/offline/offline_manifest_parser.js +5 -0
- package/lib/offline/storage.js +2 -0
- package/lib/player.js +498 -165
- package/lib/util/fake_event.js +1 -0
- package/lib/util/manifest_parser_utils.js +9 -2
- package/lib/util/mp4_box_parsers.js +32 -0
- package/lib/util/player_configuration.js +21 -9
- package/lib/util/stats.js +43 -0
- package/package.json +1 -1
- package/shaka-player.uncompiled.js +2 -0
- package/ui/ad_counter.js +3 -3
- package/ui/ad_position.js +3 -3
- package/ui/ad_statistics_button.js +237 -0
- package/ui/audio_language_selection.js +8 -4
- package/ui/controls.js +6 -3
- package/ui/element.js +3 -3
- package/ui/enums.js +1 -0
- package/ui/externs/ui.js +3 -0
- package/ui/language_utils.js +48 -3
- package/ui/less/containers.less +32 -0
- package/ui/less/thumbnails.less +13 -0
- package/ui/locales/en.json +2 -0
- package/ui/locales/es-419.json +2 -0
- package/ui/locales/es.json +3 -0
- package/ui/locales/fr.json +1 -0
- package/ui/locales/pl.json +1 -0
- package/ui/locales/pt-BR.json +1 -0
- package/ui/locales/pt-PT.json +1 -0
- package/ui/locales/source.json +8 -0
- package/ui/mute_button.js +4 -4
- package/ui/overflow_menu.js +3 -3
- package/ui/play_button.js +5 -7
- package/ui/presentation_time.js +3 -3
- package/ui/save_video_frame_button.js +196 -0
- package/ui/seek_bar.js +75 -20
- package/ui/skip_ad_button.js +4 -4
- package/ui/statistics_button.js +14 -2
- package/ui/ui.js +15 -0
- package/ui/volume_bar.js +4 -4
package/ui/seek_bar.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
goog.provide('shaka.ui.SeekBar');
|
|
9
9
|
|
|
10
|
-
goog.require('shaka.ads.
|
|
10
|
+
goog.require('shaka.ads.Utils');
|
|
11
11
|
goog.require('shaka.net.NetworkingEngine');
|
|
12
12
|
goog.require('shaka.ui.Constants');
|
|
13
13
|
goog.require('shaka.ui.Locales');
|
|
@@ -113,6 +113,10 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
|
|
|
113
113
|
this.thumbnailContainer_.appendChild(this.thumbnailTime_);
|
|
114
114
|
this.container.appendChild(this.thumbnailContainer_);
|
|
115
115
|
|
|
116
|
+
this.timeContainer_ = shaka.util.Dom.createHTMLElement('div');
|
|
117
|
+
this.timeContainer_.id = 'shaka-player-ui-time-container';
|
|
118
|
+
this.container.appendChild(this.timeContainer_);
|
|
119
|
+
|
|
116
120
|
/**
|
|
117
121
|
* @private {?shaka.extern.Thumbnail}
|
|
118
122
|
*/
|
|
@@ -151,21 +155,21 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
|
|
|
151
155
|
() => this.updateAriaLabel_());
|
|
152
156
|
|
|
153
157
|
this.eventManager.listen(
|
|
154
|
-
this.adManager, shaka.ads.
|
|
158
|
+
this.adManager, shaka.ads.Utils.AD_STARTED, () => {
|
|
155
159
|
if (!this.shouldBeDisplayed_()) {
|
|
156
160
|
shaka.ui.Utils.setDisplay(this.container, false);
|
|
157
161
|
}
|
|
158
162
|
});
|
|
159
163
|
|
|
160
164
|
this.eventManager.listen(
|
|
161
|
-
this.adManager, shaka.ads.
|
|
165
|
+
this.adManager, shaka.ads.Utils.AD_STOPPED, () => {
|
|
162
166
|
if (this.shouldBeDisplayed_()) {
|
|
163
167
|
shaka.ui.Utils.setDisplay(this.container, true);
|
|
164
168
|
}
|
|
165
169
|
});
|
|
166
170
|
|
|
167
171
|
this.eventManager.listen(
|
|
168
|
-
this.adManager, shaka.ads.
|
|
172
|
+
this.adManager, shaka.ads.Utils.CUEPOINTS_CHANGED, (e) => {
|
|
169
173
|
this.adCuePoints_ = (e)['cuepoints'];
|
|
170
174
|
this.onAdCuePointsChanged_();
|
|
171
175
|
});
|
|
@@ -180,13 +184,10 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
|
|
|
180
184
|
}
|
|
181
185
|
this.lastThumbnail_ = null;
|
|
182
186
|
this.hideThumbnail_();
|
|
187
|
+
this.hideTime_();
|
|
183
188
|
});
|
|
184
189
|
|
|
185
190
|
this.eventManager.listen(this.bar, 'mousemove', (event) => {
|
|
186
|
-
if (!this.player.getImageTracks().length) {
|
|
187
|
-
this.hideThumbnail_();
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
191
|
const rect = this.bar.getBoundingClientRect();
|
|
191
192
|
const min = parseFloat(this.bar.min);
|
|
192
193
|
const max = parseFloat(this.bar.max);
|
|
@@ -196,11 +197,17 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
|
|
|
196
197
|
const scale = (max - min) / rect.width;
|
|
197
198
|
// Mouse position in units, which may be outside the allowed range.
|
|
198
199
|
const value = Math.round(min + scale * mousePosition);
|
|
199
|
-
|
|
200
|
+
if (!this.player.getImageTracks().length) {
|
|
201
|
+
this.hideThumbnail_();
|
|
202
|
+
this.showTime_(mousePosition, value);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
this.hideTime_();
|
|
200
206
|
this.showThumbnail_(mousePosition, value);
|
|
201
207
|
});
|
|
202
208
|
|
|
203
209
|
this.eventManager.listen(this.container, 'mouseleave', () => {
|
|
210
|
+
this.hideTime_();
|
|
204
211
|
this.hideThumbnailTimer_.stop();
|
|
205
212
|
this.hideThumbnailTimer_.tickAfter(/* seconds= */ 0.25);
|
|
206
213
|
});
|
|
@@ -375,13 +382,14 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
|
|
|
375
382
|
markAdBreaks_() {
|
|
376
383
|
if (!this.adCuePoints_.length) {
|
|
377
384
|
this.adMarkerContainer_.style.background = 'transparent';
|
|
385
|
+
this.adBreaksTimer_.stop();
|
|
378
386
|
return;
|
|
379
387
|
}
|
|
380
388
|
|
|
381
389
|
const seekRange = this.player.seekRange();
|
|
382
390
|
const seekRangeSize = seekRange.end - seekRange.start;
|
|
383
391
|
const gradient = ['to right'];
|
|
384
|
-
|
|
392
|
+
let pointsAsFractions = [];
|
|
385
393
|
const adBreakColor = this.config_.seekBarColors.adBreaks;
|
|
386
394
|
let postRollAd = false;
|
|
387
395
|
for (const point of this.adCuePoints_) {
|
|
@@ -413,6 +421,10 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
|
|
|
413
421
|
}
|
|
414
422
|
}
|
|
415
423
|
|
|
424
|
+
pointsAsFractions = pointsAsFractions.sort((a, b) => {
|
|
425
|
+
return a.start - b.start;
|
|
426
|
+
});
|
|
427
|
+
|
|
416
428
|
for (const point of pointsAsFractions) {
|
|
417
429
|
gradient.push(this.makeColor_('transparent', point.start));
|
|
418
430
|
gradient.push(this.makeColor_(adBreakColor, point.start));
|
|
@@ -445,16 +457,24 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
|
|
|
445
457
|
*/
|
|
446
458
|
onAdCuePointsChanged_() {
|
|
447
459
|
this.markAdBreaks_();
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
460
|
+
const action = () => {
|
|
461
|
+
const seekRange = this.player.seekRange();
|
|
462
|
+
const seekRangeSize = seekRange.end - seekRange.start;
|
|
463
|
+
const minSeekBarWindow =
|
|
464
|
+
shaka.ui.Constants.MIN_SEEK_WINDOW_TO_SHOW_SEEKBAR;
|
|
465
|
+
// Seek range keeps changing for live content and some of the known
|
|
466
|
+
// ad breaks might not be in the seek range now, but get into
|
|
467
|
+
// it later.
|
|
468
|
+
// If we have a LIVE seekable content, keep checking for ad breaks
|
|
469
|
+
// every second.
|
|
470
|
+
if (this.player.isLive() && seekRangeSize > minSeekBarWindow) {
|
|
471
|
+
this.adBreaksTimer_.tickEvery(/* seconds= */ 0.25);
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
if (this.player.isFullyLoaded()) {
|
|
475
|
+
action();
|
|
476
|
+
} else {
|
|
477
|
+
this.eventManager.listenOnce(this.player, 'loaded', action);
|
|
458
478
|
}
|
|
459
479
|
}
|
|
460
480
|
|
|
@@ -482,6 +502,33 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
|
|
|
482
502
|
this.bar.ariaLabel = this.localization.resolve(shaka.ui.Locales.Ids.SEEK);
|
|
483
503
|
}
|
|
484
504
|
|
|
505
|
+
/** @private */
|
|
506
|
+
showTime_(pixelPosition, value) {
|
|
507
|
+
const offsetTop = -10;
|
|
508
|
+
const width = this.timeContainer_.clientWidth;
|
|
509
|
+
const height = 20;
|
|
510
|
+
this.timeContainer_.style.width = 'auto';
|
|
511
|
+
this.timeContainer_.style.height = height + 'px';
|
|
512
|
+
this.timeContainer_.style.top = -(height - offsetTop) + 'px';
|
|
513
|
+
const leftPosition = Math.min(this.bar.offsetWidth - width,
|
|
514
|
+
Math.max(0, pixelPosition - (width / 2)));
|
|
515
|
+
this.timeContainer_.style.left = leftPosition + 'px';
|
|
516
|
+
this.timeContainer_.style.visibility = 'visible';
|
|
517
|
+
if (this.player.isLive()) {
|
|
518
|
+
const seekRange = this.player.seekRange();
|
|
519
|
+
const totalSeconds = seekRange.end - value;
|
|
520
|
+
if (totalSeconds < 1) {
|
|
521
|
+
this.timeContainer_.textContent =
|
|
522
|
+
this.localization.resolve(shaka.ui.Locales.Ids.LIVE);
|
|
523
|
+
} else {
|
|
524
|
+
this.timeContainer_.textContent =
|
|
525
|
+
'-' + this.timeFormatter_(totalSeconds);
|
|
526
|
+
}
|
|
527
|
+
} else {
|
|
528
|
+
this.timeContainer_.textContent = this.timeFormatter_(value);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
485
532
|
|
|
486
533
|
/**
|
|
487
534
|
* @private
|
|
@@ -657,6 +704,14 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
|
|
|
657
704
|
}
|
|
658
705
|
|
|
659
706
|
|
|
707
|
+
/**
|
|
708
|
+
* @private
|
|
709
|
+
*/
|
|
710
|
+
hideTime_() {
|
|
711
|
+
this.timeContainer_.style.visibility = 'hidden';
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
|
|
660
715
|
/**
|
|
661
716
|
* @param {number} totalSeconds
|
|
662
717
|
* @private
|
package/ui/skip_ad_button.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
goog.provide('shaka.ui.SkipAdButton');
|
|
9
9
|
|
|
10
10
|
goog.require('goog.asserts');
|
|
11
|
-
goog.require('shaka.ads.
|
|
11
|
+
goog.require('shaka.ads.Utils');
|
|
12
12
|
goog.require('shaka.ui.Element');
|
|
13
13
|
goog.require('shaka.ui.Locales');
|
|
14
14
|
goog.require('shaka.ui.Localization');
|
|
@@ -74,17 +74,17 @@ shaka.ui.SkipAdButton = class extends shaka.ui.Element {
|
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
this.eventManager.listen(
|
|
77
|
-
this.adManager, shaka.ads.
|
|
77
|
+
this.adManager, shaka.ads.Utils.AD_STARTED, () => {
|
|
78
78
|
this.onAdStarted_();
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
this.eventManager.listen(
|
|
82
|
-
this.adManager, shaka.ads.
|
|
82
|
+
this.adManager, shaka.ads.Utils.AD_SKIP_STATE_CHANGED, () => {
|
|
83
83
|
this.onSkipStateChanged_();
|
|
84
84
|
});
|
|
85
85
|
|
|
86
86
|
this.eventManager.listen(
|
|
87
|
-
this.adManager, shaka.ads.
|
|
87
|
+
this.adManager, shaka.ads.Utils.AD_STOPPED, () => {
|
|
88
88
|
this.reset_();
|
|
89
89
|
});
|
|
90
90
|
|
package/ui/statistics_button.js
CHANGED
|
@@ -117,7 +117,15 @@ shaka.ui.StatisticsButton = class extends shaka.ui.Element {
|
|
|
117
117
|
return this.currentStats_[name] + ' (stalls)';
|
|
118
118
|
};
|
|
119
119
|
|
|
120
|
-
const
|
|
120
|
+
const parseErrors = (name) => {
|
|
121
|
+
return this.currentStats_[name] + ' (errors)';
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const parsePeriods = (name) => {
|
|
125
|
+
return this.currentStats_[name] + ' (periods)';
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const parseBytes = (name) => {
|
|
121
129
|
const bytes = parseInt(this.currentStats_[name], 10);
|
|
122
130
|
if (bytes > 1e6) {
|
|
123
131
|
return (bytes / 1e6).toFixed(2) + 'MB';
|
|
@@ -149,7 +157,11 @@ shaka.ui.StatisticsButton = class extends shaka.ui.Element {
|
|
|
149
157
|
'droppedFrames': parseFrames,
|
|
150
158
|
'stallsDetected': parseStalls,
|
|
151
159
|
'gapsJumped': parseGaps,
|
|
152
|
-
'
|
|
160
|
+
'manifestSizeBytes': parseBytes,
|
|
161
|
+
'bytesDownloaded': parseBytes,
|
|
162
|
+
'nonFatalErrorCount': parseErrors,
|
|
163
|
+
'manifestPeriodCount': parsePeriods,
|
|
164
|
+
'manifestGapCount': parseGaps,
|
|
153
165
|
};
|
|
154
166
|
|
|
155
167
|
/** @private {shaka.util.Timer} */
|
package/ui/ui.js
CHANGED
|
@@ -192,6 +192,7 @@ shaka.ui.Overlay = class {
|
|
|
192
192
|
'playback_rate',
|
|
193
193
|
'recenter_vr',
|
|
194
194
|
'toggle_stereoscopic',
|
|
195
|
+
'save_video_frame',
|
|
195
196
|
],
|
|
196
197
|
statisticsList: [
|
|
197
198
|
'width',
|
|
@@ -211,12 +212,26 @@ shaka.ui.Overlay = class {
|
|
|
211
212
|
'pauseTime',
|
|
212
213
|
'playTime',
|
|
213
214
|
'completionPercent',
|
|
215
|
+
'manifestSizeBytes',
|
|
214
216
|
'bytesDownloaded',
|
|
217
|
+
'nonFatalErrorCount',
|
|
218
|
+
'manifestPeriodCount',
|
|
219
|
+
'manifestGapCount',
|
|
220
|
+
],
|
|
221
|
+
adStatisticsList: [
|
|
222
|
+
'loadTimes',
|
|
223
|
+
'averageLoadTime',
|
|
224
|
+
'started',
|
|
225
|
+
'playedCompletely',
|
|
226
|
+
'skipped',
|
|
227
|
+
'errors',
|
|
215
228
|
],
|
|
216
229
|
contextMenuElements: [
|
|
217
230
|
'loop',
|
|
218
231
|
'picture_in_picture',
|
|
232
|
+
'save_video_frame',
|
|
219
233
|
'statistics',
|
|
234
|
+
'ad_statistics',
|
|
220
235
|
],
|
|
221
236
|
playbackRates: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],
|
|
222
237
|
fastForwardRates: [2, 4, 8, 1],
|
package/ui/volume_bar.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
goog.provide('shaka.ui.VolumeBar');
|
|
9
9
|
|
|
10
10
|
goog.require('goog.asserts');
|
|
11
|
-
goog.require('shaka.ads.
|
|
11
|
+
goog.require('shaka.ads.Utils');
|
|
12
12
|
goog.require('shaka.ui.Controls');
|
|
13
13
|
goog.require('shaka.ui.Locales');
|
|
14
14
|
goog.require('shaka.ui.Localization');
|
|
@@ -41,15 +41,15 @@ shaka.ui.VolumeBar = class extends shaka.ui.RangeElement {
|
|
|
41
41
|
() => this.onPresentationVolumeChange_());
|
|
42
42
|
|
|
43
43
|
this.eventManager.listen(this.adManager,
|
|
44
|
-
shaka.ads.
|
|
44
|
+
shaka.ads.Utils.AD_VOLUME_CHANGED,
|
|
45
45
|
() => this.onAdVolumeChange_());
|
|
46
46
|
|
|
47
47
|
this.eventManager.listen(this.adManager,
|
|
48
|
-
shaka.ads.
|
|
48
|
+
shaka.ads.Utils.AD_MUTED,
|
|
49
49
|
() => this.onAdVolumeChange_());
|
|
50
50
|
|
|
51
51
|
this.eventManager.listen(this.adManager,
|
|
52
|
-
shaka.ads.
|
|
52
|
+
shaka.ads.Utils.AD_STOPPED,
|
|
53
53
|
() => this.onPresentationVolumeChange_());
|
|
54
54
|
|
|
55
55
|
this.eventManager.listen(this.localization,
|