shaka-player 4.11.13 → 4.11.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 (52) hide show
  1. package/.csslintrc +2 -1
  2. package/.eslintrc.js +1 -0
  3. package/AUTHORS +1 -0
  4. package/CONTRIBUTORS +1 -0
  5. package/dist/controls.css +3 -3
  6. package/dist/controls.css.map +1 -1
  7. package/dist/deps.js +3 -2
  8. package/dist/locales.js +36 -36
  9. package/dist/shaka-player.compiled.d.ts +7 -7
  10. package/dist/shaka-player.compiled.debug.d.ts +7 -7
  11. package/dist/shaka-player.compiled.debug.js +326 -324
  12. package/dist/shaka-player.compiled.debug.map +4 -4
  13. package/dist/shaka-player.compiled.js +1317 -1313
  14. package/dist/shaka-player.compiled.map +4 -4
  15. package/dist/shaka-player.ui.d.ts +7 -7
  16. package/dist/shaka-player.ui.debug.d.ts +7 -7
  17. package/dist/shaka-player.ui.debug.js +328 -326
  18. package/dist/shaka-player.ui.debug.map +4 -4
  19. package/dist/shaka-player.ui.js +1520 -1516
  20. package/dist/shaka-player.ui.map +4 -4
  21. package/externs/managedmediasource.js +6 -0
  22. package/externs/shaka/abortable.js +36 -36
  23. package/lib/ads/interstitial_ad_manager.js +41 -15
  24. package/lib/cast/cast_utils.js +4 -2
  25. package/lib/hls/hls_parser.js +1 -1
  26. package/lib/media/drm_engine.js +2 -0
  27. package/lib/media/media_source_capabilities.js +6 -8
  28. package/lib/media/media_source_engine.js +61 -4
  29. package/lib/media/preload_manager.js +6 -1
  30. package/lib/media/segment_reference.js +1 -1
  31. package/lib/media/segment_utils.js +7 -3
  32. package/lib/media/streaming_engine.js +9 -11
  33. package/lib/net/http_xhr_plugin.js +1 -0
  34. package/lib/player.js +42 -36
  35. package/lib/polyfill/media_capabilities.js +46 -8
  36. package/lib/text/vtt_text_parser.js +9 -10
  37. package/lib/util/abortable_operation.js +11 -6
  38. package/lib/util/buffer_utils.js +10 -8
  39. package/lib/util/mime_utils.js +2 -0
  40. package/lib/util/number_utils.js +37 -0
  41. package/lib/util/object_utils.js +1 -1
  42. package/lib/util/platform.js +18 -7
  43. package/lib/util/uint8array_utils.js +3 -2
  44. package/package.json +3 -3
  45. package/ui/chapter_selection.js +6 -2
  46. package/ui/language_utils.js +3 -1
  47. package/ui/less/ad_controls.less +3 -3
  48. package/ui/less/buttons.less +4 -4
  49. package/ui/less/containers.less +7 -7
  50. package/ui/less/overflow_menu.less +4 -4
  51. package/ui/less/thumbnails.less +3 -3
  52. package/ui/less/tooltip.less +1 -1
