shaka-player 4.2.8 → 4.2.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.
Files changed (104) hide show
  1. package/.github/workflows/build-and-test.yaml +4 -4
  2. package/.github/workflows/demo-version-index.yaml +6 -0
  3. package/.github/workflows/selenium-lab-tests.yaml +78 -17
  4. package/.github/workflows/update-screenshots.yaml +142 -0
  5. package/AUTHORS +2 -1
  6. package/CHANGELOG.md +50 -0
  7. package/CONTRIBUTORS +4 -1
  8. package/demo/common/asset.js +15 -0
  9. package/demo/common/assets.js +4 -2
  10. package/demo/common/message_ids.js +1 -0
  11. package/demo/custom.js +19 -0
  12. package/demo/locales/en.json +1 -0
  13. package/demo/locales/source.json +4 -0
  14. package/demo/main.js +14 -0
  15. package/dist/controls.css +1 -1
  16. package/dist/demo.compiled.debug.js +170 -290
  17. package/dist/demo.compiled.debug.map +4 -4
  18. package/dist/demo.compiled.js +170 -290
  19. package/dist/demo.compiled.map +4 -4
  20. package/dist/deps.js +2 -2
  21. package/dist/locales.js +30 -30
  22. package/dist/receiver.compiled.debug.js +52 -81
  23. package/dist/receiver.compiled.debug.map +4 -4
  24. package/dist/receiver.compiled.js +52 -81
  25. package/dist/receiver.compiled.map +4 -4
  26. package/dist/shaka-player.compiled.d.ts +19 -3
  27. package/dist/shaka-player.compiled.debug.d.ts +19 -3
  28. package/dist/shaka-player.compiled.debug.externs.js +17 -12
  29. package/dist/shaka-player.compiled.debug.js +181 -176
  30. package/dist/shaka-player.compiled.debug.map +4 -4
  31. package/dist/shaka-player.compiled.externs.js +17 -12
  32. package/dist/shaka-player.compiled.js +825 -823
  33. package/dist/shaka-player.compiled.map +3 -3
  34. package/dist/shaka-player.ui.d.ts +19 -3
  35. package/dist/shaka-player.ui.debug.d.ts +19 -3
  36. package/dist/shaka-player.ui.debug.externs.js +5 -0
  37. package/dist/shaka-player.ui.debug.js +191 -186
  38. package/dist/shaka-player.ui.debug.map +3 -3
  39. package/dist/shaka-player.ui.externs.js +5 -0
  40. package/dist/shaka-player.ui.js +955 -951
  41. package/dist/shaka-player.ui.map +3 -3
  42. package/docs/tutorials/a11y.md +0 -4
  43. package/docs/tutorials/ad_monetization.md +0 -4
  44. package/docs/tutorials/basic-usage.md +0 -5
  45. package/docs/tutorials/config.md +0 -5
  46. package/docs/tutorials/debugging.md +0 -5
  47. package/docs/tutorials/drm-config.md +0 -5
  48. package/docs/tutorials/errors.md +94 -0
  49. package/docs/tutorials/fairplay.md +4 -4
  50. package/docs/tutorials/index.json +2 -0
  51. package/docs/tutorials/license-server-auth.md +0 -5
  52. package/docs/tutorials/license-wrapping.md +0 -5
  53. package/docs/tutorials/network-and-buffering-config.md +0 -5
  54. package/docs/tutorials/ui-customization.md +0 -5
  55. package/docs/tutorials/ui.md +0 -7
  56. package/docs/tutorials/welcome.md +0 -5
  57. package/docs/tutorials/widevine-service-certs.md +45 -0
  58. package/externs/ima.js +9 -0
  59. package/externs/network_information.js +7 -2
  60. package/externs/shaka/abr_manager.js +6 -0
  61. package/externs/shaka/net.js +1 -0
  62. package/externs/shaka/player.js +13 -7
  63. package/lib/abr/simple_abr_manager.js +27 -3
  64. package/lib/ads/client_side_ad_manager.js +11 -5
  65. package/lib/dash/dash_parser.js +49 -48
  66. package/lib/debug/log.js +9 -13
  67. package/lib/hls/hls_parser.js +2 -0
  68. package/lib/media/drm_engine.js +4 -2
  69. package/lib/media/media_source_engine.js +11 -4
  70. package/lib/media/segment_index.js +2 -0
  71. package/lib/media/streaming_engine.js +8 -3
  72. package/lib/media/transmuxer.js +13 -7
  73. package/lib/media/video_wrapper.js +3 -3
  74. package/lib/net/http_fetch_plugin.js +79 -57
  75. package/lib/net/networking_engine.js +1 -0
  76. package/lib/offline/indexeddb/storage_mechanism.js +1 -1
  77. package/lib/player.js +24 -3
  78. package/lib/polyfill/media_capabilities.js +15 -8
  79. package/lib/polyfill/mediasource.js +24 -2
  80. package/lib/text/mp4_vtt_parser.js +4 -0
  81. package/lib/text/text_engine.js +1 -0
  82. package/lib/text/ui_text_displayer.js +1 -0
  83. package/lib/text/vtt_text_parser.js +4 -5
  84. package/lib/util/manifest_parser_utils.js +1 -2
  85. package/lib/util/mime_utils.js +12 -1
  86. package/lib/util/periods.js +5 -5
  87. package/lib/util/stream_utils.js +28 -16
  88. package/maintained-branches.md +3 -4
  89. package/package.json +1 -1
  90. package/test/media/content_workarounds_unit.js +43 -0
  91. package/test/media/drm_engine_integration.js +4 -17
  92. package/test/media/streaming_engine_unit.js +6 -1
  93. package/test/net/networking_engine_unit.js +6 -1
  94. package/test/player_integration.js +39 -0
  95. package/test/player_unit.js +57 -0
  96. package/test/polyfill/media_capabilities_unit.js +20 -23
  97. package/test/test/assets/text-clip-alt.vtt +63 -0
  98. package/test/test/util/fake_drm_engine.js +3 -0
  99. package/test/test/util/simple_fakes.js +6 -0
  100. package/test/test/util/test_scheme.js +9 -14
  101. package/test/text/mp4_vtt_parser_unit.js +8 -0
  102. package/test/text/vtt_text_parser_unit.js +26 -2
  103. package/test/text/web_vtt_layout_integration.js +0 -3
  104. package/test/util/mime_utils_unit.js +10 -0
