stormcloud-video-player 0.5.21 → 0.5.23

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.
@@ -50,15 +50,18 @@ declare class StormcloudVideoPlayer {
50
50
  private readonly backoffBaseMs;
51
51
  private readonly maxBackoffMs;
52
52
  private readonly adTransitionGapMs;
53
- private placeholderContainer;
53
+ private fillerVideo;
54
+ private fillerBreakTimerId;
54
55
  constructor(config: StormcloudVideoPlayerConfig);
55
56
  private adRequest;
56
57
  load(): Promise<void>;
57
58
  private getAdSource;
58
59
  private attachAdLayerEventListeners;
59
- private ensurePlaceholderContainer;
60
+ private ensureFillerVideo;
60
61
  private showPlaceholderLayer;
61
62
  private hidePlaceholderLayer;
63
+ private startFillerBreakTimer;
64
+ private stopFillerBreakTimer;
62
65
  private attach;
63
66
  private shouldUseNativeHls;
64
67
  private onId3Tag;
@@ -918,6 +918,106 @@ function createEmptyTrackingState() {
918
918
  complete: false
919
919
  };
920
920
  }
921
+ function firePixelWithRetry(url) {
922
+ var retries = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 2, delayMs = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 500, logPrefix = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : "[VastParser]";
923
+ return _async_to_generator(function() {
924
+ var _loop, attempt, _ret;
925
+ return _ts_generator(this, function(_state) {
926
+ switch(_state.label){
927
+ case 0:
928
+ _loop = function(attempt) {
929
+ var unused;
930
+ return _ts_generator(this, function(_state) {
931
+ switch(_state.label){
932
+ case 0:
933
+ _state.trys.push([
934
+ 0,
935
+ 2,
936
+ ,
937
+ 6
938
+ ]);
939
+ return [
940
+ 4,
941
+ fetch(url, {
942
+ method: "GET",
943
+ mode: "no-cors",
944
+ cache: "no-cache",
945
+ keepalive: true
946
+ })
947
+ ];
948
+ case 1:
949
+ _state.sent();
950
+ return [
951
+ 2,
952
+ {
953
+ v: void void 0
954
+ }
955
+ ];
956
+ case 2:
957
+ unused = _state.sent();
958
+ if (!(attempt < retries)) return [
959
+ 3,
960
+ 4
961
+ ];
962
+ return [
963
+ 4,
964
+ new Promise(function(r) {
965
+ return setTimeout(r, delayMs * Math.pow(2, attempt));
966
+ })
967
+ ];
968
+ case 3:
969
+ _state.sent();
970
+ return [
971
+ 3,
972
+ 5
973
+ ];
974
+ case 4:
975
+ console.warn("".concat(logPrefix, " Tracking pixel failed after ").concat(retries + 1, " attempts: ").concat(url));
976
+ _state.label = 5;
977
+ case 5:
978
+ return [
979
+ 3,
980
+ 6
981
+ ];
982
+ case 6:
983
+ return [
984
+ 2
985
+ ];
986
+ }
987
+ });
988
+ };
989
+ attempt = 0;
990
+ _state.label = 1;
991
+ case 1:
992
+ if (!(attempt <= retries)) return [
993
+ 3,
994
+ 4
995
+ ];
996
+ return [
997
+ 5,
998
+ _ts_values(_loop(attempt))
999
+ ];
1000
+ case 2:
1001
+ _ret = _state.sent();
1002
+ if (_type_of(_ret) === "object") return [
1003
+ 2,
1004
+ _ret.v
1005
+ ];
1006
+ _state.label = 3;
1007
+ case 3:
1008
+ attempt++;
1009
+ return [
1010
+ 3,
1011
+ 1
1012
+ ];
1013
+ case 4:
1014
+ return [
1015
+ 2
1016
+ ];
1017
+ }
1018
+ });
1019
+ })();
1020
+ }
921
1021
  function fireTrackingPixels(urls, sessionId) {
922
1022
  var logPrefix = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "[VastParser]";
923
1023
  if (!urls || urls.length === 0) return;
@@ -927,9 +1027,13 @@ function fireTrackingPixels(urls, sessionId) {
927
1027
  if (sessionId) {
928
1028
  trackingUrl = "".concat(trackingUrl).concat(trackingUrl.includes("?") ? "&" : "?", "session_id=").concat(sessionId);
929
1029
  }
930
- var img = new Image(1, 1);
931
- img.onerror = function() {};
932
- img.src = trackingUrl;
1030
+ if (typeof fetch !== "undefined") {
1031
+ firePixelWithRetry(trackingUrl, 2, 500, logPrefix).catch(function() {});
1032
+ } else {
1033
+ var img = new Image(1, 1);
1034
+ img.onerror = function() {};
1035
+ img.src = trackingUrl;
1036
+ }
933
1037
  console.log("".concat(logPrefix, " Fired tracking pixel: ").concat(trackingUrl));
934
1038
  } catch (error) {
935
1039
  console.warn("".concat(logPrefix, " Error firing tracking pixel:"), error);
@@ -3070,13 +3174,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3070
3174
  }
3071
3175
  }
