shaka-player 4.6.8 → 4.6.9

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.
@@ -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.
@@ -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) {
@@ -47,12 +47,12 @@ shaka.hls.Utils = class {
47
47
  * @return {?shaka.hls.Tag}
48
48
  */
49
49
  static getFirstTagWithName(tags, name) {
50
- const tagsWithName = shaka.hls.Utils.filterTagsByName(tags, name);
51
- if (!tagsWithName.length) {
52
- return null;
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_, 'canplay', () => {
1796
+ this.eventManager_.listenOnce(this.video_, 'canplaythrough', () => {
1797
1797
  this.destroyer_.ensureNotDestroyed();
1798
1798
 
1799
1799
  this.video_.autoplay = previousAutoPlayState;
@@ -41,6 +41,7 @@ shaka.media.PlayRateController = class {
41
41
 
42
42
  /** @override */
43
43
  release() {
44
+ this.set(this.getDefaultRate());
44
45
  if (this.timer_) {
45
46
  this.timer_.stop();
46
47
  this.timer_ = null;
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
  /**
@@ -6785,7 +6814,7 @@ shaka.Player.TYPICAL_BUFFERING_THRESHOLD_ = 0.5;
6785
6814
  * @export
6786
6815
  */
6787
6816
  // eslint-disable-next-line no-useless-concat
6788
- shaka.Player.version = 'v4.6.8' + '-uncompiled'; // x-release-please-version
6817
+ shaka.Player.version = 'v4.6.9' + '-uncompiled'; // x-release-please-version
6789
6818
 
6790
6819
  // Initialize the deprecation system using the version string we just set
6791
6820
  // 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 components = locale.split(`-${privateusePrefix}`);
196
- const languageAndRegion = components[0].split('-');
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
- let language = languageAndRegion[0] || '';
201
- let region = languageAndRegion[1] || '';
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 = language.toLowerCase();
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 = region.toUpperCase();
212
+ const region = regionCode.toUpperCase();
214
213
 
215
214
  return `${region ? `${language}-${region}` : language}${
216
215
  privateuse ? `-${privateuse}` : ''}`;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "shaka-player",
3
3
  "description": "DASH/EME video player library",
4
- "version": "4.6.8",
4
+ "version": "4.6.9",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
@@ -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('canplay');
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('canplay');
1316
+ expect(addListenOnceSpy.calls.argsFor(0)[1]).toBe('canplaythrough');
1317
1317
  expect(video.autoplay).toBe(false);
1318
1318
  expect(playSpy).toHaveBeenCalled();
1319
1319
  } finally {
@@ -638,8 +638,8 @@ describe('TtmlTextParser', () => {
638
638
  id: 'subtitleArea',
639
639
  viewportAnchorX: 50,
640
640
  viewportAnchorY: 16,
641
- width: 100,
642
- height: 100,
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: 100,
670
- height: 100,
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: 100,
698
- height: 100,
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: 100,
876
- height: 100,
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: 100,
949
- height: 100,
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: 100,
977
- height: 100,
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: 100,
1005
- height: 100,
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: 100,
1036
- height: 100,
1035
+ width: 87.8,
1036
+ height: 49.995,
1037
1037
  },
1038
1038
  startTime: 62.05,
1039
1039
  endTime: 3723.2,
@@ -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
  });