@@ -56,10 +56,6 @@ this.eventManager.listen(this.button_, 'click', () => {
56
56
  });
57
57
  ```
58
58
 
59
- #### Continue the Tutorials
60
-
61
- Next, check out {@tutorial ad_monetization}.
62
-
63
59
 
64
60
 
65
61
  [Web Accessibility Standards]: https://www.w3.org/WAI/standards-guidelines/wcag/
@@ -222,7 +222,3 @@ before instantiating the player.
222
222
  // myapp.CustomAdManager is a placeholder name for your ad manager implementation.
223
223
  shaka.Player.setAdManagerFactory(() => new myapp.CustomAdManager());
224
224
  ```
225
-
226
- #### Continue the Tutorials
227
-
228
- Next, check out {@tutorial plugins}.
@@ -86,8 +86,3 @@ document.addEventListener('DOMContentLoaded', initApp);
86
86
  ```
87
87
 
88
88
  That's it!
89
-
90
-
91
- #### Continue the Tutorials
92
-
93
- Next, check out {@tutorial debugging}.
@@ -142,8 +142,3 @@ player.configure({
142
142
 
143
143
  For more detail on individual configuration options, please see the API docs for
144
144
  {@link shaka.extern.PlayerConfiguration} and {@link shaka.Player#configure}.
145
-
146
-
147
- #### Continue the Tutorials
148
-
149
- Next, check out {@tutorial network-and-buffering-config}.
@@ -187,8 +187,3 @@ To sum up, remember these points when debugging your application:
187
187
  - Use the debug version of Shaka Player for debugging and integration work
188
188
  - Refer to the docs for error codes
189
189
  - Increase the log level when you need more detail
190
-
191
-
192
- #### Continue the Tutorials
193
-
194
- Next, check out {@tutorial config}.
@@ -208,8 +208,3 @@ you should provide an empty string as robustness
208
208
  ##### Other key-systems
209
209
 
210
210
  Values for other key systems are not known to us at this time.
211
-
212
- #### Continue the Tutorials
213
-
214
- Next, check out {@tutorial license-server-auth}.
215
- Or check out {@tutorial fairplay}.
@@ -0,0 +1,94 @@
1
+ # Error Handling
2
+
3
+ The basics for handling native Error and {@link shaka.util.Error} thrown by Shaka.
4
+
5
+ ## Listening To and Handling Errors
6
+
7
+ ```javascript
8
+ const handleError = (error) => {
9
+ if (error instanceof Error) {
10
+ // shaka crashed with an unhandled native error
11
+ }
12
+
13
+ if (error.severity === shaka.util.Error.Severity.CRITICAL) {
14
+ // handle fatal error, playback can not continue
15
+ } else {
16
+ // handle non-fatal error, playback can continue
17
+ }
18
+ };
19
+
20
+ const player = new shaka.Player(video);
21
+
22
+ // handle errors that occur after load
23
+ player.addEventListener('error', handleError);
24
+
25
+ // there are two options for catching errors that occur during load
26
+
27
+ // it's possible to listen directly on the promise
28
+ player.load(url).catch(handleError);
29
+
30
+ // or to use async/await with a try/catch
31
+ try {
32
+ await player.load(url);
33
+ } catch (e) {
34
+ handleError(e);
35
+ }
36
+ ```
37
+
38
+ ## Custom Handling of Streaming Errors
39
+
40
+ The `streaming.failureCallback` property of {@link shaka.extern.PlayerConfiguration} can be used to add custom handling or error conversion of errors that occur during streaming.
41
+
42
+ ```javascript
43
+ player.configure('streaming.failureCallback', (error) => {
44
+ if (error.severity === shaka.util.Error.Severity.CRITICAL) {
45
+ // custom handling of critical error
46
+ // e.g. player.retryStreaming();
47
+ } else {
48
+ // custom handling of recoverable error
49
+ }
50
+ });
51
+ ```
52
+
53
+ ## Custom Handling of Retries
54
+
55
+ When configuring retry parameters in Shaka there may be known error codes that should not be retried, or the need to break out of an infinite retry loop in a live context. Retries for failed network requests are not reported as `RECOVERABLE` errors.
56
+
57
+ For example, if a VOD manifest is missing, unlike when a LIVE manifest is missing, it can be expected to not show up and there is no need to retry.
58
+
59
+ This is how to convert a retry into a critical error, see {@link shaka.net.NetworkingEngine.RetryEvent} and {@link shaka.util.Error} to decipher how the event can be parsed:
60
+
61
+ ```javascript
62
+ const nwEngine = player.getNetworkingEngine();
63
+
64
+ const vodManifestNotFoundHandler = (event /* shaka.net.NetworkingEngine.RetryEvent */) => {
65
+ const code = event.error.code;
66
+ const data = event.error.data;
67
+
68
+ if (code === shaka.util.Error.Code.BAD_HTTP_STATUS) {
69
+ if (
70
+ // each type of error has its own data structure (or none at all), tread with care
71
+ Array.isArray(data) &&
72
+ data[1] === 404 &&
73
+ data[4] === shaka.net.NetworkingEngine.RequestType.MANIFEST
74
+ ) {
75
+ // Throwing inside a retry callback will immediately stop retries
76
+ throw error;
77
+
78
+ // A proprietary error code can also be thrown
79
+ // throw new shaka.util.Error(
80
+ // shaka.util.Error.Severity.CRITICAL,
81
+ // shaka.util.Error.Category.NETWORK,
82
+ // 'RECOGNIZABLE_ERROR_MESSAGE'
83
+ // );
84
+ }
85
+ }
86
+ };
87
+
88
+ nwEngine.addEventListener('retry', vodManifestNotFoundHandler);
89
+
90
+ player.addEventListener('load'() => {
91
+ nwEngine.removeEventListener('retry', vodManifestNotFoundHandler);
92
+ });
93
+
94
+ ```
@@ -46,12 +46,12 @@ you.
46
46
  const req = await fetch('https://example.com/cert.der');
47
47
  const cert = await req.arrayBuffer();
48
48
 
49
- player.configure('drm.advanced.com\\.apple\\.fps\\.serverCertificate',
49
+ player.configure('drm.advanced.com\\.apple\\.fps.serverCertificate',
50
50
  new Uint8Array(cert));
51
51
  ```
