shaka-player 4.7.13 → 4.7.15

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.
Files changed (59) hide show
  1. package/AUTHORS +1 -0
  2. package/CONTRIBUTORS +2 -0
  3. package/dist/cast-boot.js +37 -0
  4. package/dist/deps.js +5 -4
  5. package/dist/locales.js +31 -31
  6. package/dist/shaka-player.compiled.d.ts +37 -14
  7. package/dist/shaka-player.compiled.debug.d.ts +37 -14
  8. package/dist/shaka-player.compiled.debug.externs.js +14 -0
  9. package/dist/shaka-player.compiled.debug.js +360 -350
  10. package/dist/shaka-player.compiled.debug.map +4 -4
  11. package/dist/shaka-player.compiled.externs.js +14 -0
  12. package/dist/shaka-player.compiled.js +1107 -1105
  13. package/dist/shaka-player.compiled.map +4 -4
  14. package/dist/shaka-player.ui.d.ts +37 -14
  15. package/dist/shaka-player.ui.debug.d.ts +37 -14
  16. package/dist/shaka-player.ui.debug.externs.js +14 -0
  17. package/dist/shaka-player.ui.debug.js +280 -269
  18. package/dist/shaka-player.ui.debug.map +4 -4
  19. package/dist/shaka-player.ui.externs.js +14 -0
  20. package/dist/shaka-player.ui.js +1267 -1265
  21. package/dist/shaka-player.ui.map +4 -4
  22. package/externs/cast-namespace.js +14 -0
  23. package/externs/{chromecast.js → cast-sdk-v2.js} +0 -4
  24. package/externs/cast-sdk-v3.js +35 -0
  25. package/externs/ima.js +2 -0
  26. package/externs/mediatailor.js +0 -0
  27. package/externs/{cast.js → remote-playback.js} +2 -2
  28. package/externs/shaka/player.js +5 -2
  29. package/lib/ads/client_side_ad_manager.js +9 -5
  30. package/lib/cea/cea608_data_channel.js +9 -0
  31. package/lib/cea/cea_decoder.js +9 -2
  32. package/lib/dash/segment_template.js +30 -2
  33. package/lib/hls/hls_parser.js +19 -10
  34. package/lib/media/closed_caption_parser.js +16 -4
  35. package/lib/media/drm_engine.js +17 -3
  36. package/lib/media/gap_jumping_controller.js +9 -1
  37. package/lib/media/media_source_engine.js +20 -13
  38. package/lib/media/play_rate_controller.js +36 -8
  39. package/lib/media/playhead.js +3 -3
  40. package/lib/media/segment_index.js +10 -0
  41. package/lib/media/segment_reference.js +12 -0
  42. package/lib/media/stall_detector.js +3 -0
  43. package/lib/media/streaming_engine.js +8 -14
  44. package/lib/net/http_fetch_plugin.js +3 -1
  45. package/lib/net/http_xhr_plugin.js +6 -1
  46. package/lib/player.js +111 -53
  47. package/lib/polyfill/media_capabilities.js +7 -5
  48. package/lib/polyfill/patchedmediakeys_cert.js +62 -0
  49. package/lib/text/ui_text_displayer.js +10 -1
  50. package/lib/transmuxer/ts_transmuxer.js +6 -24
  51. package/lib/util/object_utils.js +1 -2
  52. package/lib/util/platform.js +100 -11
  53. package/lib/util/stream_utils.js +31 -14
  54. package/package.json +7 -2
  55. package/support.html +2 -0
  56. package/ui/audio_language_selection.js +4 -0
  57. package/ui/range_element.js +8 -2
  58. package/ui/resolution_selection.js +5 -0
  59. package/ui/text_selection.js +4 -0
@@ -107,6 +107,33 @@ shaka.util.Platform = class {
107
107
  return shaka.util.Platform.userAgentContains_('Tizen');
108
108
  }
109
109
 
110
+ /**
111
+ * Check if the current platform is a Tizen 6 TV.
112
+ *
113
+ * @return {boolean}
114
+ */
115
+ static isTizen6() {
116
+ return shaka.util.Platform.userAgentContains_('Tizen 6');
117
+ }
118
+
119
+ /**
120
+ * Check if the current platform is a Tizen 5.0 TV.
121
+ *
122
+ * @return {boolean}
123
+ */
124
+ static isTizen5_0() {
125
+ return shaka.util.Platform.userAgentContains_('Tizen 5.0');
126
+ }
127
+
128
+ /**
129
+ * Check if the current platform is a Tizen 5 TV.
130
+ *
131
+ * @return {boolean}
132
+ */
133
+ static isTizen5() {
134
+ return shaka.util.Platform.userAgentContains_('Tizen 5');
135
+ }
136
+
110
137
  /**
111
138
  * Check if the current platform is a Tizen 4 TV.
112
139
  *
@@ -149,10 +176,9 @@ shaka.util.Platform = class {
149
176
  * @return {boolean}
150
177
  */
