stormcloud-video-player 0.8.14 → 0.8.16

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/lib/index.cjs CHANGED
@@ -2940,6 +2940,7 @@ function supportsFeature(feature) {
2940
2940
  // src/utils/ctvVastSignals.ts
2941
2941
  var AIRY_ANDROID_APP_ID = "com.freeairytv.android";
2942
2942
  var AIRY_APP_NAME = "AiryTV Movies & TV";
2943
+ var AIRY_DEFAULT_CONTENT_URL = "https://live.airy.tv";
2943
2944
  var CTV_SESSION_STORAGE_KEY = "stormcloud.ctv.sid";
2944
2945
  var DEVICE_ID_STORAGE_KEYS = [
2945
2946
  "rdid",
@@ -2957,8 +2958,9 @@ function resolveCtvVastSignals() {
2957
2958
  var bridgeSignals = readNativeBridgeSignals();
2958
2959
  var deviceId = bridgeSignals.deviceId || readStoredDeviceId();
2959
2960
  var deviceIdType = bridgeSignals.deviceIdType || readStoredString("deviceIdType") || inferDeviceIdType();
2961
+ var contentUrl = bridgeSignals.contentUrl || readStoredString("contentUrl") || AIRY_DEFAULT_CONTENT_URL;
2960
2962
  return _object_spread_props(_object_spread({
2961
- contentUrl: "https://".concat(AIRY_ANDROID_APP_ID, ".example.com"),
2963
+ contentUrl: contentUrl,
2962
2964
  appId: AIRY_ANDROID_APP_ID,
2963
2965
  appName: AIRY_APP_NAME,
2964
2966
  sessionId: getOrCreateCtvSessionId()
@@ -3009,6 +3011,12 @@ function readNativeBridgeSignals() {
3009
3011
  try {
3010
3012
  for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3011
3013
  var source = _step.value;
3014
+ var contentUrl = readBridgeValue(source, [
3015
+ "contentUrl",
3016
+ "url",
3017
+ "videoUrl",
3018
+ "canonicalUrl"
3019
+ ]) || void 0;
3012
3020
  var deviceId = readBridgeValue(source, [
3013
3021
  "rdid",
3014
3022
  "ifa",
@@ -3016,7 +3024,7 @@ function readNativeBridgeSignals() {
3016
3024
  "adId",
3017
3025
  "deviceId"
3018
3026
  ]) || void 0;
3019
- if (!deviceId) continue;
3027
+ if (!contentUrl && !deviceId) continue;
3020
3028
  var deviceIdType = readBridgeValue(source, [
3021
3029
  "idtype",
3022
3030
  "deviceIdType",
@@ -3028,11 +3036,13 @@ function readNativeBridgeSignals() {
3028
3036
  "limitedAdTracking",
3029
3037
  "lat"
3030
3038
  ]);
3031
- return _object_spread({
3039
+ return _object_spread({}, contentUrl ? {
3040
+ contentUrl: contentUrl
3041
+ } : {}, deviceId ? {
3032
3042
  deviceId: deviceId
3033
- }, deviceIdType ? {
3043
+ } : {}, deviceId && deviceIdType ? {
3034
3044
  deviceIdType: deviceIdType
3035
- } : {}, limitAdTracking != null ? {
3045
+ } : {}, deviceId && limitAdTracking != null ? {
3036
3046
  limitAdTracking: limitAdTracking
3037
3047
  } : {});
3038
3048
  }
@@ -3792,7 +3802,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3792
3802
  _this.showAds = true;
3793
3803
  _this.resetGamNoFillCounter();
3794
3804
  if (_this.inAdBreak && _this.expectedAdBreakDurationMs != null && _this.adStopTimerId == null) {
3795
- _this.scheduleAdStopCountdown(_this.getRemainingAdMs());
3805
+ _this.scheduleAdStopAtBreakBoundary();
3796
3806
  if (_this.config.debugAdTiming) {
3797
3807
  console.log("[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)");
3798
3808
  }
@@ -4447,12 +4457,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4447
4457
  if (marker.durationSeconds != null) {
4448
4458
  var newDurationMs = marker.durationSeconds * 1e3;
4449
4459
  if (this.expectedAdBreakDurationMs == null || newDurationMs > this.expectedAdBreakDurationMs) {
4450
- this.expectedAdBreakDurationMs = newDurationMs;
4451
- var elapsedMs = this.currentAdBreakStartWallClockMs != null ? Date.now() - this.currentAdBreakStartWallClockMs : 0;
4452
- var remainingMs = Math.max(0, newDurationMs - elapsedMs);
4453
- this.scheduleAdStopCountdown(remainingMs);
4460
+ this.setAdBreakDurationBoundary(newDurationMs);
4461
+ this.scheduleAdStopAtBreakBoundary();
4454
4462
  if (this.config.debugAdTiming) {
4455
- console.log("[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ".concat(newDurationMs, "ms, remaining: ").concat(remainingMs, "ms"));
4463
+ console.log("[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ".concat(newDurationMs, "ms, remaining: ").concat(this.getWallClockRemainingAdMs(), "ms"));
4456
4464
  }
4457
4465
  }
4458
4466
  }
@@ -4526,13 +4534,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4526
4534
  }
4527
4535
  if (marker.type === "progress" && this.inAdBreak) {
4528
4536
  if (marker.durationSeconds != null) {
4529
- this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;
4530
- }
4531
- if (this.expectedAdBreakDurationMs != null && this.currentAdBreakStartWallClockMs != null) {
4532
- var elapsedMs1 = Date.now() - this.currentAdBreakStartWallClockMs;
4533
- var remainingMs1 = Math.max(0, this.expectedAdBreakDurationMs - elapsedMs1);
4534
- this.scheduleAdStopCountdown(remainingMs1);
4537
+ this.setAdBreakDurationBoundary(marker.durationSeconds * 1e3);
4535
4538
  }
4539
+ this.scheduleAdStopAtBreakBoundary();
4536
4540
  if (!this.adPlayer.isAdPlaying() && this.activeAdRequestToken === null && this.adRequestQueue.length > 0 && this.hasTimeToStartAnotherAd()) {
4537
4541
  this.tryNextAvailableAdWithRateLimit();
4538
4542
  }
@@ -4556,15 +4560,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4556
4560
  activeAdRequest: this.activeAdRequestToken !== null
4557
4561
  });
4558
4562
  }
4559
- if (adPlaying || remaining > 1e3 && hasQueuedAds) {
4560
- if (this.config.debugAdTiming) {
4561
- console.log("[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active");
4562
- }
4563
- return;
4564
- }
4565
- this.inAdBreak = false;
4566
- this.expectedAdBreakDurationMs = void 0;
4567
- this.currentAdBreakStartWallClockMs = void 0;
4563
+ this.scteAdBreakEndWallClockMs = Date.now();
4568
4564
  this.clearAdStartTimer();
4569
4565
  this.clearAdStopTimer();
4570
4566
  if (adPlaying) {
@@ -4581,12 +4577,46 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4581
4577
  this.inAdBreak = true;
4582
4578
  this.activeScte35BreakKey = cueKey !== null && cueKey !== void 0 ? cueKey : this.pendingScte35CueKey;
4583
4579
  this.scheduledScte35BreakKey = void 0;
4584
- this.expectedAdBreakDurationMs = durationMs;
4585
- this.currentAdBreakStartWallClockMs = Date.now();
4580
+ this.currentAdBreakStartWallClockMs = this.resolveScteBreakStartWallClockMs(marker);
4581
+ this.setAdBreakDurationBoundary(durationMs);
4586
4582
  this.handleAdStart(marker);
4587
- if (this.expectedAdBreakDurationMs != null) {
4588
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
4583
+ this.scheduleAdStopAtBreakBoundary();
4584
+ }
4585
+ },
4586
+ {
4587
+ key: "resolveScteBreakStartWallClockMs",
4588
+ value: function resolveScteBreakStartWallClockMs(marker) {
4589
+ var nowWallClockMs = Date.now();
4590
+ if (typeof marker.ptsSeconds !== "number") {
4591
+ return nowWallClockMs;
4592
+ }
4593
+ var nowMs = this.video.currentTime * 1e3;
4594
+ var estimatedCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
4595
+ var deltaMs = marker.ptsSeconds * 1e3 - estimatedCurrentPtsMs;
4596
+ if (!Number.isFinite(deltaMs)) {
4597
+ return nowWallClockMs;
4598
+ }
4599
+ return nowWallClockMs + Math.floor(deltaMs);
4600
+ }
4601
+ },
4602
+ {
4603
+ key: "setAdBreakDurationBoundary",
4604
+ value: function setAdBreakDurationBoundary(durationMs) {
4605
+ this.expectedAdBreakDurationMs = durationMs;
4606
+ if (durationMs != null && this.currentAdBreakStartWallClockMs != null) {
4607
+ this.scteAdBreakEndWallClockMs = this.currentAdBreakStartWallClockMs + durationMs;
4608
+ } else {
4609
+ this.scteAdBreakEndWallClockMs = void 0;
4610
+ }
4611
+ }
4612
+ },
4613
+ {
4614
+ key: "scheduleAdStopAtBreakBoundary",
4615
+ value: function scheduleAdStopAtBreakBoundary() {
4616
+ if (this.expectedAdBreakDurationMs == null) {
4617
+ return;
4589
4618
  }
4619
+ this.scheduleAdStopCountdown(this.getWallClockRemainingAdMs());
4590
4620
  }
4591
4621
  },
4592
4622
  {
@@ -6236,7 +6266,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6236
6266
  currentVolume = this.video.volume;
6237
6267
  this.adPlayer.updateOriginalMutedState(currentMuted, currentVolume);
6238
6268
  this.inAdBreak = true;
6239
- this.currentAdBreakStartWallClockMs = Date.now();
6240
6269
  this.adBreakPlayedDurationMs = 0;
6241
6270
  this.currentAdIndex = 0;
6242
6271
  this.totalAdsInBreak = 0;
@@ -6342,7 +6371,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6342
6371
  _state.sent();
6343
6372
  this.markAdStarted();
6344
6373
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
6345
- this.scheduleAdStopCountdown(this.getRemainingAdMs());
6374
+ this.scheduleAdStopAtBreakBoundary();
6346
6375
  }
6347
6376
  adVolume = currentMuted ? 0 : currentVolume;
6348
6377
  this.adPlayer.setAdVolume(adVolume);
@@ -6402,7 +6431,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6402
6431
  _state.sent();
6403
6432
  this.markAdStarted();
6404
6433
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
6405
- this.scheduleAdStopCountdown(this.getRemainingAdMs());
6434
+ this.scheduleAdStopAtBreakBoundary();
6406
6435
  }
6407
6436
  adVolume1 = currentMuted ? 0 : currentVolume;
6408
6437
  this.adPlayer.setAdVolume(adVolume1);
@@ -6475,7 +6504,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6475
6504
  _state.sent();
6476
6505
  this.markAdStarted();
6477
6506
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
6478
- this.scheduleAdStopCountdown(this.getRemainingAdMs());
6507
+ this.scheduleAdStopAtBreakBoundary();
6479
6508
  }
6480
6509
  adVolume2 = currentMuted ? 0 : currentVolume;
6481
6510
  this.adPlayer.setAdVolume(adVolume2);
@@ -6858,7 +6887,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6858
6887
  _state.sent();
6859
6888
  this.markAdStarted();
6860
6889
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
6861
- this.scheduleAdStopCountdown(this.getRemainingAdMs());
6890
+ this.scheduleAdStopAtBreakBoundary();
6862
6891
  }
6863
6892
  this.adPlayer.setAdVolume(this.getAdAudioVolume());
6864
6893
  this.consecutiveFailures = 0;
@@ -7386,19 +7415,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7386
7415
  {
7387
7416
  key: "ensureAdStoppedByTimer",
7388
7417
  value: function ensureAdStoppedByTimer() {
7389
- var _this_config_adBreakCheckIntervalMs, _this_expectedAdBreakDurationMs;
7418
+ var _this_config_adBreakCheckIntervalMs, _this_getAdBreakEndWallClockMs;
7390
7419
  if (!this.inAdBreak) return;
7391
7420
  this.adStopTimerId = void 0;
7392
7421
  var adPlaying = this.adPlayer.isAdPlaying();
7393
7422
  var checkIntervalMs = Math.max(250, Math.floor((_this_config_adBreakCheckIntervalMs = this.config.adBreakCheckIntervalMs) !== null && _this_config_adBreakCheckIntervalMs !== void 0 ? _this_config_adBreakCheckIntervalMs : 1e3));
7394
7423
  var maxExtensionMsConfig = this.config.maxAdBreakExtensionMs;
7395
7424
  var maxExtensionMs = typeof maxExtensionMsConfig === "number" && maxExtensionMsConfig > 0 ? maxExtensionMsConfig : 0;
7396
- var elapsedSinceStartMs = 0;
7397
- if (this.currentAdBreakStartWallClockMs != null) {
7398
- elapsedSinceStartMs = Date.now() - this.currentAdBreakStartWallClockMs;
7399
- }
7400
- var expectedDurationMs = (_this_expectedAdBreakDurationMs = this.expectedAdBreakDurationMs) !== null && _this_expectedAdBreakDurationMs !== void 0 ? _this_expectedAdBreakDurationMs : 0;
7401
- var overrunMs = Math.max(0, elapsedSinceStartMs - expectedDurationMs);
7425
+ var endWallClockMs = (_this_getAdBreakEndWallClockMs = this.getAdBreakEndWallClockMs()) !== null && _this_getAdBreakEndWallClockMs !== void 0 ? _this_getAdBreakEndWallClockMs : Date.now();
7426
+ var overrunMs = Math.max(0, Date.now() - endWallClockMs);
7402
7427
  var shouldExtendAdBreak = adPlaying && overrunMs < maxExtensionMs;
7403
7428
  if (shouldExtendAdBreak) {
7404
7429
  this.scheduleAdStopCountdown(checkIntervalMs);
@@ -7674,7 +7699,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7674
7699
  _state.sent();
7675
7700
  this.markAdStarted();
7676
7701
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
7677
- this.scheduleAdStopCountdown(this.getRemainingAdMs());
7702
+ this.scheduleAdStopAtBreakBoundary();
7678
7703
  }
7679
7704
  this.adPlayer.setAdVolume(this.getAdAudioVolume());
7680
7705
  this.consecutiveFailures = 0;
@@ -7726,7 +7751,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7726
7751
  _state.sent();
7727
7752
  this.markAdStarted();
7728
7753
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
7729
- this.scheduleAdStopCountdown(this.getRemainingAdMs());
7754
+ this.scheduleAdStopAtBreakBoundary();
7730
7755
  }
7731
7756
  this.adPlayer.setAdVolume(this.getAdAudioVolume());
7732
7757
  return [
@@ -7872,6 +7897,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7872
7897
  this.scheduledScte35BreakKey = void 0;
7873
7898
  this.expectedAdBreakDurationMs = void 0;
7874
7899
  this.currentAdBreakStartWallClockMs = void 0;
7900
+ this.scteAdBreakEndWallClockMs = void 0;
7875
7901
  this.clearAdStartTimer();
7876
7902
  this.clearAdStopTimer();
7877
7903
  this.adPodQueue = [];
@@ -8059,11 +8085,23 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8059
8085
  {
8060
8086
  key: "getWallClockRemainingAdMs",
8061
8087
  value: function getWallClockRemainingAdMs() {
8088
+ var endWallClockMs = this.getAdBreakEndWallClockMs();
8089
+ if (endWallClockMs != null) {
8090
+ return Math.max(0, endWallClockMs - Date.now());
8091
+ }
8092
+ return 0;
8093
+ }
8094
+ },
8095
+ {
8096
+ key: "getAdBreakEndWallClockMs",
8097
+ value: function getAdBreakEndWallClockMs() {
8098
+ if (this.scteAdBreakEndWallClockMs != null) {
8099
+ return this.scteAdBreakEndWallClockMs;
8100
+ }
8062
8101
  if (this.expectedAdBreakDurationMs == null || this.currentAdBreakStartWallClockMs == null) {
8063
- return 0;
8102
+ return void 0;
8064
8103
  }
8065
- var elapsed = Date.now() - this.currentAdBreakStartWallClockMs;
8066
- return Math.max(0, this.expectedAdBreakDurationMs - elapsed);
8104
+ return this.currentAdBreakStartWallClockMs + this.expectedAdBreakDurationMs;
8067
8105
  }
8068
8106
  },
8069
8107
  {