52
52
 
53
53
  ```js
54
- player.configure('drm.advanced.com\\.apple\\.fps\\.serverCertificateUri',
54
+ player.configure('drm.advanced.com\\.apple\\.fps.serverCertificateUri',
55
55
  'https://example.com/cert.der');
56
56
  ```
57
57
 
@@ -65,13 +65,13 @@ is used by the browser to generate the license request. If you don't use the
65
65
  default content ID derivation, you need to specify a custom init data transform:
66
66
 
67
67
  ```js
68
- player.configure('drm.initDataTransform', (initData, initDataType) => {
68
+ player.configure('drm.initDataTransform', (initData, initDataType, drmInfo) => {
69
69
  if (initDataType != 'skd')
70
70
  return initData;
71
71
  // 'initData' is a buffer containing an 'skd://' URL as a UTF-8 string.
72
72
  const skdUri = shaka.util.StringUtils.fromBytesAutoDetect(initData);
73
73
  const contentId = getMyContentId(skdUri);
74
- const cert = player.drmInfo().serverCertificate;
74
+ const cert = drmInfo.serverCertificate;
75
75
  return shaka.util.FairPlayUtils.initDataTransform(initData, contentId, cert);
76
76
  });
77
77
  ```
@@ -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
+ { "errors": { "title": "Error Handling" } },
12
13
  { "a11y": { "title": "Creating accessible buttons" } },