3072
3176
  _this.adLayer.setAdVolume(_this.adLayer.getOriginalMutedState() ? 1 : _this.adLayer.getOriginalVolume());
3073
- if (_this.isShowingPlaceholder) {
3074
- if (_this.config.debugAdTiming) {
3075
- console.log("[StormcloudVideoPlayer] Hiding placeholder - new ads starting");
3076
- }
3077
- _this.hidePlaceholderLayer();
3078
- _this.adLayer.hidePlaceholder();
3079
- _this.isShowingPlaceholder = false;
3177
+ _this.stopFillerBreakTimer();
3178
+ _this.hidePlaceholderLayer();
3179
+ _this.isShowingPlaceholder = false;
3180
+ if (_this.config.debugAdTiming) {
3181
+ console.log("[StormcloudVideoPlayer] Hiding placeholder - new ads starting");
3080
3182
  }
3081
3183
  });
3082
3184
  this.adLayer.on("content_resume", function() {
@@ -3127,90 +3229,80 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3127
3229
  }
3128
3230
  },
3129
3231
  {
3130
- key: "ensurePlaceholderContainer",
3131
- value: function ensurePlaceholderContainer() {
3132
- if (this.placeholderContainer) {
3133
- return;
3134
- }
3135
- var container = document.createElement("div");
3136
- container.style.position = "absolute";
3137
- container.style.left = "0";
3138
- container.style.top = "0";
3139
- container.style.right = "0";
3140
- container.style.bottom = "0";
3141
- container.style.display = "none";
3142
- container.style.alignItems = "center";
3143
- container.style.justifyContent = "center";
3144
- container.style.pointerEvents = "none";
3145
- container.style.zIndex = "5";
3146
- container.style.backgroundColor = "#000";
3147
- container.style.transition = "opacity 0.3s ease-in-out";
3148
- container.style.opacity = "0";
3149
- if (!this.video.parentElement) {
3150
- if (this.config.debugAdTiming) {
3151
- console.warn("[StormcloudVideoPlayer] Video element has no parent for placeholder container");
3152
- }
3153
- return;
3154
- }
3155
- this.video.parentElement.appendChild(container);
3156
- this.placeholderContainer = container;
3232
+ key: "ensureFillerVideo",
3233
+ value: function ensureFillerVideo() {
3234
+ if (this.fillerVideo) return;
3235
+ if (!this.video.parentElement) return;
3236
+ var filler = document.createElement("video");
3237
+ filler.src = "https://f000.backblazeb2.com/file/AdStormAds/384/Sonifi_Filler.mp4";
3238
+ filler.loop = true;
3239
+ filler.muted = false;
3240
+ filler.playsInline = true;
3241
+ filler.style.position = "absolute";
3242
+ filler.style.left = "0";
3243
+ filler.style.top = "0";
3244
+ filler.style.width = "100%";
3245
+ filler.style.height = "100%";
3246
+ filler.style.objectFit = "cover";
3247
+ filler.style.zIndex = "20";
3248
+ filler.style.display = "none";
3249
+ filler.preload = "auto";
3250
+ this.video.parentElement.appendChild(filler);
3251
+ this.fillerVideo = filler;
3157
3252
  }
3158
3253
  },
3159
3254
  {
3160
3255
  key: "showPlaceholderLayer",
3161
3256
  value: function showPlaceholderLayer() {
3162
3257
  var _this = this;
3163
- this.ensurePlaceholderContainer();
3164
- if (!this.placeholderContainer) {
3165
- return;
3166
- }
3258
+ this.ensureFillerVideo();
3259
+ if (!this.fillerVideo) return;
3167
3260
  if (!this.video.muted) {
3168
3261
  this.video.muted = true;
3169
3262
  this.video.volume = 0;
3170
- if (this.config.debugAdTiming) {
3171
- console.log("[StormcloudVideoPlayer] Muted video when showing placeholder");
3172
- }
3173
- }
3174
- var wasHidden = this.placeholderContainer.style.display === "none" || this.placeholderContainer.style.opacity === "0";
3175
- if (wasHidden) {
3176
- this.placeholderContainer.style.transition = "none";
3177
- } else {
3178
- this.placeholderContainer.style.transition = "opacity 0.3s ease-in-out";
3179
- }
3180
- this.placeholderContainer.style.backgroundColor = "#000";
3181
- this.placeholderContainer.style.display = "flex";
3182
- this.placeholderContainer.offsetHeight;
3183
- this.placeholderContainer.style.opacity = "1";
3184
- this.placeholderContainer.style.pointerEvents = "auto";
3185
- if (wasHidden) {
3186
- requestAnimationFrame(function() {
3187
- if (_this.placeholderContainer) {
3188
- _this.placeholderContainer.style.transition = "opacity 0.3s ease-in-out";
3189
- }
3190
- });
3191
3263
  }
3264
+ this.fillerVideo.style.display = "block";
3265
+ this.fillerVideo.play().catch(function() {
3266
+ if (_this.fillerVideo) {
3267
+ _this.fillerVideo.style.display = "none";
3268
+ }
3269
+ });
3192
3270
  if (this.config.debugAdTiming) {
3193
- console.log("[StormcloudVideoPlayer] Showing placeholder layer");
3271
+ console.log("[StormcloudVideoPlayer] Showing filler video layer");
3194
3272
  }
3195
3273
  }
3196
3274
  },
3197
3275
  {
3198
3276
  key: "hidePlaceholderLayer",
3199
3277
  value: function hidePlaceholderLayer() {
3200
- var _this = this;
3201
- if (!this.placeholderContainer) {
3202
- return;
3203
- }
3204
- this.placeholderContainer.style.opacity = "0";
3205
- setTimeout(function() {
3206
- if (_this.placeholderContainer) {
3207
- _this.placeholderContainer.style.display = "none";
3208
- _this.placeholderContainer.style.pointerEvents = "none";
3209
- _this.placeholderContainer.style.backgroundColor = "#000";
3210
- }
3211
- }, 300);
3278
+ if (!this.fillerVideo) return;
3279
+ this.fillerVideo.style.display = "none";
3280
+ this.fillerVideo.pause();
3281
+ this.fillerVideo.currentTime = 0;
3212
3282
  if (this.config.debugAdTiming) {
3213
- console.log("[StormcloudVideoPlayer] Hiding placeholder layer");
3283
+ console.log("[StormcloudVideoPlayer] Hiding filler video layer");
3284
+ }
3285
+ }
3286
+ },
3287
+ {
3288
+ key: "startFillerBreakTimer",
3289
+ value: function startFillerBreakTimer(durationMs) {
3290
+ var _this = this;
3291
+ this.stopFillerBreakTimer();
3292
+ this.showPlaceholderLayer();
3293
+ this.fillerBreakTimerId = setTimeout(function() {
3294
+ _this.fillerBreakTimerId = void 0;
3295
+ _this.hidePlaceholderLayer();
3296
+ if (_this.inAdBreak) _this.handleAdPodComplete();
3297
+ }, durationMs);
3298
+ }
3299
+ },
3300
+ {
3301
+ key: "stopFillerBreakTimer",
3302
+ value: function stopFillerBreakTimer() {
3303
+ if (this.fillerBreakTimerId !== void 0) {
3304
+ clearTimeout(this.fillerBreakTimerId);
3305
+ this.fillerBreakTimerId = void 0;
3214
3306
  }
3215
3307
  }
3216
3308
  },
@@ -3223,6 +3315,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3223
3315
  this.video.autoplay = !!this.config.autoplay;
3224
3316
  this.video.muted = !!this.config.muted;
3225
3317
  this.adLayer.initialize();
3318
+ this.ensureFillerVideo();
3226
3319
  this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);
