shaka-player 4.11.13 → 4.12.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 +47 -0
- package/dist/deps.js +8 -8
- package/dist/locales.js +35 -35
- package/dist/shaka-player.compiled.d.ts +36 -13
- package/dist/shaka-player.compiled.debug.d.ts +36 -13
- package/dist/shaka-player.compiled.debug.externs.js +46 -11
- package/dist/shaka-player.compiled.debug.js +543 -517
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +46 -11
- package/dist/shaka-player.compiled.js +1348 -1331
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +37 -14
- package/dist/shaka-player.ui.debug.d.ts +37 -14
- package/dist/shaka-player.ui.debug.externs.js +46 -11
- package/dist/shaka-player.ui.debug.js +629 -598
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +46 -11
- package/dist/shaka-player.ui.js +1624 -1603
- package/dist/shaka-player.ui.map +4 -4
- package/externs/shaka/ads.js +9 -0
- package/externs/shaka/manifest.js +26 -1
- package/externs/shaka/offline.js +8 -2
- package/externs/shaka/player.js +80 -28
- package/externs/shaka/text.js +9 -0
- package/lib/ads/ad_manager.js +6 -0
- package/lib/ads/ad_utils.js +1 -0
- package/lib/ads/client_side_ad.js +8 -0
- package/lib/ads/interstitial_ad.js +25 -4
- package/lib/ads/interstitial_ad_manager.js +67 -8
- package/lib/ads/media_tailor_ad.js +8 -0
- package/lib/ads/server_side_ad.js +8 -0
- package/lib/dash/content_protection.js +31 -0
- package/lib/dash/dash_parser.js +22 -12
- package/lib/hls/hls_parser.js +63 -49
- package/lib/media/adaptation_set.js +11 -17
- package/lib/media/adaptation_set_criteria.js +4 -9
- package/lib/media/drm_engine.js +3 -1
- package/lib/media/manifest_filterer.js +2 -1
- package/lib/media/media_source_engine.js +286 -20
- package/lib/media/playhead.js +3 -1
- package/lib/media/preload_manager.js +10 -7
- package/lib/media/segment_prefetch.js +32 -13
- package/lib/media/segment_reference.js +3 -3
- package/lib/media/streaming_engine.js +87 -261
- package/lib/mss/mss_parser.js +1 -0
- package/lib/offline/download_info.js +5 -1
- package/lib/offline/indexeddb/storage_mechanism.js +4 -3
- package/lib/offline/indexeddb/v1_storage_cell.js +2 -0
- package/lib/offline/indexeddb/v2_storage_cell.js +2 -0
- package/lib/offline/manifest_converter.js +4 -0
- package/lib/offline/storage.js +277 -5
- package/lib/player.js +224 -78
- package/lib/text/simple_text_displayer.js +7 -0
- package/lib/text/stub_text_displayer.js +7 -0
- package/lib/text/ui_text_displayer.js +12 -0
- package/lib/util/dom_utils.js +14 -0
- package/lib/util/error.js +5 -0
- package/lib/util/periods.js +2 -0
- package/lib/util/platform.js +15 -0
- package/lib/util/player_configuration.js +11 -4
- package/lib/util/stream_utils.js +20 -1
- package/package.json +1 -1
- package/ui/ad_statistics_button.js +12 -0
- package/ui/controls.js +31 -7
- package/ui/externs/ui.js +8 -1
- package/ui/fullscreen_button.js +9 -0
- package/ui/locales/be.json +49 -0
- package/ui/mute_button.js +42 -11
- package/ui/skip_ad_button.js +16 -11
- package/ui/statistics_button.js +12 -0
- package/ui/ui.js +10 -5
package/lib/util/periods.js
CHANGED
|
@@ -1607,6 +1607,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
1607
1607
|
closedCaptions: null,
|
|
1608
1608
|
external: false,
|
|
1609
1609
|
fastSwitching: false,
|
|
1610
|
+
isAudioMuxedInVideo: false,
|
|
1610
1611
|
};
|
|
1611
1612
|
}
|
|
1612
1613
|
|
|
@@ -1649,6 +1650,7 @@ shaka.util.PeriodCombiner = class {
|
|
|
1649
1650
|
external: false,
|
|
1650
1651
|
fastSwitching: false,
|
|
1651
1652
|
fullMimeTypes: new Set(),
|
|
1653
|
+
isAudioMuxedInVideo: false,
|
|
1652
1654
|
};
|
|
1653
1655
|
}
|
|
1654
1656
|
|
package/lib/util/platform.js
CHANGED
|
@@ -489,6 +489,21 @@ shaka.util.Platform = class {
|
|
|
489
489
|
return navigator.platform.toLowerCase().includes('mac');
|
|
490
490
|
}
|
|
491
491
|
|
|
492
|
+
/**
|
|
493
|
+
* Return true if the platform is a VisionOS.
|
|
494
|
+
*
|
|
495
|
+
* @return {boolean}
|
|
496
|
+
*/
|
|
497
|
+
static isVisionOS() {
|
|
498
|
+
if (!shaka.util.Platform.isMac()) {
|
|
499
|
+
return false;
|
|
500
|
+
}
|
|
501
|
+
if (!('xr' in navigator)) {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
return true;
|
|
505
|
+
}
|
|
506
|
+
|
|
492
507
|
/**
|
|
493
508
|
* Return true if the platform is a Windows, regardless of the browser.
|
|
494
509
|
*
|
|
@@ -118,6 +118,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
118
118
|
disableVideo: false,
|
|
119
119
|
disableText: false,
|
|
120
120
|
disableThumbnails: false,
|
|
121
|
+
disableIFrames: false,
|
|
121
122
|
defaultPresentationDelay: 0,
|
|
122
123
|
segmentRelativeVttTiming: false,
|
|
123
124
|
raiseFatalErrorOnManifestUpdateRequestFailure: false,
|
|
@@ -125,7 +126,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
125
126
|
dash: {
|
|
126
127
|
clockSyncUri: '',
|
|
127
128
|
ignoreDrmInfo: false,
|
|
128
|
-
disableXlinkProcessing:
|
|
129
|
+
disableXlinkProcessing: true,
|
|
129
130
|
xlinkFailGracefully: false,
|
|
130
131
|
ignoreMinBufferTime: false,
|
|
131
132
|
autoCorrectDrift: true,
|
|
@@ -144,13 +145,14 @@ shaka.util.PlayerConfiguration = class {
|
|
|
144
145
|
'com.microsoft.playready',
|
|
145
146
|
'urn:uuid:79f0049a-4098-8642-ab92-e65be0885f95':
|
|
146
147
|
'com.microsoft.playready',
|
|
148
|
+
'urn:uuid:94ce86fb-07ff-4f43-adb8-93d2fa968ca2':
|
|
149
|
+
'com.apple.fps',
|
|
147
150
|
},
|
|
148
151
|
manifestPreprocessor:
|
|
149
152
|
shaka.util.PlayerConfiguration.defaultManifestPreprocessor,
|
|
150
153
|
manifestPreprocessorTXml:
|
|
151
154
|
shaka.util.PlayerConfiguration.defaultManifestPreprocessorTXml,
|
|
152
155
|
sequenceMode: false,
|
|
153
|
-
enableAudioGroups: false,
|
|
154
156
|
multiTypeVariantsAllowed,
|
|
155
157
|
useStreamOnceInPeriodFlattening: false,
|
|
156
158
|
updatePeriod: -1,
|
|
@@ -170,6 +172,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
170
172
|
ignoreManifestTimestampsInSegmentsMode: false,
|
|
171
173
|
disableCodecGuessing: false,
|
|
172
174
|
disableClosedCaptionsDetection: false,
|
|
175
|
+
updatePeriod: -1,
|
|
173
176
|
allowLowLatencyByteRangeOptimization: true,
|
|
174
177
|
},
|
|
175
178
|
mss: {
|
|
@@ -214,6 +217,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
214
217
|
// Offset by 5 seconds since Chromecast takes a few seconds to start
|
|
215
218
|
// playing after a seek, even when buffered.
|
|
216
219
|
safeSeekOffset: 5,
|
|
220
|
+
safeSeekEndOffset: 0,
|
|
217
221
|
stallEnabled: true,
|
|
218
222
|
stallThreshold: 1 /* seconds */,
|
|
219
223
|
stallSkip: 0.1 /* seconds */,
|
|
@@ -231,10 +235,8 @@ shaka.util.PlayerConfiguration = class {
|
|
|
231
235
|
minBytesForProgressEvents: minBytes,
|
|
232
236
|
preferNativeHls: false,
|
|
233
237
|
updateIntervalSeconds: 1,
|
|
234
|
-
dispatchAllEmsgBoxes: false,
|
|
235
238
|
observeQualityChanges: false,
|
|
236
239
|
maxDisabledTime: 30,
|
|
237
|
-
parsePrftBox: false,
|
|
238
240
|
// When low latency streaming is enabled, segmentPrefetchLimit will
|
|
239
241
|
// default to 2 if not specified.
|
|
240
242
|
segmentPrefetchLimit: 0,
|
|
@@ -399,6 +401,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
399
401
|
[cue, uri],
|
|
400
402
|
undefined);
|
|
401
403
|
},
|
|
404
|
+
dispatchAllEmsgBoxes: false,
|
|
402
405
|
};
|
|
403
406
|
|
|
404
407
|
let customPlayheadTracker = false;
|
|
@@ -414,6 +417,8 @@ shaka.util.PlayerConfiguration = class {
|
|
|
414
417
|
customPlayheadTracker,
|
|
415
418
|
skipPlayDetection,
|
|
416
419
|
supportsMultipleMediaElements,
|
|
420
|
+
disableHLSInterstitial: false,
|
|
421
|
+
disableDASHInterstitial: false,
|
|
417
422
|
};
|
|
418
423
|
|
|
419
424
|
const textDisplayer = {
|
|
@@ -443,6 +448,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
443
448
|
preferredVideoLabel: '',
|
|
444
449
|
preferredVideoCodecs: [],
|
|
445
450
|
preferredAudioCodecs: [],
|
|
451
|
+
preferredTextFormats: [],
|
|
446
452
|
preferForcedSubs: false,
|
|
447
453
|
preferSpatialAudio: false,
|
|
448
454
|
preferredDecodingAttributes: [],
|
|
@@ -468,6 +474,7 @@ shaka.util.PlayerConfiguration = class {
|
|
|
468
474
|
cmsd: cmsd,
|
|
469
475
|
lcevc: lcevc,
|
|
470
476
|
ads: ads,
|
|
477
|
+
ignoreHardwareResolution: false,
|
|
471
478
|
};
|
|
472
479
|
|
|
473
480
|
// Add this callback so that we can reference the preferred audio language
|
package/lib/util/stream_utils.js
CHANGED
|
@@ -33,12 +33,31 @@ shaka.util.StreamUtils = class {
|
|
|
33
33
|
* @param {!Array.<string>} preferredVideoCodecs
|
|
34
34
|
* @param {!Array.<string>} preferredAudioCodecs
|
|
35
35
|
* @param {!Array.<string>} preferredDecodingAttributes
|
|
36
|
+
* @param {!Array.<string>} preferredTextFormats
|
|
36
37
|
*/
|
|
37
38
|
static chooseCodecsAndFilterManifest(manifest, preferredVideoCodecs,
|
|
38
|
-
preferredAudioCodecs, preferredDecodingAttributes) {
|
|
39
|
+
preferredAudioCodecs, preferredDecodingAttributes, preferredTextFormats) {
|
|
39
40
|
const StreamUtils = shaka.util.StreamUtils;
|
|
40
41
|
const MimeUtils = shaka.util.MimeUtils;
|
|
41
42
|
|
|
43
|
+
if (preferredTextFormats.length) {
|
|
44
|
+
let subset = manifest.textStreams;
|
|
45
|
+
for (const textFormat of preferredTextFormats) {
|
|
46
|
+
const filtered = subset.filter((textStream) => {
|
|
47
|
+
if (textStream.codecs.startsWith(textFormat) ||
|
|
48
|
+
textStream.mimeType.startsWith(textFormat)) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
return false;
|
|
52
|
+
});
|
|
53
|
+
if (filtered.length) {
|
|
54
|
+
subset = filtered;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
manifest.textStreams = subset;
|
|
59
|
+
}
|
|
60
|
+
|
|
42
61
|
let variants = manifest.variants;
|
|
43
62
|
// To start, choose the codecs based on configured preferences if available.
|
|
44
63
|
if (preferredVideoCodecs.length || preferredAudioCodecs.length) {
|
package/package.json
CHANGED
|
@@ -189,6 +189,18 @@ shaka.ui.AdStatisticsButton = class extends shaka.ui.Element {
|
|
|
189
189
|
|
|
190
190
|
/** @private */
|
|
191
191
|
loadContainer_() {
|
|
192
|
+
const closeElement = shaka.util.Dom.createHTMLElement('div');
|
|
193
|
+
closeElement.classList.add('shaka-no-propagation');
|
|
194
|
+
closeElement.classList.add('shaka-statistics-close');
|
|
195
|
+
const icon = shaka.util.Dom.createHTMLElement('i');
|
|
196
|
+
icon.classList.add('material-icons-round');
|
|
197
|
+
icon.textContent =
|
|
198
|
+
shaka.ui.Enums.MaterialDesignIcons.CLOSE;
|
|
199
|
+
closeElement.appendChild(icon);
|
|
200
|
+
this.container_.appendChild(closeElement);
|
|
201
|
+
this.eventManager.listen(icon, 'click', () => {
|
|
202
|
+
this.onClick_();
|
|
203
|
+
});
|
|
192
204
|
for (const name of this.controls.getConfig().adStatisticsList) {
|
|
193
205
|
if (name in this.currentStats_) {
|
|
194
206
|
this.container_.appendChild(this.generateComponent_(name));
|
package/ui/controls.js
CHANGED
|
@@ -29,6 +29,7 @@ goog.require('shaka.util.EventManager');
|
|
|
29
29
|
goog.require('shaka.util.FakeEvent');
|
|
30
30
|
goog.require('shaka.util.FakeEventTarget');
|
|
31
31
|
goog.require('shaka.util.IDestroyable');
|
|
32
|
+
goog.require('shaka.util.Platform');
|
|
32
33
|
goog.require('shaka.util.Timer');
|
|
33
34
|
|
|
34
35
|
goog.requireType('shaka.Player');
|
|
@@ -203,6 +204,7 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
|
|
|
203
204
|
shaka.ui.Localization.LOCALE_CHANGED, (e) => {
|
|
204
205
|
const locale = e['locales'][0];
|
|
205
206
|
this.adManager_.setLocale(locale);
|
|
207
|
+
this.videoContainer_.setAttribute('lang', locale);
|
|
206
208
|
});
|
|
207
209
|
|
|
208
210
|
this.adManager_.initInterstitial(
|
|
@@ -604,16 +606,38 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
|
|
|
604
606
|
|
|
605
607
|
/**
|
|
606
608
|
* @return {boolean}
|
|
607
|
-
* @
|
|
609
|
+
* @private
|
|
608
610
|
*/
|
|
609
|
-
|
|
610
|
-
if (document.fullscreenEnabled) {
|
|
611
|
-
return
|
|
611
|
+
shouldUseDocumentFullscreen_() {
|
|
612
|
+
if (!document.fullscreenEnabled) {
|
|
613
|
+
return false;
|
|
612
614
|
}
|
|
615
|
+
// When the preferVideoFullScreenInVisionOS configuration value applies,
|
|
616
|
+
// we avoid using document fullscreen, even if it is available.
|
|
613
617
|
const video = /** @type {HTMLVideoElement} */(this.localVideo_);
|
|
614
618
|
if (video.webkitSupportsFullscreen) {
|
|
619
|
+
if (this.config_.preferVideoFullScreenInVisionOS &&
|
|
620
|
+
shaka.util.Platform.isVisionOS()) {
|
|
621
|
+
return false;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
return true;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* @return {boolean}
|
|
629
|
+
* @export
|
|
630
|
+
*/
|
|
631
|
+
isFullScreenSupported() {
|
|
632
|
+
if (this.shouldUseDocumentFullscreen_()) {
|
|
615
633
|
return true;
|
|
616
634
|
}
|
|
635
|
+
if (!this.ad_ || !this.ad_.isUsingAnotherMediaElement()) {
|
|
636
|
+
const video = /** @type {HTMLVideoElement} */(this.localVideo_);
|
|
637
|
+
if (video.webkitSupportsFullscreen) {
|
|
638
|
+
return true;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
617
641
|
return false;
|
|
618
642
|
}
|
|
619
643
|
|
|
@@ -622,7 +646,7 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
|
|
|
622
646
|
* @export
|
|
623
647
|
*/
|
|
624
648
|
isFullScreenEnabled() {
|
|
625
|
-
if (
|
|
649
|
+
if (this.shouldUseDocumentFullscreen_()) {
|
|
626
650
|
return !!document.fullscreenElement;
|
|
627
651
|
}
|
|
628
652
|
const video = /** @type {HTMLVideoElement} */(this.localVideo_);
|
|
@@ -635,7 +659,7 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
|
|
|
635
659
|
/** @private */
|
|
636
660
|
async enterFullScreen_() {
|
|
637
661
|
try {
|
|
638
|
-
if (
|
|
662
|
+
if (this.shouldUseDocumentFullscreen_()) {
|
|
639
663
|
if (document.pictureInPictureElement) {
|
|
640
664
|
await document.exitPictureInPicture();
|
|
641
665
|
}
|
|
@@ -666,7 +690,7 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
|
|
|
666
690
|
|
|
667
691
|
/** @private */
|
|
668
692
|
async exitFullScreen_() {
|
|
669
|
-
if (
|
|
693
|
+
if (this.shouldUseDocumentFullscreen_()) {
|
|
670
694
|
if (screen.orientation) {
|
|
671
695
|
screen.orientation.unlock();
|
|
672
696
|
}
|
package/ui/externs/ui.js
CHANGED
|
@@ -97,7 +97,8 @@ shaka.extern.UIVolumeBarColors;
|
|
|
97
97
|
* refreshTickInSeconds: number,
|
|
98
98
|
* displayInVrMode: boolean,
|
|
99
99
|
* defaultVrProjectionMode: string,
|
|
100
|
-
* setupMediaSession: boolean
|
|
100
|
+
* setupMediaSession: boolean,
|
|
101
|
+
* preferVideoFullScreenInVisionOS: boolean
|
|
101
102
|
* }}
|
|
102
103
|
*
|
|
103
104
|
* @property {!Array.<string>} controlPanelElements
|
|
@@ -254,6 +255,12 @@ shaka.extern.UIVolumeBarColors;
|
|
|
254
255
|
* the ID3 APIC and TIT2 as image and title in Media Session, and ID3 APIC
|
|
255
256
|
* will also be used to change video poster.
|
|
256
257
|
* Defaults to true.
|
|
258
|
+
* @property {boolean} preferVideoFullScreenInVisionOS
|
|
259
|
+
* If true, we will use the fullscreen API of the video element itself if it
|
|
260
|
+
* is available in Vision OS. This is useful to be able to access 3D
|
|
261
|
+
* experiences that are only allowed with the fullscreen of the video element
|
|
262
|
+
* itself.
|
|
263
|
+
* Defaults to false.
|
|
257
264
|
* @exportDoc
|
|
258
265
|
*/
|
|
259
266
|
shaka.extern.UIConfiguration;
|
package/ui/fullscreen_button.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
goog.provide('shaka.ui.FullscreenButton');
|
|
9
9
|
|
|
10
|
+
goog.require('shaka.ads.Utils');
|
|
10
11
|
goog.require('shaka.ui.Controls');
|
|
11
12
|
goog.require('shaka.ui.Element');
|
|
12
13
|
goog.require('shaka.ui.Enums');
|
|
@@ -69,6 +70,14 @@ shaka.ui.FullscreenButton = class extends shaka.ui.Element {
|
|
|
69
70
|
this.eventManager.listen(this.localVideo_, 'loadeddata', () => {
|
|
70
71
|
this.checkSupport_();
|
|
71
72
|
});
|
|
73
|
+
|
|
74
|
+
this.eventManager.listen(this.adManager, shaka.ads.Utils.AD_STARTED, () => {
|
|
75
|
+
this.checkSupport_();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
this.eventManager.listen(this.adManager, shaka.ads.Utils.AD_STOPPED, () => {
|
|
79
|
+
this.checkSupport_();
|
|
80
|
+
});
|
|
72
81
|
}
|
|
73
82
|
|
|
74
83
|
/**
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"AD_DURATION": "Працягласць рэкламы",
|
|
3
|
+
"AD_PROGRESS": "Рэклама [AD_ON] з [NUM_ADS]",
|
|
4
|
+
"AD_STATISTICS": "Статыстыка аб'яўленняў",
|
|
5
|
+
"AD_TIME": "Рэклама: [AD_TIME]",
|
|
6
|
+
"AIRPLAY": "AirPlay",
|
|
7
|
+
"AUTO_QUALITY": "Аўта",
|
|
8
|
+
"BACK": "Назад",
|
|
9
|
+
"CAPTIONS": "Субцітры",
|
|
10
|
+
"CAST": "Трансляваць...",
|
|
11
|
+
"CHAPTERS": "Раздзелы",
|
|
12
|
+
"DOWNLOAD_VIDEO_FRAME": "Захаваць кадр відэа",
|
|
13
|
+
"ENTER_LOOP_MODE": "Зацыкліць цяперашняе відэа",
|
|
14
|
+
"ENTER_PICTURE_IN_PICTURE": "Перайсці ў рэжым \"Выява ў выяве\"",
|
|
15
|
+
"EXIT_FULL_SCREEN": "Звычайны рэжым",
|
|
16
|
+
"EXIT_LOOP_MODE": "Адмяніць зацыкліванне цяперашняга відэа",
|
|
17
|
+
"EXIT_PICTURE_IN_PICTURE": "Выйсці з рэжыма \"Выява ў выяве\"",
|
|
18
|
+
"FAST_FORWARD": "Перамотка наперад",
|
|
19
|
+
"FULL_SCREEN": "Поўнаэкраны рэжым",
|
|
20
|
+
"LANGUAGE": "Мова",
|
|
21
|
+
"LIVE": "Ужывую",
|
|
22
|
+
"LOOP": "Зацыкліць",
|
|
23
|
+
"MORE_SETTINGS": "Дадатковыя налады",
|
|
24
|
+
"MULTIPLE_LANGUAGES": "Несколько моваў",
|
|
25
|
+
"MUTE": "Адключыць гук",
|
|
26
|
+
"NOT_APPLICABLE": "Не ўжываецца",
|
|
27
|
+
"OFF": "Выкл.",
|
|
28
|
+
"ON": "Укл.",
|
|
29
|
+
"PAUSE": "Паўза",
|
|
30
|
+
"PICTURE_IN_PICTURE": "Выява ў выяве",
|
|
31
|
+
"PLAY": "Прайграць",
|
|
32
|
+
"PLAYBACK_RATE": "Хуткасць прайгравання",
|
|
33
|
+
"QUALITY": "Якасць",
|
|
34
|
+
"RECENTER_VR": "Цэнтраваць зноў",
|
|
35
|
+
"REPLAY": "Паўтарыць",
|
|
36
|
+
"RESOLUTION": "Раздзяляльнасць",
|
|
37
|
+
"REWIND": "Перамотка назад",
|
|
38
|
+
"SEEK": "Перамотка",
|
|
39
|
+
"SKIP_AD": "Прапусціць",
|
|
40
|
+
"SKIP_TO_LIVE": "Прапусціць і перайсці да жывога эфіра",
|
|
41
|
+
"STATISTICS": "Статыстыка",
|
|
42
|
+
"SUBTITLE_FORCED": "Субцітры прымусова",
|
|
43
|
+
"SURROUND": "Аб'ёмны гук",
|
|
44
|
+
"TOGGLE_STEREOSCOPIC": "Уключыць або адключыць стэрэаскапічны рэжым",
|
|
45
|
+
"UNDETERMINED_LANGUAGE": "Не пазначана",
|
|
46
|
+
"UNMUTE": "Уключыць гук",
|
|
47
|
+
"UNRECOGNIZED_LANGUAGE": "Не распазнана",
|
|
48
|
+
"VOLUME": "Гучнасць"
|
|
49
|
+
}
|
package/ui/mute_button.js
CHANGED
|
@@ -8,11 +8,13 @@
|
|
|
8
8
|
goog.provide('shaka.ui.MuteButton');
|
|
9
9
|
|
|
10
10
|
goog.require('shaka.ads.Utils');
|
|
11
|
+
goog.require('shaka.ui.ContextMenu');
|
|
11
12
|
goog.require('shaka.ui.Controls');
|
|
12
13
|
goog.require('shaka.ui.Element');
|
|
13
14
|
goog.require('shaka.ui.Enums');
|
|
14
15
|
goog.require('shaka.ui.Locales');
|
|
15
16
|
goog.require('shaka.ui.Localization');
|
|
17
|
+
goog.require('shaka.ui.OverflowMenu');
|
|
16
18
|
goog.require('shaka.util.Dom');
|
|
17
19
|
|
|
18
20
|
|
|
@@ -29,23 +31,44 @@ shaka.ui.MuteButton = class extends shaka.ui.Element {
|
|
|
29
31
|
constructor(parent, controls) {
|
|
30
32
|
super(parent, controls);
|
|
31
33
|
|
|
34
|
+
const LocIds = shaka.ui.Locales.Ids;
|
|
32
35
|
/** @private {!HTMLButtonElement} */
|
|
33
36
|
this.button_ = shaka.util.Dom.createButton();
|
|
34
37
|
this.button_.classList.add('shaka-mute-button');
|
|
35
|
-
this.button_.classList.add('material-icons-round');
|
|
36
38
|
this.button_.classList.add('shaka-tooltip');
|
|
39
|
+
|
|
40
|
+
/** @private {!HTMLElement} */
|
|
41
|
+
this.icon_ = shaka.util.Dom.createHTMLElement('i');
|
|
42
|
+
this.icon_.classList.add('material-icons-round');
|
|
43
|
+
this.icon_.textContent = shaka.ui.Enums.MaterialDesignIcons.MUTE;
|
|
44
|
+
this.button_.appendChild(this.icon_);
|
|
45
|
+
|
|
46
|
+
const label = shaka.util.Dom.createHTMLElement('label');
|
|
47
|
+
label.classList.add('shaka-overflow-button-label');
|
|
48
|
+
label.classList.add('shaka-overflow-menu-only');
|
|
49
|
+
this.nameSpan_ = shaka.util.Dom.createHTMLElement('span');
|
|
50
|
+
this.nameSpan_.textContent = this.localization.resolve(LocIds.MUTE);
|
|
51
|
+
label.appendChild(this.nameSpan_);
|
|
52
|
+
|
|
53
|
+
/** @private {!HTMLElement} */
|
|
54
|
+
this.currentState_ = shaka.util.Dom.createHTMLElement('span');
|
|
55
|
+
this.currentState_.classList.add('shaka-current-selection-span');
|
|
56
|
+
label.appendChild(this.currentState_);
|
|
57
|
+
|
|
58
|
+
this.button_.appendChild(label);
|
|
59
|
+
|
|
37
60
|
this.parent.appendChild(this.button_);
|
|
38
|
-
this.
|
|
61
|
+
this.updateLocalizedStrings_();
|
|
39
62
|
this.updateIcon_();
|
|
40
63
|
|
|
41
64
|
this.eventManager.listen(
|
|
42
65
|
this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
|
|
43
|
-
this.
|
|
66
|
+
this.updateLocalizedStrings_();
|
|
44
67
|
});
|
|
45
68
|
|
|
46
69
|
this.eventManager.listen(
|
|
47
70
|
this.localization, shaka.ui.Localization.LOCALE_CHANGED, () => {
|
|
48
|
-
this.
|
|
71
|
+
this.updateLocalizedStrings_();
|
|
49
72
|
});
|
|
50
73
|
|
|
51
74
|
this.eventManager.listen(this.button_, 'click', () => {
|
|
@@ -57,19 +80,19 @@ shaka.ui.MuteButton = class extends shaka.ui.Element {
|
|
|
57
80
|
});
|
|
58
81
|
|
|
59
82
|
this.eventManager.listen(this.video, 'volumechange', () => {
|
|
60
|
-
this.
|
|
83
|
+
this.updateLocalizedStrings_();
|
|
61
84
|
this.updateIcon_();
|
|
62
85
|
});
|
|
63
86
|
|
|
64
87
|
this.eventManager.listen(this.adManager,
|
|
65
88
|
shaka.ads.Utils.AD_VOLUME_CHANGED, () => {
|
|
66
|
-
this.
|
|
89
|
+
this.updateLocalizedStrings_();
|
|
67
90
|
this.updateIcon_();
|
|
68
91
|
});
|
|
69
92
|
|
|
70
93
|
this.eventManager.listen(this.adManager,
|
|
71
94
|
shaka.ads.Utils.AD_MUTED, () => {
|
|
72
|
-
this.
|
|
95
|
+
this.updateLocalizedStrings_();
|
|
73
96
|
this.updateIcon_();
|
|
74
97
|
});
|
|
75
98
|
|
|
@@ -80,7 +103,7 @@ shaka.ui.MuteButton = class extends shaka.ui.Element {
|
|
|
80
103
|
// the label and icon code depends on this.ad being correctly
|
|
81
104
|
// updated at the time it runs.
|
|
82
105
|
this.ad = null;
|
|
83
|
-
this.
|
|
106
|
+
this.updateLocalizedStrings_();
|
|
84
107
|
this.updateIcon_();
|
|
85
108
|
});
|
|
86
109
|
}
|
|
@@ -88,7 +111,7 @@ shaka.ui.MuteButton = class extends shaka.ui.Element {
|
|
|
88
111
|
/**
|
|
89
112
|
* @private
|
|
90
113
|
*/
|
|
91
|
-
|
|
114
|
+
updateLocalizedStrings_() {
|
|
92
115
|
const LocIds = shaka.ui.Locales.Ids;
|
|
93
116
|
let label;
|
|
94
117
|
if (this.ad) {
|
|
@@ -98,6 +121,7 @@ shaka.ui.MuteButton = class extends shaka.ui.Element {
|
|
|
98
121
|
}
|
|
99
122
|
|
|
100
123
|
this.button_.ariaLabel = this.localization.resolve(label);
|
|
124
|
+
this.nameSpan_.textContent = this.localization.resolve(label);
|
|
101
125
|
}
|
|
102
126
|
|
|
103
127
|
/**
|
|
@@ -111,7 +135,7 @@ shaka.ui.MuteButton = class extends shaka.ui.Element {
|
|
|
111
135
|
} else {
|
|
112
136
|
icon = this.video.muted ? Icons.UNMUTE : Icons.MUTE;
|
|
113
137
|
}
|
|
114
|
-
this.
|
|
138
|
+
this.icon_.textContent = icon;
|
|
115
139
|
}
|
|
116
140
|
};
|
|
117
141
|
|
|
@@ -127,4 +151,11 @@ shaka.ui.MuteButton.Factory = class {
|
|
|
127
151
|
}
|
|
128
152
|
};
|
|
129
153
|
|
|
130
|
-
shaka.ui.
|
|
154
|
+
shaka.ui.OverflowMenu.registerElement(
|
|
155
|
+
'mute', new shaka.ui.MuteButton.Factory());
|
|
156
|
+
|
|
157
|
+
shaka.ui.Controls.registerElement(
|
|
158
|
+
'mute', new shaka.ui.MuteButton.Factory());
|
|
159
|
+
|
|
160
|
+
shaka.ui.ContextMenu.registerElement(
|
|
161
|
+
'mute', new shaka.ui.MuteButton.Factory());
|
package/ui/skip_ad_button.js
CHANGED
|
@@ -142,17 +142,20 @@ shaka.ui.SkipAdButton = class extends shaka.ui.Element {
|
|
|
142
142
|
onTimerTick_() {
|
|
143
143
|
goog.asserts.assert(this.ad != null,
|
|
144
144
|
'this.ad should exist at this point');
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
145
|
+
if (this.ad.isSkippable()) {
|
|
146
|
+
const secondsLeft = Math.round(this.ad.getTimeUntilSkippable());
|
|
147
|
+
if (secondsLeft > 0) {
|
|
148
|
+
this.counter_.textContent = secondsLeft;
|
|
149
|
+
} else {
|
|
150
|
+
// The ad should now be skippable. OnSkipStateChanged() is
|
|
151
|
+
// listening for a SKIP_STATE_CHANGED event and will take care
|
|
152
|
+
// of the button. Here we just stop the timer and hide the counter.
|
|
153
|
+
// NOTE: onSkipStateChanged_() also hides the counter.
|
|
154
|
+
this.timer_.stop();
|
|
155
|
+
shaka.ui.Utils.setDisplay(this.counter_, false);
|
|
156
|
+
}
|
|
149
157
|
} else {
|
|
150
|
-
|
|
151
|
-
// listening for a SKIP_STATE_CHANGED event and will take care
|
|
152
|
-
// of the button. Here we just stop the timer and hide the counter.
|
|
153
|
-
// NOTE: onSkipStateChanged_() also hides the counter.
|
|
154
|
-
this.timer_.stop();
|
|
155
|
-
shaka.ui.Utils.setDisplay(this.counter_, false);
|
|
158
|
+
this.reset_();
|
|
156
159
|
}
|
|
157
160
|
}
|
|
158
161
|
|
|
@@ -161,7 +164,9 @@ shaka.ui.SkipAdButton = class extends shaka.ui.Element {
|
|
|
161
164
|
*/
|
|
162
165
|
onSkipStateChanged_() {
|
|
163
166
|
// Double-check that the ad is now skippable
|
|
164
|
-
if (this.ad.
|
|
167
|
+
if (!this.ad.isSkippable()) {
|
|
168
|
+
this.reset_();
|
|
169
|
+
} else if (this.ad.canSkipNow()) {
|
|
165
170
|
this.button_.disabled = false;
|
|
166
171
|
this.timer_.stop();
|
|
167
172
|
shaka.ui.Utils.setDisplay(this.counter_, false);
|
package/ui/statistics_button.js
CHANGED
|
@@ -239,6 +239,18 @@ shaka.ui.StatisticsButton = class extends shaka.ui.Element {
|
|
|
239
239
|
|
|
240
240
|
/** @private */
|
|
241
241
|
loadContainer_() {
|
|
242
|
+
const closeElement = shaka.util.Dom.createHTMLElement('div');
|
|
243
|
+
closeElement.classList.add('shaka-no-propagation');
|
|
244
|
+
closeElement.classList.add('shaka-statistics-close');
|
|
245
|
+
const icon = shaka.util.Dom.createHTMLElement('i');
|
|
246
|
+
icon.classList.add('material-icons-round');
|
|
247
|
+
icon.textContent =
|
|
248
|
+
shaka.ui.Enums.MaterialDesignIcons.CLOSE;
|
|
249
|
+
closeElement.appendChild(icon);
|
|
250
|
+
this.container_.appendChild(closeElement);
|
|
251
|
+
this.eventManager.listen(icon, 'click', () => {
|
|
252
|
+
this.onClick_();
|
|
253
|
+
});
|
|
242
254
|
for (const name of this.controls.getConfig().statisticsList) {
|
|
243
255
|
if (name in this.currentStats_ && !this.skippedStats_.includes(name)) {
|
|
244
256
|
const element = this.generateComponent_(name);
|
package/ui/ui.js
CHANGED
|
@@ -273,6 +273,7 @@ shaka.ui.Overlay = class {
|
|
|
273
273
|
displayInVrMode: false,
|
|
274
274
|
defaultVrProjectionMode: 'equirectangular',
|
|
275
275
|
setupMediaSession: true,
|
|
276
|
+
preferVideoFullScreenInVisionOS: false,
|
|
276
277
|
};
|
|
277
278
|
|
|
278
279
|
// eslint-disable-next-line no-restricted-syntax
|
|
@@ -487,19 +488,23 @@ shaka.ui.Overlay = class {
|
|
|
487
488
|
// <source src='foo.m2u8'/>
|
|
488
489
|
// </video>
|
|
489
490
|
// It should not be specified on both.
|
|
491
|
+
const urls = [];
|
|
490
492
|
const src = video.getAttribute('src');
|
|
491
493
|
if (src) {
|
|
492
|
-
|
|
493
|
-
sourceElem.setAttribute('src', src);
|
|
494
|
-
video.appendChild(sourceElem);
|
|
494
|
+
urls.push(src);
|
|
495
495
|
video.removeAttribute('src');
|
|
496
496
|
}
|
|
497
497
|
|
|
498
|
+
for (const source of video.getElementsByTagName('source')) {
|
|
499
|
+
urls.push(/** @type {!HTMLSourceElement} */ (source).src);
|
|
500
|
+
video.removeChild(source);
|
|
501
|
+
}
|
|
502
|
+
|
|
498
503
|
await player.attach(shaka.util.Dom.asHTMLMediaElement(video));
|
|
499
504
|
|
|
500
|
-
for (const
|
|
505
|
+
for (const url of urls) {
|
|
501
506
|
try { // eslint-disable-next-line no-await-in-loop
|
|
502
|
-
await ui.getControls().getPlayer().load(
|
|
507
|
+
await ui.getControls().getPlayer().load(url);
|
|
503
508
|
break;
|
|
504
509
|
} catch (e) {
|
|
505
510
|
shaka.log.error('Error auto-loading asset', e);
|