13
14
  { "ad_monetization": { "title": "Serving ads with our IMA SDK integration" } },
14
15
  { "plugins": { "title": "Plugins and Customizing the Build" } },
@@ -16,6 +17,7 @@
16
17
  { "architecture": { "title": "Architecture Diagrams" } },
17
18
  { "service-worker": { "title": "Service Worker Caching" } },
18
19
  { "offline": { "title": "Offline Storage and Playback" } },
20
+ { "widevine-service-certs": { "title": "Widevine Service Certificates" } },
19
21
  { "fairplay": { "title": "FairPlay support" } },
20
22
  { "application-level-redirects": { "title": "Application-Level Redirects" } },
21
23
  { "blob-url": { "title": "Blob URL" } },
@@ -246,8 +246,3 @@ License request can now continue.
246
246
 
247
247
  If you need them, you can also create asynchronous response filters in the same
248
248
  way.
249
-
250
-
251
- #### Continue the Tutorials
252
-
253
- Next, check out {@tutorial license-wrapping}.
@@ -166,8 +166,3 @@ using a request filter:
166
166
 
167
167
  Load the page again, and the license response will be accepted by the Widevine
168
168
  CDM. Open the JavaScript console to see what the server sent back.
169
-
170
-
171
- #### Continue the Tutorials
172
-
173
- Next, check out {@tutorial ui}.
@@ -117,8 +117,3 @@ URLs in your manifests always use `https:`, or by having it not include the
117
117
  scheme (e.g., `//example.com/file.mp4`).
118
118
 
119
119
  [CORS]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
120
-
121
-
122
- #### Continue the Tutorials
123
-
124
- Next, check out {@tutorial drm-config}.
@@ -265,8 +265,3 @@ PR contributions to [the gallery repo][] are welcome.
265
265
  [@lucksy]: https://github.com/lucksy
266
266
  [pre-packaged Shaka UI themes]: https://lucksy.github.io/shaka-player-themes/
267
267
  [the gallery repo]: https://github.com/lucksy/shaka-player-themes
268
-
269
-
270
- #### Continue the Tutorials
271
-
272
- Next, check out {@tutorial a11y} to make your custom buttons accessible to screen readers.
@@ -227,10 +227,3 @@ ui.configure({
227
227
  'castAndroidReceiverCompatible': true,
228
228
  });
