senza-sdk 4.2.55-fb0c331.0 → 4.2.56

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "senza-sdk",
3
- "version": "4.2.55-fb0c331.0",
3
+ "version": "4.2.56",
4
4
  "main": "./src/api.js",
5
5
  "description": "API for Senza application",
6
6
  "license": "MIT",
@@ -1031,6 +1031,8 @@ class RemotePlayer extends EventTarget {
1031
1031
  if (this._loadMode === this.LoadMode.LOADING || this._loadMode === this.LoadMode.UNLOADING) {
1032
1032
  throw new RemotePlayerError(6502, "Cannot call unload() while previous unload/load is still in progress");
1033
1033
  }
1034
+ this._abortSetAudioLanguage = true;
1035
+ this._abortSetSubtitleLanguage = true;
1034
1036
  this._abortSeeking = true;
1035
1037
  const previousLoadMode = this._loadMode;
1036
1038
  this._changeLoadMode(this.LoadMode.UNLOADING);
@@ -1326,7 +1328,7 @@ class RemotePlayer extends EventTarget {
1326
1328
 
1327
1329
  /**
1328
1330
  * Handles the asynchronous selection of an audio track.
1329
- * If the player is playing, it stops audio streamType before changing the track and resumes audio streamType playback if necessary.
1331
+ * It stops audio streamType before changing the track and resumes audio streamType playback if necessary.
1330
1332
  * Available only from v3 and on
1331
1333
  *
1332
1334
  * @param {string} audioTrackId - The ID of the audio track to select.
@@ -1462,7 +1464,7 @@ class RemotePlayer extends EventTarget {
1462
1464
 
1463
1465
  /**
1464
1466
  * Handles the asynchronous selection of a text track.
1465
- * If the player is playing, it stops subtitle streamType before changing the track and resumes subtitle streamType playback if necessary.
1467
+ * It stops subtitle streamType before changing the track and resumes subtitle streamType playback if necessary.
1466
1468
  * Available only from v3 and on
1467
1469
  *
1468
1470
  * @param {string} textTrackId - The ID of the text track to select.
@@ -1775,9 +1777,7 @@ class RemotePlayer extends EventTarget {
1775
1777
  await this._stop(StreamType.AUDIO);
1776
1778
  } catch (error) {
1777
1779
  sdkLogger.warn(`remotePlayer _atomicSetAudioLanguage: audioTrackId=${audioTrackId} failed on stop with error ${error.message}.`);
1778
- if (!this._abortSetAudioLanguage) {
1779
- setLanguageError = error;
1780
- }
1780
+ // ignore error
1781
1781
  }
1782
1782
 
1783
1783
  // check if load/unload were called
@@ -1844,9 +1844,7 @@ class RemotePlayer extends EventTarget {
1844
1844
  await this._stop(StreamType.SUBTITLE);
1845
1845
  } catch (error) {
1846
1846
  sdkLogger.warn(`remotePlayer _atomicSetSubtitleLanguage: textTrackId=${textTrackId} stop failed with error ${error.message}.`);
1847
- if (!this._abortSetSubtitleLanguage) {
1848
- setLanguageError = error;
1849
- }
1847
+ // ignore error
1850
1848
  }
1851
1849
 
1852
1850
  // check if load/unload were called
@@ -208,6 +208,8 @@ export class SenzaShakaPlayer extends shaka.Player {
208
208
  sdkLogger.warn("SenzaShakaPlayer constructor Adding videoElement in the constructor is going to be deprecated in the future. Please use attach method instead.");
209
209
  }
210
210
  SenzaShakaPlayer._prevInstance = this;
211
+
212
+
211
213
  }
212
214
 
213
215
  /**
@@ -233,6 +235,7 @@ export class SenzaShakaPlayer extends shaka.Player {
233
235
  * @export
234
236
  */
235
237
  async detach(keepAdManager = false) {
238
+
236
239
  await super.detach(keepAdManager);
237
240
  this._audioTracksMap = {};
238
241
  this._textTracksMap = {};
@@ -400,46 +403,74 @@ export class SenzaShakaPlayer extends shaka.Player {
400
403
  */
401
404
  async load(url, startTime, mimeType) {
402
405
 
403
- const waitForLoadModeChange = () => {
404
- const timeout = this.remotePlayer._remotePlayerConfirmationTimeout + 2000;
405
- return Promise.race([
406
- new Promise(resolve => this.remotePlayer.addEventListener("onloadmodechange", resolve, { once: true })),
407
- new Promise((_, reject) => setTimeout(() => reject(`Timeout: Event "onloadmodechange" did not occur within ${timeout}ms`), timeout))
408
- ]);
409
- };
406
+ // Create a promise that will resolve when _remotePlayerLoad is called
407
+ let remoteLoadResolver;
408
+ let remoteLoadRejecter;
409
+ const remoteLoadPromise = new Promise((resolve,reject) => {
410
+ remoteLoadResolver = resolve;
411
+ remoteLoadRejecter = reject;
412
+ });
413
+ // Create a flag to indicate whether the manifest load has been handled
414
+ let manifestLoadHandled = false;
415
+ const MANIFEST_TIMEOUT = 15000;
410
416
 
411
417
  // For live streams, we can set a default offset from the live edge
412
418
  // This allows for synchronizing the start position for both local and remote players
413
419
  // Note: For VOD content, negative start times are treated as 0
420
+
414
421
  const { defaultInitialLiveOffset, minInitialLiveOffset } = getPlatformInfo()?.sessionInfo?.settings?.["ui-streamer"] || {};
415
422
  if ((startTime === undefined || startTime === 0) && defaultInitialLiveOffset !== undefined) {
416
- sdkLogger.debug(`load() was called with startTime=${startTime}, setting startTime to ${-defaultInitialLiveOffset}`);
423
+ sdkLogger.info(`load() was called with startTime=${startTime}, setting startTime to ${-defaultInitialLiveOffset}`);
417
424
  startTime = -defaultInitialLiveOffset;
418
425
  } else if (startTime <= 0 && minInitialLiveOffset !== undefined && startTime > -minInitialLiveOffset) {
419
- sdkLogger.debug(`load() was called with startTime=${startTime}, setting startTime to ${-minInitialLiveOffset}`);
426
+ sdkLogger.info(`load() was called with startTime=${startTime}, setting startTime to ${-minInitialLiveOffset}`);
420
427
  startTime = -minInitialLiveOffset;
421
428
  }
422
429
 
423
- if (!this.isInRemotePlayback || remotePlayer.getAssetUri() !== url) {
424
- this._audioTracksMap = {};
425
- this._videoTracksMap = {};
426
- try {
427
- if (this.remotePlayer.getLoadMode() === this.remotePlayer.LoadMode.UNLOADING) {
428
- sdkLogger.warn("load() was called while previous unload is still in progress, waiting for unload to finish");
429
- await waitForLoadModeChange();
430
+ // This callbakc will be activated when the manifest is loaded. It will trigger load of the remote player.
431
+ // This will ensure that the remote player is loaded only after the manifest is loaded by local player.
432
+ const responseFilterCallback = async (type) => {
433
+ if (type === shaka.net.NetworkingEngine.RequestType.MANIFEST && !manifestLoadHandled) {
434
+ manifestLoadHandled = true;
435
+ try {
436
+ await this._remotePlayerLoad(url, startTime);
437
+ remoteLoadResolver();
438
+ } catch (error) {
439
+ remoteLoadRejecter(error);
430
440
  }
431
- await this.remotePlayer.load(url, startTime);
432
- } catch (error) {
433
- sdkLogger.log("Couldn't load remote player. Error:", error);
434
- this.handleSenzaError(error.code, error.message);
441
+
435
442
  }
436
- }
443
+ };
444
+
445
+ // Register the response filter
446
+ this.getNetworkingEngine().registerResponseFilter(responseFilterCallback);
447
+
448
+ const loadPromise = Promise.all([
449
+ super.load(url, startTime, mimeType),
450
+ remoteLoadPromise
451
+ ]);
452
+ // Set a timeout for the manifest load notification
453
+ let timerId;
454
+ const timerPromise = new Promise((_, reject) => {
455
+ timerId = setTimeout(() => {
456
+ const error = new Error("Manifest load timeout");
457
+ error.code = 8003;
458
+ reject(error);
459
+ }, MANIFEST_TIMEOUT);
460
+ });
461
+
437
462
  try {
438
- await super.load(url, startTime, mimeType);
463
+ return await Promise.race([loadPromise, timerPromise]);
464
+
439
465
  } catch (error) {
440
- sdkLogger.log("Couldn't load local player. Error:", error);
466
+ sdkLogger.log("Couldn't load player. Error:", error);
441
467
  this.handleSenzaError(error.code, error.message);
468
+
469
+ } finally {
470
+ this.getNetworkingEngine().unregisterResponseFilter(responseFilterCallback);
471
+ clearTimeout(timerId);
442
472
  }
473
+
443
474
  }
444
475
 
445
476
  /***
@@ -508,6 +539,32 @@ export class SenzaShakaPlayer extends shaka.Player {
508
539
 
509
540
  }
510
541
 
542
+ async _remotePlayerLoad(url,startTime) {
543
+ const waitForLoadModeChange = () => {
544
+ const timeout = this.remotePlayer._remotePlayerConfirmationTimeout + 2000;
545
+ return Promise.race([
546
+ new Promise(resolve => this.remotePlayer.addEventListener("onloadmodechange", resolve, { once: true })),
547
+ new Promise((_, reject) => setTimeout(() => reject(`Timeout: Event "onloadmodechange" did not occur within ${timeout}ms`), timeout))
548
+ ]);
549
+ };
550
+
551
+ if (!this.isInRemotePlayback || remotePlayer.getAssetUri() !== url) {
552
+ this._audioTracksMap = {};
553
+ this._videoTracksMap = {};
554
+ try {
555
+ if (this.remotePlayer.getLoadMode() === this.remotePlayer.LoadMode.UNLOADING) {
556
+ sdkLogger.warn("load() was called while previous unload is still in progress, waiting for unload to finish");
557
+ await waitForLoadModeChange();
558
+ }
559
+ sdkLogger.info("Loading remote player with startTime:", startTime);
560
+ await this.remotePlayer.load(url, startTime);
561
+ sdkLogger.log("Remote player loaded successfully");
562
+ } catch (error) {
563
+ sdkLogger.error("Couldn't load remote player. Error:", error);
564
+ this.handleSenzaError(error.code, error.message);
565
+ }
566
+ }
567
+ }
511
568
  /**
512
569
  * @private
513
570
  */