151
178
  static isWebOS3() {
152
- // See: http://webostv.developer.lge.com/discover/specifications/web-engine/
153
- return shaka.util.Platform.userAgentContains_('Web0S') &&
154
- shaka.util.Platform.userAgentContains_(
155
- 'Chrome/38.0.2125.122 Safari/537.36');
179
+ // See: https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine#useragent-string
180
+ return shaka.util.Platform.isWebOS() &&
181
+ shaka.util.Platform.chromeVersion() === 38;
156
182
  }
157
183
 
158
184
  /**
@@ -161,18 +187,20 @@ shaka.util.Platform = class {
161
187
  * @return {boolean}
162
188
  */
163
189
  static isWebOS4() {
164
- // See: http://webostv.developer.lge.com/discover/specifications/web-engine/
165
- return !!navigator.userAgent.match(/webOS\/4/i);
190
+ // See: https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine#useragent-string
191
+ return shaka.util.Platform.isWebOS() &&
192
+ shaka.util.Platform.chromeVersion() === 53;
166
193
  }
167
194
 
168
195
  /**
169
- * Check if the current platform is a WebOS 4.
196
+ * Check if the current platform is a WebOS 5.
170
197
  *
171
198
  * @return {boolean}
172
199
  */
173
200
  static isWebOS5() {
174
- // See: http://webostv.developer.lge.com/discover/specifications/web-engine/
175
- return !!navigator.userAgent.match(/webOS\/5/i);
201
+ // See: https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine#useragent-string
202
+ return shaka.util.Platform.isWebOS() &&
203
+ shaka.util.Platform.chromeVersion() === 68;
176
204
  }
177
205
 
178
206
  /**
@@ -184,6 +212,28 @@ shaka.util.Platform = class {
184
212
  return shaka.util.Platform.userAgentContains_('CrKey');
185
213
  }
186
214
 
215
+ /**
216
+ * Check if the current platform is a Google Chromecast with Android
217
+ * (i.e. Chromecast with GoogleTV).
218
+ *
219
+ * @return {boolean}
220
+ */
221
+ static isAndroidCastDevice() {
222
+ const Platform = shaka.util.Platform;
223
+ return Platform.isChromecast() && Platform.isAndroid();
224
+ }
225
+
226
+ /**
227
+ * Check if the current platform is a Google Chromecast with Fuchsia
228
+ * (i.e. Google Nest Hub).
229
+ *
230
+ * @return {boolean}
231
+ */
232
+ static isFuchsiaCastDevice() {
233
+ const Platform = shaka.util.Platform;
234
+ return Platform.isChromecast() && Platform.isFuchsia();
235
+ }
236
+
187
237
  /**
188
238
  * Returns a major version number for Chrome, or Chromium-based browsers.
189
239
  *
@@ -414,6 +464,9 @@ shaka.util.Platform = class {
414
464
  return navigator.userAgentData.platform.toLowerCase() == 'macos';
415
465
  }
416
466
  // Fall back to the old API, with less strict matching.
467
+ if (!navigator.platform) {
468
+ return false;
469
+ }
417
470
  return navigator.platform.toLowerCase().includes('mac');
418
471
  }
419
472
 
@@ -428,6 +481,9 @@ shaka.util.Platform = class {
428
481
  return navigator.userAgentData.platform.toLowerCase() == 'windows';
429
482
  }
430
483
  // Fall back to the old API, with less strict matching.
484
+ if (!navigator.platform) {
485
+ return false;
486
+ }
431
487
  return navigator.platform.toLowerCase().includes('windows');
432
488
  }
433
489
 
@@ -440,6 +496,34 @@ shaka.util.Platform = class {
440
496
  return shaka.util.Platform.userAgentContains_('Android');
441
497
  }
442
498
 
499
+ /**
500
+ * Return true if the platform is a Fuchsia, regardless of the browser.
501
+ *
502
+ * @return {boolean}
503
+ */
504
+ static isFuchsia() {
505
+ return shaka.util.Platform.userAgentContains_('Fuchsia');
506
+ }
507
+
508
+ /**
509
+ * Return true if the platform is controlled by a remote control.
510
+ *
511
+ * @return {boolean}
512
+ */
513
+ static isSmartTV() {
514
+ const Platform = shaka.util.Platform;
515
+ if (Platform.isTizen() || Platform.isWebOS() ||
516
+ Platform.isXboxOne() || Platform.isPS4() ||
517
+ Platform.isPS5() || Platform.isAmazonFireTV() ||
518
+ Platform.isEOS() || Platform.isAPL() ||
519
+ Platform.isVirginMedia() || Platform.isOrange() ||
520
+ Platform.isWPE() || Platform.isChromecast() ||
521
+ Platform.isHisense()) {
522
+ return true;
523
+ }
524
+ return false;
525
+ }
526
+
443
527
  /**
444
528
  * Check if the user agent contains a key. This is the best way we know of
445
529
  * right now to detect platforms. If there is a better way, please send a
@@ -530,11 +614,16 @@ shaka.util.Platform = class {
530
614
  */