229
229
  ```
230
-
231
-
232
-
233
-
234
- #### Continue the Tutorials
235
-
236
- Next, check out {@tutorial ui-customization}.
@@ -106,8 +106,3 @@ To subscribe to new releases on GitHub, you can follow
106
106
  To receive infrequent announcements and surveys from us, you can join our
107
107
  [mailing list](https://groups.google.com/forum/#!forum/shaka-player-users).
108
108
  The list is very low volume, and can only be written to by us.
109
-
110
-
111
- #### Continue the Tutorials
112
-
113
- Next, check out {@tutorial basic-usage}.
@@ -0,0 +1,45 @@
1
+ # Widevine Service Certificates
2
+
3
+ With Widevine, you can eliminate one round-trip to your license server or proxy
4
+ per session by preloading a Widevine service certificate. You can either provide
5
+ it directly or set a URI and let Shaka fetch it for you. Do this before calling
6
+ `player.load()`. The values will persist across multiple calls to `load()` on
7
+ the same `shaka.Player` instance.
8
+
9
+ ```js
10
+ // This is an example of loading the certificate from your site at runtime.
11
+ // You could also choose to bundle it into your JavaScript as a Uint8Array.
12
+ const req = await fetch('https://example.com/service.cert');
13
+ const cert = new Uint8Array(await req.arrayBuffer());
14
+
15
+ // This is the short form for configuration of a certificate:
16
+ player.configure('drm.advanced.com\\.widevine\\.alpha.serverCertificate',
17
+ cert);
18
+
19
+ // This is the long form:
20
+ player.configure({
21
+ drm: {
22
+ advanced: {
23
+ 'com.widevine.alpha': {
24
+ 'serverCertificate': cert,
25
+ },
26
+ },
27
+ },
28
+ });
29
+
30
+
31
+ // This is the short form for configuration of a certificate URI:
32
+ player.configure('drm.advanced.com\\.widevine\\.alpha.serverCertificateUri',
33
+ 'https://example.com/service.cert');
34
+
35
+ // This is the long form:
36
+ player.configure({
37
+ drm: {
38
+ advanced: {
39
+ 'com.widevine.alpha': {
40
+ 'serverCertificateUri': 'https://example.com/service.cert',
41
+ },
42
+ },
43
+ },
44
+ });
45
+ ```
package/externs/ima.js CHANGED
@@ -501,6 +501,15 @@ google.ima.dai.api.StreamRequest.prototype.streamActivityMonitorId;
501
501
  google.ima.dai.api.StreamRequest.prototype.format;
502
502
 
503
503
 
504
+ /**
505
+ * @enum {string}
506
+ */
507
+ google.ima.dai.api.StreamRequest.StreamFormat = {
508
+ DASH: 'dash',
509
+ HLS: 'hls',
510
+ };
511
+
512
+
504
513
  /** @const */
505
514
  google.ima.dai.api.VODStreamRequest =
506
515
  class extends google.ima.dai.api.StreamRequest {};
@@ -19,5 +19,10 @@ NetworkInformation.prototype.saveData;
19
19
  * @param {string} type
20
20
  * @param {Function} listener
21
21
  */
22
- NetworkInformation.prototype.addEventListener =
23
- function(type, listener) {};
22
+ NetworkInformation.prototype.addEventListener = function(type, listener) {};
23
+
24
+ /**
25
+ * @param {string} type
26
+ * @param {Function} listener
27
+ */
28
+ NetworkInformation.prototype.removeEventListener = function(type, listener) {};
@@ -44,6 +44,12 @@ shaka.extern.AbrManager = class {
44
44
  */
45
45
  stop() {}
46
46
 
47
+ /**
48
+ * Request that this object release all internal references.
49
+ * @exportDoc
50
+ */
51
+ release() {}
52
+
47
53
  /**
48
54
  * Updates manager's variants collection.
49
55
  *
@@ -112,6 +112,7 @@ shaka.extern.Request;
112
112
  /**
113
113
  * @typedef {{
114
114
  * uri: string,
115
+ * originalUri: string,
115
116
  * data: BufferSource,
116
117
  * status: (number|undefined),
117
118
  * headers: !Object.<string, string>,
@@ -627,9 +627,7 @@ shaka.extern.AdvancedDrmConfiguration;
627
627
  * clearKeys: !Object.<string, string>,
628
628
  * delayLicenseRequestUntilPlayed: boolean,
629
629
  * advanced: Object.<string, shaka.extern.AdvancedDrmConfiguration>,
630
- * initDataTransform:
631
- * ((function(!Uint8Array, string, ?shaka.extern.DrmInfo):!Uint8Array)|
632
- * undefined),
630
+ * initDataTransform:(shaka.extern.InitDataTransform|undefined),
633
631
  * logLicenseExchange: boolean,
634
632
  * updateExpirationTime: number,
635
633
  * preferredKeySystems: !Array.<string>,
@@ -655,10 +653,7 @@ shaka.extern.AdvancedDrmConfiguration;
655
653
  * <i>Optional.</i> <br>
656
654
  * A dictionary which maps key system IDs to advanced DRM configuration for
657
655
  * those key systems.
658
- * @property
659
- * {((function(!Uint8Array, string, ?shaka.extern.DrmInfo):!Uint8Array)|
660
- * undefined)}
661
- * initDataTransform
656
+ * @property {shaka.extern.InitDataTransform|undefined} initDataTransform
662
657
  * <i>Optional.</i><br>
663
658
  * If given, this function is called with the init data from the
664
659
  * manifest/media and should return the (possibly transformed) init data to
@@ -687,6 +682,17 @@ shaka.extern.AdvancedDrmConfiguration;
687
682
  */
688
683
  shaka.extern.DrmConfiguration;
689
684
 
685
+ /**
686
+ * @typedef {function(!Uint8Array, string, ?shaka.extern.DrmInfo):!Uint8Array}
687
+ *
688
+ * @description
689
+ * A callback function to handle custom content ID signaling for FairPlay
690
+ * content.
691
+ *
692
+ * @exportDoc
693
+ */
694
+ shaka.extern.InitDataTransform;
695
+
690
696
 
691
697
  /**
692
698
  * @typedef {{
@@ -6,6 +6,7 @@
6
6
 
7
7
  goog.provide('shaka.abr.SimpleAbrManager');
8
8
 
9
+ goog.require('shaka.util.IReleasable');
9
10
  goog.require('goog.asserts');
10
11
  goog.require('shaka.abr.EwmaBandwidthEstimator');
11
12
  goog.require('shaka.log');
@@ -32,6 +33,7 @@ goog.require('shaka.util.Timer');
32
33
  * </p>
33
34
  *
34
35
  * @implements {shaka.extern.AbrManager}
36
+ * @implements {shaka.util.IReleasable}
35
37
  * @export
36
38
  */
37
39
  shaka.abr.SimpleAbrManager = class {
@@ -50,8 +52,8 @@ shaka.abr.SimpleAbrManager = class {
50
52
  // retrieving information about a user's network connection. We listen
51
53
  // to the change event to be able to make quick changes in case the type
52
54
  // of connectivity changes.
53
- if (navigator.connection) {
54
- navigator.connection.addEventListener('change', () => {
55
+ if (navigator.connection && navigator.connection.addEventListener) {
56
+ this.onNetworkInformationChange_ = () => {
55
57
  if (this.config_.useNetworkInformation && this.enabled_) {
56
58
  this.bandwidthEstimator_ = new shaka.abr.EwmaBandwidthEstimator();
57
59
  if (this.config_) {
@@ -62,7 +64,10 @@ shaka.abr.SimpleAbrManager = class {
62
64
  this.switch_(chosenVariant);
63
65
  }
64
66
  }
65
- });
67
+ };
68
+
69
+ navigator.connection.addEventListener(
70
+ 'change', this.onNetworkInformationChange_);
66
71
  }
67
72
 
68
73
  /**
@@ -93,6 +98,9 @@ shaka.abr.SimpleAbrManager = class {
93
98
  /** @private {ResizeObserver} */
94
99
  this.resizeObserver_ = null;
95
100
 
101
+ /** @private {?function():void} */
102
+ this.onNetworkInformationChange_ = null;
103
+
96
104
  /** @private {shaka.util.Timer} */
97
105
  this.resizeObserverTimer_ = new shaka.util.Timer(() => {
98
106
  if (this.config_.restrictToElementSize) {
@@ -128,6 +136,22 @@ shaka.abr.SimpleAbrManager = class {
128
136
  // can start using bandwidth estimates right away after init() is called.
129
137
  }
130
138
 
139
+ /**
140
+ * @override
141
+ * @export
142
+ */
143
+ release() {
144
+ // stop() should already have been called for unload
145
+
146
+ if (navigator.connection && navigator.connection.removeEventListener) {
147
+ navigator.connection.removeEventListener(
148
+ 'change', this.onNetworkInformationChange_);
149
+ this.onNetworkInformationChange_ = null;
150
+ }
151
+
152
+ this.resizeObserverTimer_ = null;
153
+ }
154
+
131
155
 
132
156
  /**
133
157
  * @override
@@ -79,9 +79,9 @@ shaka.ads.ClientSideAdManager = class {
79
79
  });
80
80
 
81
81
  // Notify the SDK when the video has ended, so it can play post-roll ads.
82
- this.video_.onended = () => {
82
+ this.eventManager_.listen(this.video_, 'ended', () => {
83
83
  this.adsLoader_.contentComplete();
84
- };
84
+ });
85
85
  }
86
86
 
87
87
  /**
@@ -219,9 +219,9 @@ shaka.ads.ClientSideAdManager = class {
219
219
  // seen the ads actually play until requestAds() is called.
220
220
  // Note: We listen for a play event to avoid autoplay issues that might
221
221
  // crash IMA.
222
- this.video_.addEventListener('play', () => {
222
+ this.eventManager_.listenOnce(this.video_, 'play', () => {
223
223
  this.imaAdsManager_.start();
224
- }, {once: true});
224
+ });
225
225
  } catch (adError) {
226
226
  // If there was a problem with the VAST response,
227
227
  // we we won't be getting an ad. Hide ad UI if we showed it already
@@ -427,6 +427,10 @@ shaka.ads.ClientSideAdManager = class {
427
427
  if (this.ad_.isLinear()) {
428
428
  this.adContainer_.setAttribute('ad-active', 'true');
429
429
  this.video_.pause();
430
+ this.ad_.setVolume(this.video_.volume);
431
+ if (this.video_.muted) {
432
+ this.ad_.setMuted(true);
433
+ }
430
434
  }
431
435
  }
432
436
 
@@ -439,7 +443,9 @@ shaka.ads.ClientSideAdManager = class {
439
443
  (new Map()).set('originalEvent', e)));
440
444
  if (this.ad_ && this.ad_.isLinear()) {
441
445
  this.adContainer_.removeAttribute('ad-active');
442
- this.video_.play();
446
+ if (!this.video_.ended) {
447
+ this.video_.play();
448
+ }
443
449
  }
444
450
  }
445
451
  };
@@ -1279,55 +1279,56 @@ shaka.dash.DashParser = class {
1279
1279
  context.period.id + ',' + context.representation.id : '';
1280
1280
 
1281
1281
  /** @type {shaka.extern.Stream} */
1282
- const stream = {
1283
- id: this.globalId_++,
1284
- originalId: context.representation.id,
1285
- createSegmentIndex: async () => {
1286
- // If we have a stream with the same context id stored in the map
1287
- // that has no segmentIndex, we should set the segmentIndex for it.
1288
- const storedInMap = contextId && context.dynamic &&
1289
- this.streamMap_[contextId];
1290
-
1291
- const currentStream = storedInMap ? this.streamMap_[contextId] : stream;
1292
- if (!currentStream.segmentIndex) {
1293
- currentStream.segmentIndex = await streamInfo.generateSegmentIndex();
1294
- }
1295
- },
1282
+ let stream;
1296
1283
 
1297
- closeSegmentIndex: () => {
1298
- if (stream.segmentIndex) {
1299
- stream.segmentIndex.release();
1300
- stream.segmentIndex = null;
1301
- }
1302
- },
1303
- segmentIndex: null,
1304
- mimeType: context.representation.mimeType,
1305
- codecs: context.representation.codecs,
1306
- frameRate: context.representation.frameRate,
1307
- pixelAspectRatio: context.representation.pixelAspectRatio,
1308
- bandwidth: context.bandwidth,
1309
- width: context.representation.width,
1310
- height: context.representation.height,
1311
- kind,
1312
- encrypted: contentProtection.drmInfos.length > 0,
1313
- drmInfos: contentProtection.drmInfos,
1314
- keyIds,
1315
- language,
1316
- label,
1317
- type: context.adaptationSet.contentType,
1318
- primary: isPrimary,
1319
- trickModeVideo: null,
1320
- emsgSchemeIdUris:
1321
- context.representation.emsgSchemeIdUris,
1322
- roles,
1323
- forced: forced,
1324
- channelsCount: context.representation.numChannels,
1325
- audioSamplingRate: context.representation.audioSamplingRate,
1326
- spatialAudio: spatialAudio,
1327
- closedCaptions,
1328
- hdr,
1329
- tilesLayout,
1330
- matchedStreams: [],
1284
+ if (contextId && this.streamMap_[contextId]) {
1285
+ stream = this.streamMap_[contextId];
1286
+ } else {
1287
+ stream = {
1288
+ id: this.globalId_++,
1289
+ originalId: context.representation.id,
1290
+ createSegmentIndex: () => Promise.resolve(),
1291
+ closeSegmentIndex: () => {
1292
+ if (stream.segmentIndex) {
1293
+ stream.segmentIndex.release();
1294
+ stream.segmentIndex = null;
1295
+ }
1296
+ },
1297
+ segmentIndex: null,
1298
+ mimeType: context.representation.mimeType,
1299
+ codecs: context.representation.codecs,
1300
+ frameRate: context.representation.frameRate,
1301
+ pixelAspectRatio: context.representation.pixelAspectRatio,
1302
+ bandwidth: context.bandwidth,
1303
+ width: context.representation.width,
1304
+ height: context.representation.height,
1305
+ kind,
1306
+ encrypted: contentProtection.drmInfos.length > 0,
1307
+ drmInfos: contentProtection.drmInfos,
1308
+ keyIds,
1309
+ language,
1310
+ label,
1311
+ type: context.adaptationSet.contentType,
1312
+ primary: isPrimary,
1313
+ trickModeVideo: null,
1314
+ emsgSchemeIdUris:
1315
+ context.representation.emsgSchemeIdUris,
1316
+ roles,
1317
+ forced,
1318
+ channelsCount: context.representation.numChannels,
1319
+ audioSamplingRate: context.representation.audioSamplingRate,
1320
+ spatialAudio,
1321
+ closedCaptions,
1322
+ hdr,
1323
+ tilesLayout,
1324
+ matchedStreams: [],
1325
+ };
1326
+ }
1327
+
1328
+ stream.createSegmentIndex = async () => {
1329
+ if (!stream.segmentIndex) {
1330
+ stream.segmentIndex = await streamInfo.generateSegmentIndex();
1331
+ }
1331
1332
  };
1332
1333
 
1333
1334
  if (contextId && context.dynamic && !this.streamMap_[contextId]) {
package/lib/debug/log.js CHANGED
@@ -134,23 +134,19 @@ shaka.log.MAX_LOG_LEVEL = 3;
134
134
  shaka.log.oneTimeWarningIssued_ = new Set();
135
135
 
136
136
 
137
- // IE8 has no console unless it is opened in advance.
138
- // IE9 console methods are not Functions and have no bind.
139
- if (window.console && window.console.log.bind) {
137
+ if (window.console) {
140
138
  /** @private {!Object.<shaka.log.Level, function(...*)>} */
141
139
  shaka.log.logMap_ = {
142
- /* eslint-disable no-restricted-syntax */
143
- [shaka.log.Level.ERROR]: console.error.bind(console),
144
- [shaka.log.Level.WARNING]: console.warn.bind(console),
145
- [shaka.log.Level.INFO]: console.info.bind(console),
146
- [shaka.log.Level.DEBUG]: console.log.bind(console),
147
- [shaka.log.Level.V1]: console.debug.bind(console),
148
- [shaka.log.Level.V2]: console.debug.bind(console),
149
- /* eslint-enable no-restricted-syntax */
140
+ [shaka.log.Level.ERROR]: (...args) => console.error(...args),
141
+ [shaka.log.Level.WARNING]: (...args) => console.warn(...args),
142
+ [shaka.log.Level.INFO]: (...args) => console.info(...args),
143
+ [shaka.log.Level.DEBUG]: (...args) => console.log(...args),
144
+ [shaka.log.Level.V1]: (...args) => console.debug(...args),
145
+ [shaka.log.Level.V2]: (...args) => console.debug(...args),
150
146
  };
151
147
 
152
- shaka.log.alwaysWarn = shaka.log.logMap_[shaka.log.Level.WARNING];
153
- shaka.log.alwaysError = shaka.log.logMap_[shaka.log.Level.ERROR];
148
+ shaka.log.alwaysWarn = (...args) => console.warn(...args);
149
+ shaka.log.alwaysError = (...args) => console.error(...args);
154
150
 
155
151
  if (goog.DEBUG) {
156
152
  // Since we don't want to export shaka.log in production builds, we don't