3227
3320
  this.attachAdLayerEventListeners();
3228
3321
  this.timeUpdateHandler = function() {
@@ -4142,7 +4235,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4142
4235
  this.totalAdsInBreak = 1;
4143
4236
  this.adPodQueue = [];
4144
4237
  this.showAds = true;
4145
- this.showPlaceholderLayer();
4238
+ if (adBreakDurationMs != null) {
4239
+ this.startFillerBreakTimer(adBreakDurationMs);
4240
+ } else {
4241
+ this.showPlaceholderLayer();
4242
+ }
4146
4243
  this.adLayer.showPlaceholder();
4147
4244
  if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {
4148
4245
  this.expectedAdBreakDurationMs = adBreakDurationMs;
@@ -4244,7 +4341,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4244
4341
  key: "stopContinuousFetching",
4245
4342
  value: function stopContinuousFetching() {
4246
4343
  this.continuousFetchingActive = false;
4247
- this.hidePlaceholderLayer();
4248
4344
  if (this.config.debugAdTiming) {
4249
4345
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Stopping continuous ad fetching");
4250
4346
  }
@@ -4435,13 +4531,23 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4435
4531
  key: "showPlaceholderAndWaitForAds",
4436
4532
  value: function showPlaceholderAndWaitForAds() {
4437
4533
  return _async_to_generator(function() {
4438
- var remaining, waitTime, checkInterval, maxChecks, i, bids, unused;
4534
+ var remaining, waitTime, stillRemaining2, checkInterval, maxChecks, i, bids, unused, stillRemaining;
4439
4535
  return _ts_generator(this, function(_state) {
4440
4536
  switch(_state.label){
4441
4537
  case 0:
4442
4538
  remaining = this.getRemainingAdMs();
4443
4539
  waitTime = Math.min(this.maxPlaceholderDurationMs, remaining);
4444
4540
  if (this.consecutiveFailures >= this.maxConsecutiveFailures) {
4541
+ stillRemaining2 = this.getRemainingAdMs();
4542
+ if (stillRemaining2 >= 1e3) {
4543
+ if (this.config.debugAdTiming) {
4544
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Max failures reached but break still active — resetting and continuing filler");
4545
+ }
4546
+ this.consecutiveFailures = 0;
4547
+ return [
4548
+ 2
4549
+ ];
4550
+ }
4445
4551
  if (this.config.debugAdTiming) {
4446
4552
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Skipping placeholder - too many consecutive failures");
4447
4553
  }
@@ -4460,6 +4566,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4460
4566
  console.log("[CONTINUOUS-FETCH] ⬛ Showing placeholder for ".concat(waitTime, "ms while waiting for ad response"));
4461
4567
  }
4462
4568
  this.isShowingPlaceholder = true;
4569
+ this.showPlaceholderLayer();
4463
4570
  this.adLayer.showPlaceholder();
4464
4571
  checkInterval = 300;
4465
4572
  maxChecks = Math.floor(waitTime / checkInterval);
@@ -4483,8 +4590,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4483
4590
  ];
4484
4591
  if (this.consecutiveFailures >= this.maxConsecutiveFailures) {
4485
4592
  if (this.config.debugAdTiming) {
4486
- console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Too many failures during placeholder wait");
4593
+ console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Too many failures during placeholder wait — resetting and continuing filler");
4487
4594
  }
4595
+ this.consecutiveFailures = 0;
4488
4596
  return [
4489
4597
  3,
4490
4598
  10
@@ -4551,6 +4659,18 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4551
4659
  1
4552
4660
  ];
4553
4661
  case 10:
4662
+ stillRemaining = this.getRemainingAdMs();
4663
+ if (stillRemaining >= 1e3) {
4664
+ if (this.config.debugAdTiming) {
4665
+ console.log("[CONTINUOUS-FETCH] ⏰ Placeholder slot expired, ".concat(stillRemaining, "ms still remaining — continuing filler"));
4666
+ }
4667
+ this.isShowingPlaceholder = false;
4668
+ this.adLayer.hidePlaceholder();
4669
+ this.consecutiveFailures = 0;
4670
+ return [
4671
+ 2
4672
+ ];
4673
+ }
4554
4674
  if (this.config.debugAdTiming) {
4555
4675
  console.log("[CONTINUOUS-FETCH] \u23F0 Placeholder timeout, ending ad break");
4556
4676
  }
@@ -4674,6 +4794,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4674
4794
  this.activeAdRequestToken = null;
4675
4795
  this.isInAdTransition = false;
4676
4796
  this.stopContinuousFetching();
4797
+ this.stopFillerBreakTimer();
4798
+ this.hidePlaceholderLayer();
4677
4799
  this.clearPendingAdBreak();
4678
4800
  this.pendingNextAdBids = null;
4679
4801
  if (this.isShowingPlaceholder) {
@@ -5082,16 +5204,18 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5082
5204
  value: function destroy() {
5083
5205
  var _this_hls, _this_adLayer;
5084
5206
  this.stopContinuousFetching();
5207
+ this.stopFillerBreakTimer();
5085
5208
  this.clearAdStartTimer();
5086
5209
  this.clearAdStopTimer();
5087
5210
  this.clearAdFailsafeTimer();
5088
5211
  this.clearAdRequestWatchdog();
5089
5212
  this.clearPendingAdBreak();
5090
- if (this.placeholderContainer) {
5091
- if (this.placeholderContainer.parentElement) {
5092
- this.placeholderContainer.parentElement.removeChild(this.placeholderContainer);
5213
+ if (this.fillerVideo) {
5214
+ this.fillerVideo.pause();
5215
+ if (this.fillerVideo.parentElement) {
5216
+ this.fillerVideo.parentElement.removeChild(this.fillerVideo);
5093
5217
  }
5094
- this.placeholderContainer = void 0;
5218
+ this.fillerVideo = void 0;
5095
5219
  }
5096
5220
  if (this.timeUpdateHandler) {
5097
5221
  this.video.removeEventListener("timeupdate", this.timeUpdateHandler);