531
615
  static supportsSmoothCodecSwitching() {
532
616
  const Platform = shaka.util.Platform;
533
- if (Platform.isTizen2() || Platform.isTizen3() ||
534
- Platform.isTizen4() || Platform.isWebOS3() ||
617
+ if (Platform.isTizen2() || Platform.isTizen3() || Platform.isTizen4() ||
618
+ Platform.isTizen5() || Platform.isTizen6() || Platform.isWebOS3() ||
535
619
  Platform.isWebOS4() || Platform.isWebOS5()) {
536
620
  return false;
537
621
  }
622
+ // Older chromecasts without GoogleTV seem to not support SMOOTH properly.
623
+ if (Platform.isChromecast() && !Platform.isAndroidCastDevice() &&
624
+ !Platform.isFuchsiaCastDevice()) {
625
+ return false;
626
+ }
538
627
  // See: https://chromium-review.googlesource.com/c/chromium/src/+/4577759
539
628
  if (Platform.isWindows() && Platform.isEdge()) {
540
629
  return false;
@@ -419,7 +419,8 @@ shaka.util.StreamUtils = class {
419
419
  videoCodecs = StreamUtils.getCorrectVideoCodecs(videoCodecs);
420
420
  let audioCodecs = ManifestParserUtils.guessCodecs(
421
421
  ContentType.AUDIO, allCodecs);
422
- audioCodecs = StreamUtils.getCorrectAudioCodecs(audioCodecs);
422
+ audioCodecs = StreamUtils.getCorrectAudioCodecs(
423
+ audioCodecs, video.mimeType);
423
424
 
424
425
  const audioFullType = MimeUtils.getFullOrConvertedType(
425
426
  video.mimeType, audioCodecs, ContentType.AUDIO);
@@ -455,7 +456,8 @@ shaka.util.StreamUtils = class {
455
456
  }
456
457
 
457
458
  if (audio) {
458
- const codecs = StreamUtils.getCorrectAudioCodecs(audio.codecs);
459
+ const codecs = StreamUtils.getCorrectAudioCodecs(
460
+ audio.codecs, audio.mimeType);
459
461
  const fullType = MimeUtils.getFullOrConvertedType(
460
462
  audio.mimeType, codecs, ContentType.AUDIO);
461
463
 
@@ -536,7 +538,7 @@ shaka.util.StreamUtils = class {
536
538
  if (!a) {
537
539
  return b;
538
540
  } else {
539
- const res = shaka.util.ObjectUtils.cloneObject(a);
541
+ const res = shaka.util.ObjectUtils.shallowCloneObject(a);
540
542
  res.supported = a.supported && b.supported;
541
543
  res.powerEfficient = a.powerEfficient && b.powerEfficient;
542
544
  res.smooth = a.smooth && b.smooth;
@@ -744,17 +746,18 @@ shaka.util.StreamUtils = class {
744
746
  // We ignore the multiplexed audio when there is normal audio also.
745
747
  if (videoCodecs.includes(',') && !audio) {
746
748
  const allCodecs = videoCodecs.split(',');
749
+ const baseMimeType = MimeUtils.getBasicType(fullMimeType);
747
750
 
748
751
  videoCodecs = ManifestParserUtils.guessCodecs(
749
752
  ContentType.VIDEO, allCodecs);
750
753
 
751
754
  let audioCodecs = ManifestParserUtils.guessCodecs(
752
755
  ContentType.AUDIO, allCodecs);
753
- audioCodecs = StreamUtils.getCorrectAudioCodecs(audioCodecs);
756
+ audioCodecs = StreamUtils.getCorrectAudioCodecs(
757
+ audioCodecs, baseMimeType);
754
758
 
755
759
  const audioFullType = MimeUtils.getFullOrConvertedType(
756
- MimeUtils.getBasicType(fullMimeType), audioCodecs,
757
- ContentType.AUDIO);
760
+ baseMimeType, audioCodecs, ContentType.AUDIO);
758
761
 
759
762
  audioConfigs.push({
760
763
  contentType: audioFullType,
@@ -805,10 +808,11 @@ shaka.util.StreamUtils = class {
805
808
  }
806
809
  if (audio) {
807
810
  for (const fullMimeType of audio.fullMimeTypes) {
808
- const codecs = StreamUtils.getCorrectAudioCodecs(MimeUtils.getCodecs(
809
- fullMimeType));
811
+ const baseMimeType = MimeUtils.getBasicType(fullMimeType);
812
+ const codecs = StreamUtils.getCorrectAudioCodecs(
813
+ MimeUtils.getCodecs(fullMimeType), baseMimeType);
810
814
  const fullType = MimeUtils.getFullOrConvertedType(
811
- MimeUtils.getBasicType(fullMimeType), codecs, ContentType.AUDIO);
815
+ baseMimeType, codecs, ContentType.AUDIO);
812
816
 
813
817
  // AudioConfiguration
814
818
  audioConfigs.push({
@@ -965,21 +969,34 @@ shaka.util.StreamUtils = class {
965
969
  * Generates the correct audio codec for MediaDecodingConfiguration and
966
970
  * for MediaSource.isTypeSupported.
967
971
  * @param {string} codecs
972
+ * @param {string} mimeType
968
973
  * @return {string}
969
974
  */
970
- static getCorrectAudioCodecs(codecs) {
975
+ static getCorrectAudioCodecs(codecs, mimeType) {
971
976
  // According to RFC 6381 section 3.3, 'fLaC' is actually the correct
972
977
  // codec string. We still need to map it to 'flac', as some browsers
973
978
  // currently don't support 'fLaC', while 'flac' is supported by most
974
979
  // major browsers.
975
980
  // See https://bugs.chromium.org/p/chromium/issues/detail?id=1422728
976
- if (codecs === 'fLaC' && !shaka.util.Platform.isSafari()) {
977
- return 'flac';
981
+ if (codecs.toLowerCase() == 'flac') {
982
+ if (!shaka.util.Platform.isSafari()) {
983
+ return 'flac';
984
+ } else {
985
+ return 'fLaC';
986
+ }
978
987
  }
979
988
 
980
989
  // The same is true for 'Opus'.
981
- if (codecs === 'Opus') {
982
- return 'opus';
990
+ if (codecs.toLowerCase() === 'opus') {
991
+ if (!shaka.util.Platform.isSafari()) {
992
+ return 'opus';
993
+ } else {
994
+ if (shaka.util.MimeUtils.getContainerType(mimeType) == 'mp4') {
995
+ return 'Opus';
996
+ } else {
997
+ return 'opus';
998
+ }
999
+ }
983
1000
  }
984
1001
 
985
1002
  return codecs;
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.7.13",
4
+ "version": "4.7.15",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
@@ -39,7 +39,7 @@
39
39
  "jimp": "^0.16.1",
40
40
  "js-yaml": "^4.1.0",
41
41
  "jsdoc": "github:joeyparrish/jsdoc#2ca85bb6",
42
- "karma": "^6.3.16",
42
+ "karma": "github:joeyparrish/karma#shaka-fixes",
43
43
  "karma-coverage": "^2.2.0",
44
44
  "karma-jasmine": "^4.0.1",
45
45
  "karma-jasmine-ajax": "^0.1.13",
@@ -63,6 +63,11 @@
63
63
  "tippy.js": "^4.3.5",
64
64
  "which": "^2.0.2"
65
65
  },
66
+ "overrides": {
67
+ "karma": {
68
+ "ua-parser-js": "github:joeyparrish/ua-parser-js#preview"
69
+ }
70
+ },
66
71
  "shakaCustom": {
67
72
  "purposeOfDemoDeps": "These are the files from node_modules that need to be deployed with the demo app.",
68
73
  "demoDeps": [
package/support.html CHANGED
@@ -38,8 +38,10 @@
38
38
  }
39
39
 
40
40
  </style>
41
+ <script src="dist/cast-boot.js"></script>
41
42
  <script src="dist/shaka-player.compiled.js"></script>
42
43
  <script>
44
+
43
45
  function whenLoaded(fn) {
44
46
  // IE 9 fires DOMContentLoaded, and enters the "interactive"
45
47
  // readyState, before document.body has been initialized, so wait
@@ -46,6 +46,10 @@ shaka.ui.AudioLanguageSelection = class extends shaka.ui.SettingsMenu {
46
46
  });
47
47
 
48
48
 
49
+ this.eventManager.listen(this.player, 'loading', () => {
50
+ this.onTracksChanged_();
51
+ });
52
+
49
53
  this.eventManager.listen(this.player, 'trackschanged', () => {
50
54
  this.onTracksChanged_();
51
55
  });
@@ -70,11 +70,12 @@ shaka.ui.RangeElement = class extends shaka.ui.Element {
70
70
  this.container.appendChild(this.bar);
71
71
  this.parent.appendChild(this.container);
72
72
 
73
- this.eventManager.listen(this.bar, 'mousedown', () => {
73
+ this.eventManager.listen(this.bar, 'mousedown', (e) => {
74
74
  if (this.controls.isOpaque()) {
75
75
  this.isChanging_ = true;
76
76
  this.onChangeStart();
77
77
  }
78
+ e.stopPropagation();
78
79
  });
79
80
 
80
81
  this.eventManager.listen(this.bar, 'touchstart', (e) => {
@@ -83,6 +84,7 @@ shaka.ui.RangeElement = class extends shaka.ui.Element {
83
84
  this.setBarValueForTouch_(e);
84
85
  this.onChangeStart();
85
86
  }
87
+ e.stopPropagation();
86
88
  });
87
89
 
88
90
  this.eventManager.listen(this.bar, 'input', () => {
@@ -94,6 +96,7 @@ shaka.ui.RangeElement = class extends shaka.ui.Element {
94
96
  this.setBarValueForTouch_(e);
95
97
  this.onChange();
96
98
  }
99
+ e.stopPropagation();
97
100
  });
98
101
 
99
102
  this.eventManager.listen(this.bar, 'touchend', (e) => {
@@ -102,6 +105,7 @@ shaka.ui.RangeElement = class extends shaka.ui.Element {
102
105
  this.setBarValueForTouch_(e);
103
106
  this.onChangeEnd();
104
107
  }
108
+ e.stopPropagation();
105
109
  });
106
110
 
107
111
  this.eventManager.listen(this.bar, 'touchcancel', (e) => {
@@ -110,13 +114,15 @@ shaka.ui.RangeElement = class extends shaka.ui.Element {
110
114
  this.setBarValueForTouch_(e);
111
115
  this.onChangeEnd();
112
116
  }
117
+ e.stopPropagation();
113
118
  });
114
119
 
115
- this.eventManager.listen(this.bar, 'mouseup', () => {
120
+ this.eventManager.listen(this.bar, 'mouseup', (e) => {
116
121
  if (this.isChanging_) {
117
122
  this.isChanging_ = false;
118
123
  this.onChangeEnd();
119
124
  }
125
+ e.stopPropagation();
120
126
  });
121
127
 
122
128
  this.eventManager.listen(this.bar, 'blur', () => {
@@ -49,6 +49,10 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
49
49
  });
50
50
 
51
51
 
52
+ this.eventManager.listen(this.player, 'loading', () => {
53
+ this.updateResolutionSelection_();
54
+ });
55
+
52
56
  this.eventManager.listen(this.player, 'variantchanged', () => {
53
57
  this.updateResolutionSelection_();
54
58
  });
@@ -96,6 +100,7 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
96
100
  } else {
97
101
  otherIdx = tracks.findIndex((t) => {
98
102
  return t.height == track.height &&
103
+ t.videoBandwidth == track.videoBandwidth &&
99
104
  t.frameRate == track.frameRate &&
100
105
  t.hdr == track.hdr &&
101
106
  t.videoLayout == track.videoLayout;
@@ -64,6 +64,10 @@ shaka.ui.TextSelection = class extends shaka.ui.SettingsMenu {
64
64
  this.updateTextLanguages_();
65
65
  });
66
66
 
67
+ this.eventManager.listen(this.player, 'loading', () => {
68
+ this.onTracksChanged_();
69
+ });
70
+
67
71
  this.eventManager.listen(this.player, 'texttrackvisibility', () => {
68
72
  this.onCaptionStateChange_();
69
73
  this.updateTextLanguages_();