shaka-player 4.6.8 → 4.6.10
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/CHANGELOG.md +26 -0
- package/dist/locales.js +31 -31
- package/dist/shaka-player.compiled.debug.js +92 -90
- package/dist/shaka-player.compiled.debug.map +3 -3
- package/dist/shaka-player.compiled.js +643 -641
- package/dist/shaka-player.compiled.map +3 -3
- package/dist/shaka-player.ui.debug.js +114 -114
- package/dist/shaka-player.ui.debug.map +2 -2
- package/dist/shaka-player.ui.js +609 -607
- package/dist/shaka-player.ui.map +3 -3
- package/docs/tutorials/index.json +1 -0
- package/docs/tutorials/text-displayer.md +15 -0
- package/lib/cast/cast_proxy.js +18 -0
- package/lib/hls/hls_utils.js +5 -5
- package/lib/media/media_source_engine.js +1 -1
- package/lib/media/play_rate_controller.js +1 -0
- package/lib/player.js +35 -3
- package/lib/text/ttml_text_parser.js +5 -0
- package/lib/util/language_utils.js +7 -8
- package/lib/util/platform.js +18 -0
- package/lib/util/stream_utils.js +14 -0
- package/package.json +1 -1
- package/test/media/media_source_engine_unit.js +2 -2
- package/test/player_unit.js +19 -4
- package/test/text/ttml_text_parser_unit.js +16 -16
- package/ui/controls.js +3 -0
- package/ui/pip_button.js +5 -21
- package/ui/playback_rate_selection.js +4 -0
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
{ "license-wrapping": { "title": "License Wrapping" } },
|
|
10
10
|
{ "ui": { "title": "UI Library" } },
|
|
11
11
|
{ "ui-customization": { "title": "Configuring the UI" } },
|
|
12
|
+
{ "text-displayer": { "title": "Configuring text displayer" } },
|
|
12
13
|
{ "errors": { "title": "Error Handling" } },
|
|
13
14
|
{ "a11y": { "title": "Creating accessible buttons" } },
|
|
14
15
|
{ "ad_monetization": { "title": "Serving ads with our IMA SDK integration" } },
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Configuring text displayer`
|
|
2
|
+
|
|
3
|
+
Shaka Player supports two types of Text Displayer.
|
|
4
|
+
1) Using the browser's native API, Shaka Player creates a textTrack along
|
|
5
|
+
with the AUDIO or VIDEO Element.
|
|
6
|
+
2) Rendering the subtitles in a container in the DOM.
|
|
7
|
+
3) Providing a custom text displayer factory would allow a developer to make
|
|
8
|
+
their own custom text displayer that fits neither category.
|
|
9
|
+
|
|
10
|
+
By default, if not configured otherwise, the player will use type 1.
|
|
11
|
+
To configure type 2, you have to call `setVideoContainer` function before
|
|
12
|
+
making `load` call in the player.
|
|
13
|
+
|
|
14
|
+
Note: The UI calls setVideoContainer for you if the video's controls are
|
|
15
|
+
disabled, so this isn't always necessary when using the UI.
|
package/lib/cast/cast_proxy.js
CHANGED
|
@@ -496,6 +496,16 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
|
|
496
496
|
startTime = this.sender_.get('video', 'currentTime');
|
|
497
497
|
}
|
|
498
498
|
|
|
499
|
+
let activeTextTrack;
|
|
500
|
+
const textTracks = this.sender_.get('player', 'getTextTracks')();
|
|
501
|
+
|
|
502
|
+
if (textTracks && textTracks.length) {
|
|
503
|
+
activeTextTrack = textTracks.find((t) => t.active);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const isTextTrackVisible =
|
|
507
|
+
this.sender_.get('player', 'isTextTrackVisible')();
|
|
508
|
+
|
|
499
509
|
// Now load the manifest, if present.
|
|
500
510
|
if (assetUri) {
|
|
501
511
|
// Don't autoplay the content until we finish setting up initial state.
|
|
@@ -527,6 +537,14 @@ shaka.cast.CastProxy = class extends shaka.util.FakeEventTarget {
|
|
|
527
537
|
/** @type {Object} */(this.localPlayer_)[setter](value);
|
|
528
538
|
}
|
|
529
539
|
|
|
540
|
+
this.localPlayer_.setTextTrackVisibility(isTextTrackVisible);
|
|
541
|
+
if (activeTextTrack) {
|
|
542
|
+
this.localPlayer_.selectTextLanguage(
|
|
543
|
+
activeTextTrack.language,
|
|
544
|
+
activeTextTrack.roles,
|
|
545
|
+
activeTextTrack.forced);
|
|
546
|
+
}
|
|
547
|
+
|
|
530
548
|
// Restore the original autoplay setting.
|
|
531
549
|
this.localVideo_.autoplay = autoplay;
|
|
532
550
|
if (assetUri) {
|
package/lib/hls/hls_utils.js
CHANGED
|
@@ -47,12 +47,12 @@ shaka.hls.Utils = class {
|
|
|
47
47
|
* @return {?shaka.hls.Tag}
|
|
48
48
|
*/
|
|
49
49
|
static getFirstTagWithName(tags, name) {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
for (const tag of tags) {
|
|
51
|
+
if (tag.name === name) {
|
|
52
|
+
return tag;
|
|
53
|
+
}
|
|
53
54
|
}
|
|
54
|
-
|
|
55
|
-
return tagsWithName[0];
|
|
55
|
+
return null;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
/**
|
|
@@ -1793,7 +1793,7 @@ shaka.media.MediaSourceEngine = class {
|
|
|
1793
1793
|
|
|
1794
1794
|
this.destroyer_.ensureNotDestroyed();
|
|
1795
1795
|
|
|
1796
|
-
this.eventManager_.listenOnce(this.video_, '
|
|
1796
|
+
this.eventManager_.listenOnce(this.video_, 'canplaythrough', () => {
|
|
1797
1797
|
this.destroyer_.ensureNotDestroyed();
|
|
1798
1798
|
|
|
1799
1799
|
this.video_.autoplay = previousAutoPlayState;
|
package/lib/player.js
CHANGED
|
@@ -549,6 +549,12 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
549
549
|
*/
|
|
550
550
|
this.loadEventManager_ = new shaka.util.EventManager();
|
|
551
551
|
|
|
552
|
+
/**
|
|
553
|
+
* For listeners scoped to the lifetime of the loaded content.
|
|
554
|
+
* @private {shaka.util.EventManager}
|
|
555
|
+
*/
|
|
556
|
+
this.trickPlayEventManager_ = new shaka.util.EventManager();
|
|
557
|
+
|
|
552
558
|
/** @private {shaka.net.NetworkingEngine} */
|
|
553
559
|
this.networkingEngine_ = null;
|
|
554
560
|
|
|
@@ -840,6 +846,10 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
840
846
|
this.loadEventManager_.release();
|
|
841
847
|
this.loadEventManager_ = null;
|
|
842
848
|
}
|
|
849
|
+
if (this.trickPlayEventManager_) {
|
|
850
|
+
this.trickPlayEventManager_.release();
|
|
851
|
+
this.trickPlayEventManager_ = null;
|
|
852
|
+
}
|
|
843
853
|
|
|
844
854
|
this.abrManagerFactory_ = null;
|
|
845
855
|
this.config_ = null;
|
|
@@ -1157,6 +1167,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
1157
1167
|
// element.
|
|
1158
1168
|
if (this.video_) {
|
|
1159
1169
|
this.loadEventManager_.removeAll();
|
|
1170
|
+
this.trickPlayEventManager_.removeAll();
|
|
1160
1171
|
}
|
|
1161
1172
|
|
|
1162
1173
|
// Stop the variant checker timer
|
|
@@ -3504,6 +3515,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3504
3515
|
shaka.log.alwaysWarn('A trick play rate of 0 is unsupported!');
|
|
3505
3516
|
return;
|
|
3506
3517
|
}
|
|
3518
|
+
this.trickPlayEventManager_.removeAll();
|
|
3507
3519
|
|
|
3508
3520
|
if (this.video_.paused) {
|
|
3509
3521
|
// Our fast forward is implemented with playbackRate and needs the video
|
|
@@ -3517,6 +3529,22 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3517
3529
|
this.abrManager_.playbackRateChanged(rate);
|
|
3518
3530
|
this.streamingEngine_.setTrickPlay(Math.abs(rate) > 1);
|
|
3519
3531
|
}
|
|
3532
|
+
if (this.isLive()) {
|
|
3533
|
+
this.trickPlayEventManager_.listen(this.video_, 'timeupdate', () => {
|
|
3534
|
+
const currentTime = this.video_.currentTime;
|
|
3535
|
+
const seekRange = this.seekRange();
|
|
3536
|
+
const safeSeekOffset = this.config_.streaming.safeSeekOffset;
|
|
3537
|
+
if (rate > 0) {
|
|
3538
|
+
if (currentTime >= seekRange.end) {
|
|
3539
|
+
this.cancelTrickPlay();
|
|
3540
|
+
}
|
|
3541
|
+
} else {
|
|
3542
|
+
if (currentTime <= (seekRange.start + safeSeekOffset)) {
|
|
3543
|
+
this.cancelTrickPlay();
|
|
3544
|
+
}
|
|
3545
|
+
}
|
|
3546
|
+
});
|
|
3547
|
+
}
|
|
3520
3548
|
}
|
|
3521
3549
|
|
|
3522
3550
|
/**
|
|
@@ -3536,6 +3564,7 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
3536
3564
|
this.abrManager_.playbackRateChanged(defaultPlaybackRate);
|
|
3537
3565
|
this.streamingEngine_.setTrickPlay(false);
|
|
3538
3566
|
}
|
|
3567
|
+
this.trickPlayEventManager_.removeAll();
|
|
3539
3568
|
}
|
|
3540
3569
|
|
|
3541
3570
|
/**
|
|
@@ -4507,13 +4536,16 @@ shaka.Player = class extends shaka.util.FakeEventTarget {
|
|
|
4507
4536
|
// variant yet because we set the load mode before we select the first
|
|
4508
4537
|
// variant to stream.
|
|
4509
4538
|
const variant = this.streamingEngine_.getCurrentVariant();
|
|
4539
|
+
const textStream = this.streamingEngine_.getCurrentTextStream();
|
|
4510
4540
|
|
|
4511
4541
|
if (variant) {
|
|
4512
4542
|
const rate = this.playRateController_ ?
|
|
4513
4543
|
this.playRateController_.getRealRate() : 1;
|
|
4514
4544
|
const variantBandwidth = rate * variant.bandwidth;
|
|
4515
|
-
|
|
4516
|
-
|
|
4545
|
+
let currentStreamBandwidth = variantBandwidth;
|
|
4546
|
+
if (textStream && textStream.bandwidth) {
|
|
4547
|
+
currentStreamBandwidth += (rate * textStream.bandwidth);
|
|
4548
|
+
}
|
|
4517
4549
|
this.stats_.setCurrentStreamBandwidth(currentStreamBandwidth);
|
|
4518
4550
|
}
|
|
4519
4551
|
|
|
@@ -6785,7 +6817,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
|
|
|
6785
6817
|
* @export
|
|
6786
6818
|
*/
|
|
6787
6819
|
// eslint-disable-next-line no-useless-concat
|
|
6788
|
-
shaka.Player.version = 'v4.6.
|
|
6820
|
+
shaka.Player.version = 'v4.6.10' + '-uncompiled'; // x-release-please-version
|
|
6789
6821
|
|
|
6790
6822
|
// Initialize the deprecation system using the version string we just set
|
|
6791
6823
|
// on the player.
|
|
@@ -491,6 +491,11 @@ shaka.text.TtmlTextParser = class {
|
|
|
491
491
|
region.viewportAnchorX = region.viewportAnchorX * 100 /
|
|
492
492
|
globalWidth;
|
|
493
493
|
}
|
|
494
|
+
} else if (!extent) {
|
|
495
|
+
region.width = 100 - region.viewportAnchorX;
|
|
496
|
+
region.widthUnits = shaka.text.CueRegion.units.PERCENTAGE;
|
|
497
|
+
region.height = 100 - region.viewportAnchorY;
|
|
498
|
+
region.heightUnits = shaka.text.CueRegion.units.PERCENTAGE;
|
|
494
499
|
}
|
|
495
500
|
|
|
496
501
|
region.viewportAnchorUnits = percentage || globalWidth != null ?
|
|
@@ -192,25 +192,24 @@ shaka.util.LanguageUtils = class {
|
|
|
192
192
|
const LanguageUtils = shaka.util.LanguageUtils;
|
|
193
193
|
|
|
194
194
|
const privateusePrefix = 'x-';
|
|
195
|
-
const
|
|
196
|
-
|
|
195
|
+
const [languageRegion = '', privateuseSuffix = ''] =
|
|
196
|
+
locale.split(`-${privateusePrefix}`);
|
|
197
|
+
const [languageCode = '', regionCode = ''] = languageRegion.split('-');
|
|
197
198
|
|
|
198
199
|
// We are only going to use the language, the region and the "privateuse" part (as per https://datatracker.ietf.org/doc/html/rfc5646).
|
|
199
200
|
// Anything else is thrown away.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const privateuse = components[1] ?
|
|
203
|
-
`${privateusePrefix}${components[1]}` : '';
|
|
201
|
+
const privateuse = privateuseSuffix ?
|
|
202
|
+
`${privateusePrefix}${privateuseSuffix}` : '';
|
|
204
203
|
|
|
205
204
|
// Convert the language to lower case. It is standard for the language code
|
|
206
205
|
// to be in lower case, but it will also make the map look-up easier.
|
|
207
|
-
language =
|
|
206
|
+
let language = languageCode.toLowerCase();
|
|
208
207
|
language = LanguageUtils.isoMap_.get(language) || language;
|
|
209
208
|
|
|
210
209
|
// Convert the region to upper case. It is standard for the region to be in
|
|
211
210
|
// upper case. If there is no upper code, then it will be an empty string
|
|
212
211
|
// and this will be a no-op.
|
|
213
|
-
region =
|
|
212
|
+
const region = regionCode.toUpperCase();
|
|
214
213
|
|
|
215
214
|
return `${region ? `${language}-${region}` : language}${
|
|
216
215
|
privateuse ? `-${privateuse}` : ''}`;
|
package/lib/util/platform.js
CHANGED
|
@@ -220,6 +220,15 @@ shaka.util.Platform = class {
|
|
|
220
220
|
!shaka.util.Platform.isLegacyEdge();
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Check if the current platform is Firefox.
|
|
225
|
+
*
|
|
226
|
+
* @return {boolean}
|
|
227
|
+
*/
|
|
228
|
+
static isFirefox() {
|
|
229
|
+
return shaka.util.Platform.userAgentContains_('Firefox');
|
|
230
|
+
}
|
|
231
|
+
|
|
223
232
|
/**
|
|
224
233
|
* Check if the current platform is from Apple.
|
|
225
234
|
*
|
|
@@ -422,6 +431,15 @@ shaka.util.Platform = class {
|
|
|
422
431
|
return navigator.platform.toLowerCase().includes('windows');
|
|
423
432
|
}
|
|
424
433
|
|
|
434
|
+
/**
|
|
435
|
+
* Return true if the platform is a Android, regardless of the browser.
|
|
436
|
+
*
|
|
437
|
+
* @return {boolean}
|
|
438
|
+
*/
|
|
439
|
+
static isAndroid() {
|
|
440
|
+
return shaka.util.Platform.userAgentContains_('Android');
|
|
441
|
+
}
|
|
442
|
+
|
|
425
443
|
/**
|
|
426
444
|
* Check if the user agent contains a key. This is the best way we know of
|
|
427
445
|
* right now to detect platforms. If there is a better way, please send a
|
package/lib/util/stream_utils.js
CHANGED
|
@@ -370,6 +370,9 @@ shaka.util.StreamUtils = class {
|
|
|
370
370
|
const StreamUtils = shaka.util.StreamUtils;
|
|
371
371
|
const isXboxOne = shaka.util.Platform.isXboxOne();
|
|
372
372
|
|
|
373
|
+
const isFirefoxAndroid = shaka.util.Platform.isFirefox() &&
|
|
374
|
+
shaka.util.Platform.isAndroid();
|
|
375
|
+
|
|
373
376
|
manifest.variants = manifest.variants.filter((variant) => {
|
|
374
377
|
// See: https://github.com/shaka-project/shaka-player/issues/3860
|
|
375
378
|
const video = variant.video;
|
|
@@ -425,6 +428,17 @@ shaka.util.StreamUtils = class {
|
|
|
425
428
|
|
|
426
429
|
const audio = variant.audio;
|
|
427
430
|
|
|
431
|
+
// See: https://github.com/shaka-project/shaka-player/issues/6111
|
|
432
|
+
// It seems that Firefox Android reports that it supports
|
|
433
|
+
// Opus + Widevine, but it is not actually supported.
|
|
434
|
+
// It makes sense to drop early.
|
|
435
|
+
if (isFirefoxAndroid && audio && audio.encrypted &&
|
|
436
|
+
audio.codecs.toLowerCase().includes('opus')) {
|
|
437
|
+
shaka.log.debug('Dropping variant - not compatible with platform',
|
|
438
|
+
StreamUtils.getVariantSummaryString_(variant));
|
|
439
|
+
return false;
|
|
440
|
+
}
|
|
441
|
+
|
|
428
442
|
if (audio) {
|
|
429
443
|
const codecs = StreamUtils.getCorrectAudioCodecs_(audio.codecs);
|
|
430
444
|
const fullType = MimeUtils.getFullOrConvertedType(
|
package/package.json
CHANGED
|
@@ -1246,7 +1246,7 @@ describe('MediaSourceEngine', () => {
|
|
|
1246
1246
|
const callback = addListenOnceSpy.calls.argsFor(0)[2];
|
|
1247
1247
|
callback();
|
|
1248
1248
|
expect(initSourceBufferSpy).toHaveBeenCalled();
|
|
1249
|
-
expect(addListenOnceSpy.calls.argsFor(0)[1]).toBe('
|
|
1249
|
+
expect(addListenOnceSpy.calls.argsFor(0)[1]).toBe('canplaythrough');
|
|
1250
1250
|
expect(video.autoplay).toBe(true);
|
|
1251
1251
|
expect(playSpy).not.toHaveBeenCalled();
|
|
1252
1252
|
} finally {
|
|
@@ -1313,7 +1313,7 @@ describe('MediaSourceEngine', () => {
|
|
|
1313
1313
|
const callback = addListenOnceSpy.calls.argsFor(0)[2];
|
|
1314
1314
|
callback();
|
|
1315
1315
|
expect(initSourceBufferSpy).toHaveBeenCalled();
|
|
1316
|
-
expect(addListenOnceSpy.calls.argsFor(0)[1]).toBe('
|
|
1316
|
+
expect(addListenOnceSpy.calls.argsFor(0)[1]).toBe('canplaythrough');
|
|
1317
1317
|
expect(video.autoplay).toBe(false);
|
|
1318
1318
|
expect(playSpy).toHaveBeenCalled();
|
|
1319
1319
|
} finally {
|
package/test/player_unit.js
CHANGED
|
@@ -2633,6 +2633,9 @@ describe('Player', () => {
|
|
|
2633
2633
|
variant.addExistingStream(1); // audio
|
|
2634
2634
|
variant.addExistingStream(2); // video
|
|
2635
2635
|
});
|
|
2636
|
+
manifest.addTextStream(4, (stream) => {
|
|
2637
|
+
stream.bandwidth = 10;
|
|
2638
|
+
});
|
|
2636
2639
|
});
|
|
2637
2640
|
|
|
2638
2641
|
await player.load(fakeManifestUri, 0, fakeMimeType);
|
|
@@ -2649,11 +2652,15 @@ describe('Player', () => {
|
|
|
2649
2652
|
});
|
|
2650
2653
|
|
|
2651
2654
|
it('tracks info about current stream', () => {
|
|
2652
|
-
|
|
2655
|
+
let stats = player.getStats();
|
|
2653
2656
|
// Should have chosen the first of each type of stream.
|
|
2654
2657
|
expect(stats.width).toBe(100);
|
|
2655
2658
|
expect(stats.height).toBe(200);
|
|
2656
2659
|
expect(stats.streamBandwidth).toBe(200);
|
|
2660
|
+
const textTracks = player.getTextTracks();
|
|
2661
|
+
player.selectTextTrack(textTracks[0]);
|
|
2662
|
+
stats = player.getStats();
|
|
2663
|
+
expect(stats.streamBandwidth).toBe(210);
|
|
2657
2664
|
});
|
|
2658
2665
|
|
|
2659
2666
|
it('tracks frame info', () => {
|
|
@@ -2768,7 +2775,7 @@ describe('Player', () => {
|
|
|
2768
2775
|
* @param {!Array.<shaka.extern.TrackChoice>} additional
|
|
2769
2776
|
*/
|
|
2770
2777
|
function checkHistory(additional) {
|
|
2771
|
-
const
|
|
2778
|
+
const variantPrefix = {
|
|
2772
2779
|
timestamp: jasmine.any(Number),
|
|
2773
2780
|
id: 0,
|
|
2774
2781
|
type: 'variant',
|
|
@@ -2776,10 +2783,18 @@ describe('Player', () => {
|
|
|
2776
2783
|
bandwidth: 200,
|
|
2777
2784
|
};
|
|
2778
2785
|
|
|
2786
|
+
const textPrefix = {
|
|
2787
|
+
timestamp: jasmine.any(Number),
|
|
2788
|
+
id: 4,
|
|
2789
|
+
type: 'text',
|
|
2790
|
+
fromAdaptation: true,
|
|
2791
|
+
bandwidth: null,
|
|
2792
|
+
};
|
|
2779
2793
|
const switchHistory = player.getStats().switchHistory;
|
|
2780
2794
|
|
|
2781
|
-
expect(switchHistory[0]).toEqual(
|
|
2782
|
-
expect(switchHistory
|
|
2795
|
+
expect(switchHistory[0]).toEqual(variantPrefix);
|
|
2796
|
+
expect(switchHistory[1]).toEqual(textPrefix);
|
|
2797
|
+
expect(switchHistory.slice(2)).toEqual(additional);
|
|
2783
2798
|
}
|
|
2784
2799
|
|
|
2785
2800
|
/**
|
|
@@ -638,8 +638,8 @@ describe('TtmlTextParser', () => {
|
|
|
638
638
|
id: 'subtitleArea',
|
|
639
639
|
viewportAnchorX: 50,
|
|
640
640
|
viewportAnchorY: 16,
|
|
641
|
-
width:
|
|
642
|
-
height:
|
|
641
|
+
width: 50,
|
|
642
|
+
height: 84,
|
|
643
643
|
},
|
|
644
644
|
startTime: 62.05,
|
|
645
645
|
endTime: 3723.2,
|
|
@@ -666,8 +666,8 @@ describe('TtmlTextParser', () => {
|
|
|
666
666
|
region: {
|
|
667
667
|
viewportAnchorX: 50,
|
|
668
668
|
viewportAnchorY: 16,
|
|
669
|
-
width:
|
|
670
|
-
height:
|
|
669
|
+
width: 50,
|
|
670
|
+
height: 84,
|
|
671
671
|
},
|
|
672
672
|
startTime: 62.05,
|
|
673
673
|
endTime: 3723.2,
|
|
@@ -694,8 +694,8 @@ describe('TtmlTextParser', () => {
|
|
|
694
694
|
region: {
|
|
695
695
|
viewportAnchorX: 50,
|
|
696
696
|
viewportAnchorY: 16,
|
|
697
|
-
width:
|
|
698
|
-
height:
|
|
697
|
+
width: 50,
|
|
698
|
+
height: 84,
|
|
699
699
|
},
|
|
700
700
|
startTime: 62.05,
|
|
701
701
|
endTime: 3723.2,
|
|
@@ -872,8 +872,8 @@ describe('TtmlTextParser', () => {
|
|
|
872
872
|
viewportAnchorY: 16,
|
|
873
873
|
regionAnchorX: 0,
|
|
874
874
|
regionAnchorY: 0,
|
|
875
|
-
width:
|
|
876
|
-
height:
|
|
875
|
+
width: 50,
|
|
876
|
+
height: 84,
|
|
877
877
|
heightUnits: CueRegion.units.PERCENTAGE,
|
|
878
878
|
widthUnits: CueRegion.units.PERCENTAGE,
|
|
879
879
|
viewportAnchorUnits: CueRegion.units.PERCENTAGE,
|
|
@@ -945,8 +945,8 @@ describe('TtmlTextParser', () => {
|
|
|
945
945
|
id: 'subtitleArea',
|
|
946
946
|
viewportAnchorX: 50,
|
|
947
947
|
viewportAnchorY: 16,
|
|
948
|
-
width:
|
|
949
|
-
height:
|
|
948
|
+
width: 50,
|
|
949
|
+
height: 84,
|
|
950
950
|
},
|
|
951
951
|
startTime: 62.05,
|
|
952
952
|
endTime: 3723.2,
|
|
@@ -973,8 +973,8 @@ describe('TtmlTextParser', () => {
|
|
|
973
973
|
region: {
|
|
974
974
|
viewportAnchorX: 50,
|
|
975
975
|
viewportAnchorY: 16,
|
|
976
|
-
width:
|
|
977
|
-
height:
|
|
976
|
+
width: 50,
|
|
977
|
+
height: 84,
|
|
978
978
|
},
|
|
979
979
|
startTime: 62.05,
|
|
980
980
|
endTime: 3723.2,
|
|
@@ -1001,8 +1001,8 @@ describe('TtmlTextParser', () => {
|
|
|
1001
1001
|
region: {
|
|
1002
1002
|
viewportAnchorX: 50,
|
|
1003
1003
|
viewportAnchorY: 16,
|
|
1004
|
-
width:
|
|
1005
|
-
height:
|
|
1004
|
+
width: 50,
|
|
1005
|
+
height: 84,
|
|
1006
1006
|
},
|
|
1007
1007
|
startTime: 62.05,
|
|
1008
1008
|
endTime: 3723.2,
|
|
@@ -1032,8 +1032,8 @@ describe('TtmlTextParser', () => {
|
|
|
1032
1032
|
id: 'subtitleArea',
|
|
1033
1033
|
viewportAnchorX: 12.2,
|
|
1034
1034
|
viewportAnchorY: 50.005,
|
|
1035
|
-
width:
|
|
1036
|
-
height:
|
|
1035
|
+
width: 87.8,
|
|
1036
|
+
height: 49.995,
|
|
1037
1037
|
},
|
|
1038
1038
|
startTime: 62.05,
|
|
1039
1039
|
endTime: 3723.2,
|
package/ui/controls.js
CHANGED
|
@@ -648,6 +648,9 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
|
|
|
648
648
|
* @export
|
|
649
649
|
*/
|
|
650
650
|
isPiPAllowed() {
|
|
651
|
+
if (this.castProxy_.isCasting()) {
|
|
652
|
+
return false;
|
|
653
|
+
}
|
|
651
654
|
if ('documentPictureInPicture' in window &&
|
|
652
655
|
this.config_.preferDocumentPictureInPicture) {
|
|
653
656
|
const video = /** @type {HTMLVideoElement} */(this.localVideo_);
|
package/ui/pip_button.js
CHANGED
|
@@ -98,8 +98,8 @@ shaka.ui.PipButton = class extends shaka.ui.Element {
|
|
|
98
98
|
this.onLeavePictureInPicture_();
|
|
99
99
|
});
|
|
100
100
|
|
|
101
|
-
this.eventManager.listen(this.controls, 'caststatuschanged', (
|
|
102
|
-
this.
|
|
101
|
+
this.eventManager.listen(this.controls, 'caststatuschanged', () => {
|
|
102
|
+
this.onTracksChanged_();
|
|
103
103
|
});
|
|
104
104
|
|
|
105
105
|
this.eventManager.listen(this.player, 'trackschanged', () => {
|
|
@@ -164,25 +164,6 @@ shaka.ui.PipButton = class extends shaka.ui.Element {
|
|
|
164
164
|
this.localization.resolve(currentPipState);
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
/**
|
|
168
|
-
* @param {Event} e
|
|
169
|
-
* @private
|
|
170
|
-
*/
|
|
171
|
-
onCastStatusChange_(e) {
|
|
172
|
-
const isCasting = e['newStatus'];
|
|
173
|
-
|
|
174
|
-
if (isCasting) {
|
|
175
|
-
// Picture-in-picture is not applicable if we're casting
|
|
176
|
-
if (this.controls.isPiPAllowed()) {
|
|
177
|
-
shaka.ui.Utils.setDisplay(this.pipButton_, false);
|
|
178
|
-
}
|
|
179
|
-
} else {
|
|
180
|
-
if (this.controls.isPiPAllowed()) {
|
|
181
|
-
shaka.ui.Utils.setDisplay(this.pipButton_, true);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
167
|
|
|
187
168
|
/**
|
|
188
169
|
* Display the picture-in-picture button only when the content contains video.
|
|
@@ -194,6 +175,9 @@ shaka.ui.PipButton = class extends shaka.ui.Element {
|
|
|
194
175
|
async onTracksChanged_() {
|
|
195
176
|
if (!this.controls.isPiPAllowed()) {
|
|
196
177
|
shaka.ui.Utils.setDisplay(this.pipButton_, false);
|
|
178
|
+
if (this.controls.isPiPEnabled()) {
|
|
179
|
+
await this.controls.togglePiP();
|
|
180
|
+
}
|
|
197
181
|
} else if (this.player && this.player.isAudioOnly()) {
|
|
198
182
|
shaka.ui.Utils.setDisplay(this.pipButton_, false);
|
|
199
183
|
if (this.controls.isPiPEnabled()) {
|
|
@@ -44,6 +44,10 @@ shaka.ui.PlaybackRateSelection = class extends shaka.ui.SettingsMenu {
|
|
|
44
44
|
this.updateLocalizedStrings_();
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
+
this.eventManager.listen(this.player, 'loaded', () => {
|
|
48
|
+
this.updatePlaybackRateSelection_(this.player.getPlaybackRate());
|
|
49
|
+
});
|
|
50
|
+
|
|
47
51
|
this.eventManager.listen(this.player, 'ratechange', () => {
|
|
48
52
|
this.updatePlaybackRateSelection_(this.player.getPlaybackRate());
|
|
49
53
|
});
|