@@ -327,18 +327,56 @@ shaka.polyfill.MediaCapabilities = class {
327
327
 
328
328
  let displayType = videoConfig.contentType;
329
329
  if (videoConfig.width && videoConfig.height) {
330
- displayType +=
331
- `; width=${videoConfig.width}; height=${videoConfig.height}`;
330
+ // All Chromecast can support 720p videos
331
+ if (videoConfig.width > 1280 || videoConfig.height > 720) {
332
+ displayType +=
333
+ `; width=${videoConfig.width}; height=${videoConfig.height}`;
334
+ }
332
335
  }
333
336
  if (videoConfig.framerate) {
334
- displayType += `; framerate=${videoConfig.framerate}`;
337
+ // All Chromecast can support a framerate of 24, 25 or 30.
338
+ const framerate = Math.round(videoConfig.framerate);
339
+ if (framerate < 24 || framerate > 30) {
340
+ displayType += `; framerate=${videoConfig.framerate}`;
341
+ }
335
342
  }
336
- if (videoConfig.transferFunction === 'pq') {
337
- // A "PQ" transfer function indicates this is an HDR-capable stream;
338
- // "smpte2084" is the published standard. We need to inform the platform
339
- // this query is specifically for HDR.
340
- displayType += '; eotf=smpte2084';
343
+
344
+ // Don't trust Closure types here. Although transferFunction is string or
345
+ // undefined, we don't want to count on the input type. A switch statement
346
+ // will, however, differentiate between null and undefined. So we default
347
+ // to a blank string.
348
+ const transferFunction = videoConfig.transferFunction || '';
349
+
350
+ // Based on internal sources. Googlers, see go/cast-hdr-queries for source.
351
+ switch (transferFunction) {
352
+ // The empty case falls through to SDR.
353
+ case '':
354
+ // These are the only 3 values defined by MCap as of November 2024.
355
+ case 'srgb':
356
+ // https://en.wikipedia.org/wiki/Standard-dynamic-range_video
357
+ // https://en.wikipedia.org/wiki/SRGB
358
+ // https://en.wikipedia.org/wiki/Rec._709
359
+ // This is SDR, standardized in BT 709.
360
+ // The platform recognizes "eotf=bt709", but we can also omit it.
361
+ break;
362
+
363
+ case 'pq':
364
+ // https://en.wikipedia.org/wiki/Perceptual_quantizer
365
+ // This HDR transfer function is standardized as SMPTE ST 2084.
366
+ displayType += '; eotf=smpte2084';
367
+ break;
368
+
369
+ case 'hlg':
370
+ // https://en.wikipedia.org/wiki/Hybrid_log%E2%80%93gamma
371
+ // This HDR transfer function is standardized as ARIB STD-B67.
372
+ displayType += '; eotf=arib-std-b67';
373
+ break;
374
+
375
+ default:
376
+ // An unrecognized transfer function. Reject this query.
377
+ return false;
341
378
  }
379
+
342
380
  let result = false;
343
381
  if (displayType in shaka.polyfill.MediaCapabilities
344
382
  .memoizedCanDisplayTypeRequests_) {
@@ -83,15 +83,14 @@ shaka.text.VttTextParser = class {
83
83
  // HLS content, which should use X-TIMESTAMP-MAP and periodStart instead.
84
84
  let offset = time.vttOffset;
85
85
 
86
- // Only use 'X-TIMESTAMP-MAP' with HLS. This overrides offset above.
87
- if (blocks[0].includes('X-TIMESTAMP-MAP') &&
88
- this.manifestType_ == shaka.media.ManifestParser.HLS) {
89
- if (this.sequenceMode_) {
90
- // Compute a different, rollover-based offset for sequence mode.
91
- offset = this.computeHlsSequenceModeOffset_(blocks[0], time);
92
- } else {
93
- // Calculate the offset from the segment startTime.
94
- offset = time.segmentStart;
86
+ if (this.manifestType_ == shaka.media.ManifestParser.HLS) {
87
+ // Only use 'X-TIMESTAMP-MAP' with HLS.
88
+ if (blocks[0].includes('X-TIMESTAMP-MAP')) {
89
+ offset = this.computeHlsOffset_(blocks[0], time);
90
+ } else if (time.periodStart && time.vttOffset == time.periodStart) {
91
+ // In the case where X-TIMESTAMP-MAP is not used and it is HLS, we
92
+ // should not use offset unless segment-relative times are used.
93
+ offset = 0;
95
94
  }
96
95
  }
97
96
 
@@ -129,7 +128,7 @@ shaka.text.VttTextParser = class {
129
128
  * @return {number}
130
129
  * @private
131
130
  */
132
- computeHlsSequenceModeOffset_(headerBlock, time) {
131
+ computeHlsOffset_(headerBlock, time) {
133
132
  // https://bit.ly/2K92l7y
134
133
  // The 'X-TIMESTAMP-MAP' header is used in HLS to align text with
135
134
  // the rest of the media.
@@ -39,8 +39,8 @@ shaka.util.AbortableOperation = class {
39
39
  /** @private {function():!Promise} */
40
40
  this.onAbort_ = onAbort;
41
41
 
42
- /** @private {boolean} */
43
- this.aborted_ = false;
42
+ /** @private {?Promise} */
43
+ this.abortPromise_ = null;
44
44
  }
45
45
 
46
46
  /**
@@ -48,7 +48,7 @@ shaka.util.AbortableOperation = class {
48
48
  * @export
49
49
  */
50
50
  get aborted() {
51
- return this.aborted_;
51
+ return this.abortPromise_ !== null;
52
52
  }
53
53
 
54
54
  /**
@@ -118,8 +118,10 @@ shaka.util.AbortableOperation = class {
118
118
  * @export
119
119
  */
120
120
  abort() {
121
- this.aborted_ = true;
122
- return this.onAbort_();
121
+ if (!this.abortPromise_) {
122
+ this.abortPromise_ = this.onAbort_();
123
+ }
124
+ return this.abortPromise_;
123
125
  }
124
126
 
125
127
  /**
@@ -164,6 +166,9 @@ shaka.util.AbortableOperation = class {
164
166
  */
165
167
  chain(onSuccess, onError) {
166
168
  const newPromise = new shaka.util.PublicPromise();
169
+ // Silence uncaught rejection errors, which may otherwise occur any place
170
+ // we don't explicitly handle aborted operations.
171
+ newPromise.catch(() => {});
167
172
  const abortError = shaka.util.AbortableOperation.abortError();
168
173
 
169
174
  // If called before "this" completes, just abort "this".
@@ -174,7 +179,7 @@ shaka.util.AbortableOperation = class {
174
179
 
175
180
  const makeCallback = (isSuccess) => {
176
181
  return (value) => {
177
- if (this.aborted_ && isSuccess) {
182
+ if (this.abortPromise_ && isSuccess) {
178
183
  // If "this" is not abortable(), or if abort() is called after "this"
179
184
  // is complete but before the next stage in the chain begins, we
180
185
  // should stop right away.
@@ -62,10 +62,10 @@ shaka.util.BufferUtils = class {
62
62
  * @private
63
63
  */
64
64
  static unsafeGetArrayBuffer_(view) {
65
- if (view instanceof ArrayBuffer) {
66
- return view;
65
+ if (!ArrayBuffer.isView(view)) {
66
+ return /** @type {!ArrayBuffer} */(view);
67
67
  } else {
68
- return view.buffer;
68
+ return /** @type {!ArrayBufferView} */(view).buffer;
69
69
  }
70
70
  }
71
71
 
@@ -79,17 +79,19 @@ shaka.util.BufferUtils = class {
79
79
  * @export
80
80
  */
81
81
  static toArrayBuffer(view) {
82
- if (view instanceof ArrayBuffer) {
83
- return view;
82
+ if (!ArrayBuffer.isView(view)) {
83
+ return /** @type {!ArrayBuffer} */(view);
84
84
  } else {
85
- if (view.byteOffset == 0 && view.byteLength == view.buffer.byteLength) {
85
+ const aView = /** @type {!ArrayBufferView} */(view);
86
+ if (aView.byteOffset == 0 &&
87
+ aView.byteLength == aView.buffer.byteLength) {
86
88
  // This is a TypedArray over the whole buffer.
87
- return view.buffer;
89
+ return aView.buffer;
88
90
  }
89
91
  // This is a "view" on the buffer. Create a new buffer that only contains
90
92
  // the data. Note that since this isn't an ArrayBuffer, the "new" call
91
93
  // will allocate a new buffer to hold the copy.
92
- return new Uint8Array(view).buffer;
94
+ return new Uint8Array(aView).buffer;
93
95
  }
94
96
  }
95
97
 
@@ -166,6 +166,8 @@ shaka.util.MimeUtils = class {
166
166
  return 'dtsx'; // DTS:X
167
167
  case base === 'mp4a' && profile === 'a9':
168
168
  return 'dtsc'; // DTS Digital Surround
169
+ case base === 'vp09':
170
+ return 'vp9';
169
171
  case base === 'avc1':
170
172
  case base === 'avc3':
171
173
  return 'avc'; // H264
@@ -0,0 +1,37 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.util.NumberUtils');
8
+
9
+
10
+ shaka.util.NumberUtils = class {
11
+ /**
12
+ * Compare two float numbers, taking a configurable tolerance margin into
13
+ * account.
14
+ *
15
+ * @param {number} a
16
+ * @param {number} b
17
+ * @param {number=} tolerance
18
+ * @return {boolean}
19
+ */
20
+ static isFloatEqual(a, b, tolerance = Number.EPSILON) {
21
+ if (a === b) {
22
+ return true;
23
+ }
24
+
25
+ const error = Math.abs(a - b);
26
+
27
+ if (error <= tolerance) {
28
+ return true;
29
+ }
30
+
31
+ if (tolerance !== Number.EPSILON) {
32
+ return Math.abs(error - tolerance) <= Number.EPSILON;
33
+ }
34
+
35
+ return false;
36
+ }
37
+ };
@@ -41,7 +41,7 @@ shaka.util.ObjectUtils = class {
41
41
 
42
42
  // This covers Uint8Array and friends, even without a TypedArray
43
43
  // base-class constructor.
44
- const isTypedArray = val.buffer instanceof ArrayBuffer;
44
+ const isTypedArray = ArrayBuffer.isView(val);
45
45
  if (isTypedArray) {
46
46
  return val;
47
47
  }
@@ -205,6 +205,17 @@ shaka.util.Platform = class {
205
205
  shaka.util.Platform.chromeVersion() === 68;
206
206
  }
207
207
 
208
+ /**
209
+ * Check if the current platform is a WebOS 6.
210
+ *
211
+ * @return {boolean}
212
+ */
213
+ static isWebOS6() {
214
+ // See: https://webostv.developer.lge.com/develop/specifications/web-api-and-web-engine#useragent-string
215
+ return shaka.util.Platform.isWebOS() &&
216
+ shaka.util.Platform.chromeVersion() === 79;
217
+ }
218
+
208
219
  /**
209
220
  * Check if the current platform is a Google Chromecast.
210
221
  *
@@ -627,19 +638,19 @@ shaka.util.Platform = class {
627
638
  /**
628
639
  * Returns if codec switching SMOOTH is known reliable device support.
629
640
  *
630
- * Some devices are known not to support `MediaSource.changeType`
641
+ * Some devices are known not to support <code>SourceBuffer.changeType</code>
631
642
  * well. These devices should use the reload strategy. If a device
632
- * reports that it supports `changeType` but support it unreliably
633
- * it should be added to this list.
643
+ * reports that it supports <code<changeType</code> but supports it unreliably
644
+ * it should be disallowed in this method.
634
645
  *
635
646
  * @return {boolean}
636
647
  */
637
648
  static supportsSmoothCodecSwitching() {
638
649
  const Platform = shaka.util.Platform;
639
- if (Platform.isTizen2() || Platform.isTizen3() || Platform.isTizen4() ||
640
- Platform.isTizen5() || Platform.isTizen6() || Platform.isWebOS3() ||
641
- Platform.isWebOS4() || Platform.isWebOS5() || Platform.isPS4() ||
642
- Platform.isPS5()) {
650
+ // All Tizen versions (up to Tizen 8) do not support SMOOTH so far.
651
+ // webOS seems to support SMOOTH from webOS 22.
652
+ if (Platform.isTizen() || Platform.isPS4() || Platform.isPS5() ||
653
+ Platform.isWebOS6()) {
643
654
  return false;
644
655
  }
645
656
  // Older chromecasts without GoogleTV seem to not support SMOOTH properly.
@@ -119,8 +119,9 @@ shaka.util.Uint8ArrayUtils = class {
119
119
 
120
120
  for (let i = 0; i < varArgs.length; ++i) {
121
121
  const value = varArgs[i];
122
- if (value instanceof Uint8Array) {
123
- result.set(value, offset);
122
+ if (ArrayBuffer.isView(value) &&
123
+ /** @type {TypedArray} */ (value).BYTES_PER_ELEMENT === 1) {
124
+ result.set(/** @type {!Uint8Array} */(value), offset);
124
125
  } else {
125
126
  result.set(BufferUtils.toUint8(value), offset);
126
127
  }
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.11.13",
4
+ "version": "4.11.15",
5
5
  "homepage": "https://github.com/shaka-project/shaka-player",
6
6
  "author": "Google",
7
7
  "maintainers": [
@@ -26,7 +26,7 @@
26
26
  "core-js": "^3.21.1",
27
27
  "dialog-polyfill": "^0.5.6",
28
28
  "es6-promise-polyfill": "^1.2.0",
29
- "eslint": "^8.9.0",
29
+ "eslint": "^8.57.1",
30
30
  "eslint-config-google": "^0.14.0",
31
31
  "eslint-plugin-shaka-rules": "file:./build/eslint-plugin-shaka-rules",
32
32
  "esprima": "^4.0.1",
@@ -105,7 +105,7 @@
105
105
  "prepublishOnly": "python build/checkversion.py && python build/all.py --force"
106
106
  },
107
107
  "dependencies": {
108
- "eme-encryption-scheme-polyfill": "^2.1.5"
108
+ "eme-encryption-scheme-polyfill": "^2.1.6"
109
109
  },
110
110
  "clean-package": {
111
111
  "remove": [
@@ -119,14 +119,18 @@ shaka.ui.ChapterSelection = class extends shaka.ui.SettingsMenu {
119
119
  const currentLocales = this.localization.getCurrentLocales();
120
120
  for (const locale of Array.from(currentLocales)) {
121
121
  nextLanguage = locale;
122
- nextChapters = this.player.getChapters(nextLanguage);
122
+ // If player is a proxy, and the cast receiver doesn't support this
123
+ // method, you get back undefined.
124
+ nextChapters = this.player.getChapters(nextLanguage) || [];
123
125
  if (nextChapters.length) {
124
126
  break;
125
127
  }
126
128
  }
127
129
  if (!nextChapters.length) {
128
130
  nextLanguage = 'und';
129
- nextChapters = this.player.getChapters(nextLanguage);
131
+ // If player is a proxy, and the cast receiver doesn't support this
132
+ // method, you get back undefined.
133
+ nextChapters = this.player.getChapters(nextLanguage) || [];
130
134
  }
131
135
 
132
136
  const languageChanged = nextLanguage !== this.chaptersLanguage_;
@@ -14,6 +14,7 @@ goog.require('shaka.ui.Overlay.TrackLabelFormat');
14
14
  goog.require('shaka.ui.Utils');
15
15
  goog.require('shaka.util.Dom');
16
16
  goog.require('shaka.util.LanguageUtils');
17
+ goog.require('shaka.util.MimeUtils');
17
18
  goog.requireType('shaka.ui.Localization');
18
19
 
19
20
 
@@ -48,7 +49,8 @@ shaka.ui.LanguageUtils = class {
48
49
  if (!codecsByLanguage.has(track.language)) {
49
50
  codecsByLanguage.set(track.language, new Set());
50
51
  }
51
- codecsByLanguage.get(track.language).add(track.audioCodec);
52
+ codecsByLanguage.get(track.language).add(
53
+ shaka.util.MimeUtils.getNormalizedCodec(track.audioCodec));
52
54
  }
53
55
  const hasDifferentAudioCodecs = (language) =>
54
56
  codecsByLanguage.has(language) && codecsByLanguage.get(language).size > 1;
@@ -95,11 +95,11 @@
95
95
 
96
96
  .shaka-skip-ad-button {
97
97
  padding: 5px 15px;
98
- background: rgba(0 0 0 / 70%);
98
+ background: rgba(0, 0, 0, 70%);
99
99
  border: none;
100
100
 
101
101
  &:disabled {
102
- background: rgba(0 0 0 / 30%);
102
+ background: rgba(0, 0, 0, 30%);
103
103
  }
104
104
 
105
105
  cursor: pointer;
@@ -107,6 +107,6 @@
107
107
 
108
108
  .shaka-skip-ad-counter {
109
109
  padding: 5px;
110
- background: rgba(0 0 0 / 70%);
110
+ background: rgba(0, 0, 0, 70%);
111
111
  margin: 0;
112
112
  }
@@ -38,7 +38,7 @@
38
38
  border-radius: 50%;
39
39
 
40
40
  /* A small drop shadow below the button. */
41
- box-shadow: rgba(0 0 0 / 10%) 0 0 20px 0;
41
+ box-shadow: rgba(0, 0, 0, 10%) 0 0 20px 0;
42
42
 
43
43
  /* No border. */
44
44
  border: none;
@@ -51,7 +51,7 @@
51
51
  background-position: center center;
52
52
 
53
53
  /* A background color behind the play arrow. */
54
- background-color: rgba(255 255 255 / 90%);
54
+ background-color: rgba(255, 255, 255, 90%);
55
55
 
56
56
  .show-when-controls-shown();
57
57
 
@@ -127,10 +127,10 @@
127
127
  border: none;
128
128
 
129
129
  /* Setting text color to white */
130
- color: rgb(255 255 255);
130
+ color: rgb(255, 255, 255);
131
131
 
132
132
  /* Setting background color to black so white text can be seen clearly */
133
- background-color: rgb(0 0 0 / 50%);
133
+ background-color: rgb(0, 0, 0, 50%);
134
134
 
135
135
  cursor: default;
136
136
  font-size: 20px;
@@ -222,7 +222,7 @@
222
222
  min-width: 300px;
223
223
 
224
224
  color: white;
225
- background-color: rgba(35 35 35 / 90%);
225
+ background-color: rgba(35, 35, 35, 90%);
226
226
 
227
227
  font-size: 14px;
228
228
 
@@ -243,7 +243,7 @@
243
243
  }
244
244
 
245
245
  span {
246
- color: rgb(150 150 150);
246
+ color: rgb(150, 150, 150);
247
247
  }
248
248
  }
249
249
 
@@ -254,7 +254,7 @@
254
254
  min-width: 150px;
255
255
 
256
256
  color: white;
257
- background-color: rgba(35 35 35 / 90%);
257
+ background-color: rgba(35, 35, 35, 90%);
258
258
 
259
259
  font-size: 14px;
260
260
 
@@ -275,12 +275,12 @@
275
275
  }
276
276
 
277
277
  span {
278
- color: rgb(150 150 150);
278
+ color: rgb(150, 150, 150);
279
279
  }
280
280
  }
281
281
 
282
282
  .shaka-context-menu {
283
- background-color: rgba(35 35 35 / 90%);
283
+ background-color: rgba(35, 35, 35, 90%);
284
284
 
285
285
  border-radius: 2px;
286
286
 
@@ -300,7 +300,7 @@
300
300
  cursor: pointer;
301
301
 
302
302
  &:hover {
303
- background-color: rgba(50 50 50 / 90%);
303
+ background-color: rgba(50, 50, 50, 90%);
304
304
  }
305
305
  }
306
306
 
@@ -406,7 +406,7 @@
406
406
 
407
407
  /* Add a bit of a white shadow to keep our black spinner visible
408
408
  on a black background. */
409
- filter: drop-shadow(0 0 2px rgba(255 255 255 / 50%));
409
+ filter: drop-shadow(0 0 2px rgba(255, 255, 255, 50%));
410
410
  }
411
411
 
412
412
  .shaka-hidden-fast-forward-container,
@@ -18,7 +18,7 @@
18
18
 
19
19
  /* Styles for the menu itself. */
20
20
  background: white;
21
- box-shadow: 0 1px 9px 0 rgba(0 0 0 / 40%);
21
+ box-shadow: 0 1px 9px 0 rgba(0, 0, 0, 40%);
22
22
  border-radius: 2px;
23
23
  max-height: 250px;
24
24
  min-width: 180px;
@@ -53,7 +53,7 @@
53
53
 
54
54
  /* When hovered, the button's background is highlighted. */
55
55
  &:hover {
56
- background: rgb(224 224 224);
56
+ background: rgb(224, 224, 224);
57
57
  }
58
58
 
59
59
  /* The button is clickable, showing cursor pointer */
@@ -65,7 +65,7 @@
65
65
  }
66
66
 
67
67
  .shaka-keyboard-navigation &:focus {
68
- background: rgb(224 224 224);
68
+ background: rgb(224, 224, 224);
69
69
  }
70
70
  }
71
71
 
@@ -110,7 +110,7 @@
110
110
  * language, the currently-selected resolution, etc. */
111
111
  .shaka-current-selection-span {
112
112
  /* This is dimmer than the other span, which is the name of the submenu. */
113
- color: rgba(0 0 0 / 54%);
113
+ color: rgba(0, 0, 0, 54%);
114
114
  }
115
115
 
116
116
  /* The submenus have somewhat different margins inside them. */
@@ -1,7 +1,7 @@
1
1
  #shaka-player-ui-thumbnail-container {
2
2
  background-color: black;
3
3
  border: 1px solid black;
4
- box-shadow: 0 8px 8px 0 rgb(0 0 0 / 50%);
4
+ box-shadow: 0 8px 8px 0 rgb(0, 0, 0, 50%);
5
5
  min-width: 150px;
6
6
  overflow: hidden;
7
7
  position: absolute;
@@ -14,7 +14,7 @@
14
14
  }
15
15
 
16
16
  #shaka-player-ui-thumbnail-time {
17
- background-color: rgb(0 0 0 / 50%);
17
+ background-color: rgb(0, 0, 0, 50%);
18
18
  bottom: 0;
19
19
  color: white;
20
20
  font-size: 16px;
@@ -29,7 +29,7 @@
29
29
  background-color: white;
30
30
  border: 1px solid black;
31
31
  border-radius: 10px;
32
- box-shadow: 0 8px 8px 0 rgb(0 0 0 / 50%);
32
+ box-shadow: 0 8px 8px 0 rgb(0, 0, 0, 50%);
33
33
  color: black;
34
34
  overflow: hidden;
35
35
  padding: 1px 7px;
@@ -53,7 +53,7 @@
53
53
  font-size: 13px;
54
54
 
55
55
  /* Styling */
56
- background: rgba(35 35 35 / 90%);
56
+ background: rgba(35, 35, 35, 90%);
57
57
  color: white;
58
58
  border-radius: 3px;
59
59
  padding: 5px 10px;