stormcloud-video-player 0.8.69 → 0.8.71

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.js CHANGED
@@ -2487,7 +2487,7 @@ function createHlsAdPlayer(contentVideo, options) {
2487
2487
  img.onload = null;
2488
2488
  img.onerror = null;
2489
2489
  inFlightBeacons.delete(img);
2490
- console.log("[HlsAdPlayer] Tracking pixel settled (".concat(outcome, "): ").concat(trackingUrl));
2490
+ console.log("[HlsAdPlayer] Tracking pixel settled (".concat(outcome, "): ").concat(trackingHost));
2491
2491
  if (outcome !== "load") {
2492
2492
  logFunnel("tracking_request_settled", {
2493
2493
  reason: outcome,
@@ -2505,7 +2505,7 @@ function createHlsAdPlayer(contentVideo, options) {
2505
2505
  return release("timeout");
2506
2506
  }, BEACON_TIMEOUT_MS);
2507
2507
  img.src = trackingUrl;
2508
- console.log("[HlsAdPlayer] Fired tracking pixel: ".concat(trackingUrl));
2508
+ console.log("[HlsAdPlayer] Fired tracking pixel: ".concat(trackingHost));
2509
2509
  logFunnel("tracking_request_created", {
2510
2510
  trackingHost: trackingHost,
2511
2511
  errorCode: options2 === null || options2 === void 0 ? void 0 : options2.errorCode
@@ -2959,7 +2959,7 @@ function createHlsAdPlayer(contentVideo, options) {
2959
2959
  });
2960
2960
  }
2961
2961
  if (parsed.type === "wrapper") {
2962
- console.log("[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ".concat(parsed.vastAdTagUri));
2962
+ console.log("[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ".concat(redactUrl(parsed.vastAdTagUri)));
2963
2963
  }
2964
2964
  return parsed;
2965
2965
  }
@@ -3151,8 +3151,8 @@ function createHlsAdPlayer(contentVideo, options) {
3151
3151
  switch(_state.label){
3152
3152
  case 0:
3153
3153
  attempt++;
3154
- if (kind === "gam") {
3155
- logFunnel("gam_http_request_sent", {
3154
+ if (kind !== "wrapper") {
3155
+ logFunnel("".concat(kind, "_http_request_sent"), {
3156
3156
  attempt: attempt,
3157
3157
  credentials: creds
3158
3158
  });
@@ -3172,8 +3172,8 @@ function createHlsAdPlayer(contentVideo, options) {
3172
3172
  ];
3173
3173
  case 1:
3174
3174
  response = _state.sent();
3175
- if (kind === "gam") {
3176
- logFunnel("gam_response_received", {
3175
+ if (kind !== "wrapper") {
3176
+ logFunnel("".concat(kind, "_response_received"), {
3177
3177
  attempt: attempt,
3178
3178
  httpStatus: response.status,
3179
3179
  ok: response.ok,
@@ -3343,8 +3343,7 @@ function createHlsAdPlayer(contentVideo, options) {
3343
3343
  elapsedMs: Date.now() - fetchStartedAt
3344
3344
  });
3345
3345
  }
3346
- console.log("[HlsAdPlayer] VAST XML received");
3347
- console.log("[HlsAdPlayer] VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
3346
+ console.log("[HlsAdPlayer] VAST XML received (length=".concat(vastXml.length, ")"));
3348
3347
  parsed = parseVastXml(vastXml);
3349
3348
  if (parsed.type === "empty") {
3350
3349
  ;
@@ -3385,16 +3384,35 @@ function createHlsAdPlayer(contentVideo, options) {
3385
3384
  });
3386
3385
  }).apply(this, arguments);
3387
3386
  }
3387
+ function isEdgeEmptySentinelAd(adElement) {
3388
+ var _textOf;
3389
+ if ((adElement.getAttribute("id") || "").trim().toLowerCase() === "empty") {
3390
+ return true;
3391
+ }
3392
+ var inLine = adElement.querySelector(":scope > InLine");
3393
+ if (!inLine) return false;
3394
+ if (/^no ad available$/i.test((_textOf = textOf(inLine.querySelector(":scope > AdTitle"))) !== null && _textOf !== void 0 ? _textOf : "")) {
3395
+ return true;
3396
+ }
3397
+ var durations = Array.from(inLine.querySelectorAll(":scope > Creatives > Creative > Linear > Duration")).map(function(el) {
3398
+ return parseVastTime(textOf(el));
3399
+ });
3400
+ return durations.length > 0 && durations.every(function(seconds) {
3401
+ return seconds === 0;
3402
+ });
3403
+ }
3388
3404
  function fetchAndParsePod(vastTagUrl) {
3405
+ var source = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "gam";
3389
3406
  return _async_to_generator(function() {
3390
- var _root_getAttribute, _root_getAttribute1, vastXml, trimmedXml, xmlDoc, root, adElements, _root_getAttribute2, _empty_errorUrls, empty, _empty_errorCode, resolveAd, podElements, buffet, resolveAll, ads, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, ad, err, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, ad1, err;
3407
+ var _root_getAttribute, _root_getAttribute1, isEdge, vastXml, trimmedXml, xmlDoc, root, adElements, _root_getAttribute2, _empty_errorUrls, empty, _empty_errorCode, resolveAd, candidates, podElements, buffet, resolveAll, ads, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, ad, err, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, ad1, err;
3391
3408
  return _ts_generator(this, function(_state) {
3392
3409
  switch(_state.label){
3393
3410
  case 0:
3394
3411
  lastPodAdElementCount = 0;
3412
+ isEdge = source === "edge";
3395
3413
  return [
3396
3414
  4,
3397
- fetchVastXml(vastTagUrl)
3415
+ fetchVastXml(vastTagUrl, isEdge ? "omit" : "include", source)
3398
3416
  ];
3399
3417
  case 1:
3400
3418
  vastXml = _state.sent();
@@ -3417,7 +3435,6 @@ function createHlsAdPlayer(contentVideo, options) {
3417
3435
  }
3418
3436
  xmlDoc = parseXml(vastXml);
3419
3437
  if (!xmlDoc) {
3420
- console.error("[HlsAdPlayer] Pod VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
3421
3438
  logFunnel("vast_parsed", {
3422
3439
  adElementCount: 0,
3423
3440
  reason: "xml_parse_error"
@@ -3489,12 +3506,24 @@ function createHlsAdPlayer(contentVideo, options) {
3489
3506
  });
3490
3507
  })();
3491
3508
  };
3492
- podElements = adElements.filter(function(el) {
3509
+ candidates = adElements;
3510
+ if (isEdge) {
3511
+ candidates = adElements.filter(function(el) {
3512
+ return !isEdgeEmptySentinelAd(el);
3513
+ });
3514
+ if (candidates.length < adElements.length) {
3515
+ logFunnel("edge_empty_sentinel", {
3516
+ sentinelCount: adElements.length - candidates.length,
3517
+ adElementCount: adElements.length
3518
+ });
3519
+ }
3520
+ }
3521
+ podElements = candidates.filter(function(el) {
3493
3522
  return getAdSequence(el) !== void 0;
3494
3523
  }).sort(function(a, b) {
3495
3524
  return getAdSequence(a) - getAdSequence(b);
3496
3525
  });
3497
- buffet = adElements.filter(function(el) {
3526
+ buffet = candidates.filter(function(el) {
3498
3527
  return getAdSequence(el) === void 0;
3499
3528
  });
3500
3529
  resolveAll = function resolveAll(elements) {
@@ -3651,7 +3680,9 @@ function createHlsAdPlayer(contentVideo, options) {
3651
3680
  lastPodAdElementCount = adElements.length;
3652
3681
  return [
3653
3682
  2,
3654
- ads
3683
+ isEdge ? ads.filter(function(ad) {
3684
+ return ad.duration > 0;
3685
+ }) : ads
3655
3686
  ];
3656
3687
  }
3657
3688
  });
@@ -4652,13 +4683,14 @@ function createHlsAdPlayer(contentVideo, options) {
4652
4683
  contentVideo[AD_CONTAINER_PROP] = adContainerEl;
4653
4684
  attachContainerHandlers();
4654
4685
  },
4655
- requestAds: function requestAds(vastTagUrl) {
4686
+ requestAds: function requestAds(vastTagUrl, requestOptions) {
4656
4687
  return _async_to_generator(function() {
4657
- var ads, preloaded, error;
4688
+ var _ref, source, ads, preloaded, error;
4658
4689
  return _ts_generator(this, function(_state) {
4659
4690
  switch(_state.label){
4660
4691
  case 0:
4661
- console.log("[HlsAdPlayer] Requesting ads:", vastTagUrl);
4692
+ source = (_ref = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.source) !== null && _ref !== void 0 ? _ref : "gam";
4693
+ console.log("[HlsAdPlayer] Requesting ads (".concat(source, "):"), redactUrl(vastTagUrl));
4662
4694
  if (adPlaying) {
4663
4695
  console.warn("[HlsAdPlayer] Cannot request new ads while an ad is playing");
4664
4696
  return [
@@ -4703,7 +4735,7 @@ function createHlsAdPlayer(contentVideo, options) {
4703
4735
  case 2:
4704
4736
  return [
4705
4737
  4,
4706
- fetchAndParsePod(vastTagUrl)
4738
+ fetchAndParsePod(vastTagUrl, source)
4707
4739
  ];
4708
4740
  case 3:
4709
4741
  ads = _state.sent();
@@ -5113,6 +5145,75 @@ function createHlsAdPlayer(contentVideo, options) {
5113
5145
  return podAds.reduce(function(total, ad) {
5114
5146
  return total + (ad.duration > 0 ? ad.duration * 1e3 : 0);
5115
5147
  }, 0);
5148
+ },
5149
+ limitPodToBudget: function limitPodToBudget(maxDurationMs, maxAds) {
5150
+ if (adPlaying) return podAds.length;
5151
+ var kept = [];
5152
+ var dropped = [];
5153
+ var totalMs = 0;
5154
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
5155
+ try {
5156
+ for(var _iterator = podAds[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
5157
+ var ad = _step.value;
5158
+ var durationMs = Math.round(ad.duration * 1e3);
5159
+ if (kept.length < maxAds && totalMs + durationMs <= maxDurationMs) {
5160
+ kept.push(ad);
5161
+ totalMs += durationMs;
5162
+ } else {
5163
+ dropped.push(ad);
5164
+ }
5165
+ }
5166
+ } catch (err) {
5167
+ _didIteratorError = true;
5168
+ _iteratorError = err;
5169
+ } finally{
5170
+ try {
5171
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
5172
+ _iterator.return();
5173
+ }
5174
+ } finally{
5175
+ if (_didIteratorError) {
5176
+ throw _iteratorError;
5177
+ }
5178
+ }
5179
+ }
5180
+ if (dropped.length > 0) {
5181
+ logFunnel("pod_trimmed_to_budget", {
5182
+ keptCount: kept.length,
5183
+ droppedCount: dropped.length,
5184
+ keptDurationMs: totalMs,
5185
+ maxDurationMs: maxDurationMs,
5186
+ maxAds: maxAds
5187
+ });
5188
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
5189
+ try {
5190
+ for(var _iterator1 = dropped[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
5191
+ var ad1 = _step1.value;
5192
+ resolvedAds.add(ad1);
5193
+ fireTrackingPixels(ad1.trackingUrls.notUsed, {
5194
+ ad: ad1
5195
+ });
5196
+ }
5197
+ } catch (err) {
5198
+ _didIteratorError1 = true;
5199
+ _iteratorError1 = err;
5200
+ } finally{
5201
+ try {
5202
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
5203
+ _iterator1.return();
5204
+ }
5205
+ } finally{
5206
+ if (_didIteratorError1) {
5207
+ throw _iteratorError1;
5208
+ }
5209
+ }
5210
+ }
5211
+ }
5212
+ podAds = kept;
5213
+ podIndex = 0;
5214
+ currentAd = kept[0];
5215
+ currentAdMediaFile = void 0;
5216
+ return kept.length;
5116
5217
  }
5117
5218
  };
5118
5219
  }
@@ -9125,6 +9226,71 @@ var HlsEngine = /*#__PURE__*/ function() {
9125
9226
  ]);
9126
9227
  return HlsEngine;
9127
9228
  }();
9229
+ // src/player/EdgePodRequest.ts
9230
+ var EDGE_POD_MAX_ADS = 10;
9231
+ var EDGE_POD_EXCEEDS_BUDGET = "edge_pod_exceeds_budget";
9232
+ var LICENSE_KEY_PLACEHOLDER = /\{licenseKey\}|%7BlicenseKey%7D/gi;
9233
+ function resolveEdgePodBaseUrl(config) {
9234
+ var _config_edgePodUrl, _config_licenseKey;
9235
+ if (config.enableEdgePodRequest !== true) return void 0;
9236
+ var raw = (_config_edgePodUrl = config.edgePodUrl) === null || _config_edgePodUrl === void 0 ? void 0 : _config_edgePodUrl.trim();
9237
+ if (!raw) {
9238
+ console.warn("[AdBreak][EDGE] enableEdgePodRequest is true but edgePodUrl is missing; using GAM only");
9239
+ return void 0;
9240
+ }
9241
+ var licenseKey = (_config_licenseKey = config.licenseKey) === null || _config_licenseKey === void 0 ? void 0 : _config_licenseKey.trim();
9242
+ if (!licenseKey) {
9243
+ console.warn("[AdBreak][EDGE] enableEdgePodRequest is true but licenseKey is missing; using GAM only");
9244
+ return void 0;
9245
+ }
9246
+ var encodedKey = encodeURIComponent(licenseKey);
9247
+ try {
9248
+ var hasPlaceholder = raw.search(LICENSE_KEY_PLACEHOLDER) !== -1;
9249
+ var url = new URL(hasPlaceholder ? raw.replace(LICENSE_KEY_PLACEHOLDER, encodedKey) : raw);
9250
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
9251
+ throw new Error("unsupported protocol ".concat(url.protocol));
9252
+ }
9253
+ if (!hasPlaceholder) {
9254
+ var path = url.pathname.replace(/\/+$/, "");
9255
+ url.pathname = /\/[^/]+\/pod$/.test(path) ? path.replace(/\/[^/]+\/pod$/, "/".concat(encodedKey, "/pod")) : "".concat(path, "/").concat(encodedKey, "/pod");
9256
+ }
9257
+ return url.toString();
9258
+ } catch (unused) {
9259
+ console.warn("[AdBreak][EDGE] edgePodUrl is not a valid http(s) URL; using GAM only");
9260
+ return void 0;
9261
+ }
9262
+ }
9263
+ function buildEdgePodUrl(baseUrl, remainingMs, remainingAdLimit) {
9264
+ var url = new URL(baseUrl);
9265
+ var maxMs = Math.max(0, Math.floor(remainingMs));
9266
+ var maxAds = Math.max(1, Math.min(EDGE_POD_MAX_ADS, Math.floor(remainingAdLimit)));
9267
+ url.searchParams.set("pmxd", String(maxMs));
9268
+ url.searchParams.set("pmad", String(maxAds));
9269
+ url.searchParams.set("duration", String(Math.floor(maxMs / 1e3)));
9270
+ url.searchParams.set("count", String(maxAds));
9271
+ return url.toString();
9272
+ }
9273
+ function classifyEdgeVastResponse(result) {
9274
+ var _ref;
9275
+ var _result_error;
9276
+ if (result.error == null) {
9277
+ return result.podAdCount > 0 ? "fill" : "no_fill";
9278
+ }
9279
+ var message = (_ref = (_result_error = result.error) === null || _result_error === void 0 ? void 0 : _result_error.message) !== null && _ref !== void 0 ? _ref : String(result.error);
9280
+ if (/no ads available|fill rejected|no media file|no ad loaded/i.test(message) || message.includes(EDGE_POD_EXCEEDS_BUDGET)) {
9281
+ return "no_fill";
9282
+ }
9283
+ return "invalid";
9284
+ }
9285
+ function describeEdgeUrl(url) {
9286
+ try {
9287
+ var parsed = new URL(url);
9288
+ return "".concat(parsed.origin).concat(parsed.pathname);
9289
+ } catch (unused) {
9290
+ var _url_split_;
9291
+ return (_url_split_ = url.split("?")[0]) !== null && _url_split_ !== void 0 ? _url_split_ : "";
9292
+ }
9293
+ }
9128
9294
  // src/player/PlayerControls.ts
9129
9295
  function getAdAudioVolume(adPlayer) {
9130
9296
  return adPlayer.getOriginalMutedState() ? 0 : adPlayer.getOriginalVolume();
@@ -9284,6 +9450,8 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9284
9450
  this.controllerCallInFlight = false;
9285
9451
  this.playbackStartedForCurrentRequest = false;
9286
9452
  this.opportunityEpoch = -1;
9453
+ this.edgeExhaustedForBreak = false;
9454
+ this.edgeRequestsInBreak = 0;
9287
9455
  this.adPodQueue = [];
9288
9456
  this.defaultMinRemainingMsToRequestAd = 1e4;
9289
9457
  this.defaultMaxNoFillsPerBreak = 2;
@@ -9434,7 +9602,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9434
9602
  _this.timing.clearAdRequestWatchdog();
9435
9603
  _this.timing.activeAdRequestToken = null;
9436
9604
  _this.showAds = true;
9437
- _this.timing.resetGamNoFillCounter();
9605
+ if (_this.currentPodSource !== "edge") {
9606
+ _this.timing.resetGamNoFillCounter();
9607
+ }
9438
9608
  if (_this.inAdBreak && _this.timing.expectedAdBreakDurationMs != null && _this.timing.getAdBreakEndWallClockMs() == null) {
9439
9609
  _this.timing.scheduleAdStopAtBreakBoundary();
9440
9610
  if (_this.debug) {
@@ -9566,6 +9736,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9566
9736
  key: "beginVmapBreak",
9567
9737
  value: function beginVmapBreak(breakKey, position) {
9568
9738
  this.breakSource = "vmap";
9739
+ this.resetEdgeStateForBreak();
9569
9740
  this.followUpBaseVastUrl = void 0;
9570
9741
  this.unusableResponsesInBreak = 0;
9571
9742
  this.timing.totalAdRequestsInBreak = 0;
@@ -9577,7 +9748,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9577
9748
  key: "handleAdStart",
9578
9749
  value: function handleAdStart(marker) {
9579
9750
  return _async_to_generator(function() {
9580
- var baseVastUrl, adBreakDurationMs, currentMuted, currentVolume, epoch, hasPrefetchedUrl, mode, podPlayed;
9751
+ var baseVastUrl, edgeConfigured, adBreakDurationMs, currentMuted, currentVolume, epoch, hasPrefetchedUrl, mode, edgeUrl, outcome, podPlayed;
9581
9752
  return _ts_generator(this, function(_state) {
9582
9753
  switch(_state.label){
9583
9754
  case 0:
@@ -9591,7 +9762,8 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9591
9762
  ];
9592
9763
  }
9593
9764
  baseVastUrl = this.adConfig.apiVastTagUrl;
9594
- if (!baseVastUrl) {
9765
+ edgeConfigured = !!this.host.getEdgePodBaseUrl();
9766
+ if (!baseVastUrl && !edgeConfigured) {
9595
9767
  console.warn("[AdBreak] SCTE-35 break started but no direct VAST tag is configured");
9596
9768
  this.clearPendingAdBreak();
9597
9769
  return [
@@ -9607,6 +9779,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9607
9779
  this.breakSource = "scte35";
9608
9780
  this.followUpBaseVastUrl = baseVastUrl;
9609
9781
  this.unusableResponsesInBreak = 0;
9782
+ this.resetEdgeStateForBreak();
9610
9783
  this.setSlotState("NEEDS_NEXT_AD", "scte35_break_start");
9611
9784
  if (this.adConfig.podAssignedByPrefetch) {
9612
9785
  this.adConfig.podAssignedByPrefetch = false;
@@ -9628,7 +9801,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9628
9801
  this.noteOpportunity("scte35", this.cueManager.activeScte35BreakKey, "midroll");
9629
9802
  epoch = this.timing.adBreakEpoch;
9630
9803
  hasPrefetchedUrl = !!(this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0);
9631
- if (!(adBreakDurationMs == null && !hasPrefetchedUrl)) return [
9804
+ if (!(adBreakDurationMs == null && (!hasPrefetchedUrl || edgeConfigured))) return [
9632
9805
  3,
9633
9806
  2
9634
9807
  ];
@@ -9647,11 +9820,46 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9647
9820
  mode = this.host.config.isLiveStream ? "LIVE" : "VOD";
9648
9821
  console.log("[AdBreak] ".concat(mode, " break start: target duration=").concat(adBreakDurationMs != null ? "".concat(adBreakDurationMs, "ms") : "unknown"));
9649
9822
  }
9823
+ if (!edgeConfigured) return [
9824
+ 3,
9825
+ 5
9826
+ ];
9827
+ edgeUrl = this.canRequestEdge() ? this.prepareEdgePodRequest() : void 0;
9828
+ if (!edgeUrl) return [
9829
+ 3,
9830
+ 4
9831
+ ];
9832
+ this.clearPendingAdBreak();
9650
9833
  return [
9651
9834
  4,
9652
- this.startOptimizedPod(baseVastUrl, adBreakDurationMs)
9835
+ this.runEdgePod(edgeUrl, "edge_break_start")
9653
9836
  ];
9654
9837
  case 3:
9838
+ outcome = _state.sent();
9839
+ this.continueAfterEdgeOutcome(outcome, epoch);
9840
+ return [
9841
+ 2
9842
+ ];
9843
+ case 4:
9844
+ if (!this.edgeExhaustedForBreak) {
9845
+ this.markEdgeExhausted("not_eligible_at_break_start", {
9846
+ isLive: this.isLiveBreak(),
9847
+ durationMs: this.timing.expectedAdBreakDurationMs
9848
+ });
9849
+ }
9850
+ _state.label = 5;
9851
+ case 5:
9852
+ if (!baseVastUrl) {
9853
+ this.requestNextAd("no_gam_source");
9854
+ return [
9855
+ 2
9856
+ ];
9857
+ }
9858
+ return [
9859
+ 4,
9860
+ this.startOptimizedPod(baseVastUrl, adBreakDurationMs)
9861
+ ];
9862
+ case 6:
9655
9863
  podPlayed = _state.sent();
9656
9864
  if (!podPlayed && this.inAdBreak && epoch === this.timing.adBreakEpoch) {
9657
9865
  this.setSlotState("NEEDS_NEXT_AD", "initial_request_failed");
@@ -9743,6 +9951,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9743
9951
  adPlayer = this.host.getAdPlayer();
9744
9952
  requestToken = ++this.timing.adRequestTokenCounter;
9745
9953
  this.timing.activeAdRequestToken = requestToken;
9954
+ this.currentPodSource = "gam";
9746
9955
  this.setSlotState("REQUESTING", "initial_pod");
9747
9956
  this.beginFunnelRequest(adPlayer, requestToken, "initial_pod");
9748
9957
  requestUrl = this.applyOpportunityFloor(podUrl);
@@ -9859,6 +10068,224 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9859
10068
  }).call(this);
9860
10069
  }
9861
10070
  },
10071
+ {
10072
+ // ───────────────────────────────────────────────────────────────
10073
+ // Edge-first pods (live SCTE-35 only, GAM fallback)
10074
+ // ───────────────────────────────────────────────────────────────
10075
+ key: "resetEdgeStateForBreak",
10076
+ value: function resetEdgeStateForBreak() {
10077
+ this.edgeExhaustedForBreak = false;
10078
+ this.edgeRequestsInBreak = 0;
10079
+ this.currentPodSource = void 0;
10080
+ }
10081
+ },
10082
+ {
10083
+ key: "isLiveBreak",
10084
+ value: function isLiveBreak() {
10085
+ return this.host.isLiveStream() || this.host.config.isLiveStream === true;
10086
+ }
10087
+ },
10088
+ {
10089
+ key: "canRequestEdge",
10090
+ value: function canRequestEdge() {
10091
+ return this.breakSource === "scte35" && !this.edgeExhaustedForBreak && !!this.host.getEdgePodBaseUrl() && this.isLiveBreak() && this.timing.expectedAdBreakDurationMs != null && this.edgeRequestsInBreak < this.timing.maxTotalAdRequestsPerBreak;
10092
+ }
10093
+ },
10094
+ {
10095
+ key: "markEdgeExhausted",
10096
+ value: function markEdgeExhausted(reason) {
10097
+ var extra = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
10098
+ this.edgeExhaustedForBreak = true;
10099
+ this.countFunnelStage("edge_fallback:".concat(reason));
10100
+ this.logOrchestratorFunnel("edge_exhausted", _object_spread({
10101
+ reason: reason,
10102
+ edgeRequests: this.edgeRequestsInBreak,
10103
+ remainingMs: this.timing.getRemainingAdMs()
10104
+ }, extra));
10105
+ }
10106
+ },
10107
+ {
10108
+ /**
10109
+ * Builds the next Edge request from the budget left right now, or marks Edge
10110
+ * exhausted for this break. Synchronous on purpose: callers must reach the
10111
+ * REQUESTING state in the same tick so a second completion event cannot race
10112
+ * in a parallel request.
10113
+ */ key: "prepareEdgePodRequest",
10114
+ value: function prepareEdgePodRequest() {
10115
+ var baseUrl = this.host.getEdgePodBaseUrl();
10116
+ if (!baseUrl) return void 0;
10117
+ var remainingMs = this.timing.getRemainingAdMs();
10118
+ var remainingAds = Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolvePodParams().maxAds - this.timing.totalAdsInBreak);
10119
+ if (remainingAds < 1) {
10120
+ this.markEdgeExhausted("ad_capacity_reached", {
10121
+ adsInBreak: this.timing.totalAdsInBreak
10122
+ });
10123
+ return void 0;
10124
+ }
10125
+ if (remainingMs < this.getMinRemainingMsToRequestAd()) {
10126
+ this.markEdgeExhausted("insufficient_break_time", {
10127
+ remainingMs: remainingMs
10128
+ });
10129
+ return void 0;
10130
+ }
10131
+ try {
10132
+ return buildEdgePodUrl(baseUrl, remainingMs, remainingAds);
10133
+ } catch (unused) {
10134
+ this.markEdgeExhausted("invalid_edge_url");
10135
+ return void 0;
10136
+ }
10137
+ }
10138
+ },
10139
+ {
10140
+ key: "runEdgePod",
10141
+ value: function runEdgePod(requestUrl, trigger) {
10142
+ return _async_to_generator(function() {
10143
+ var _params_get, _params_get1, epoch, generation, adPlayer, requestToken, params, _ref, _adPlayer_getPodAdCount, _adPlayer_getPodTotalDurationMs, remainingMs, remainingAds, podCount, error, errorMessage, classification, diag;
10144
+ return _ts_generator(this, function(_state) {
10145
+ switch(_state.label){
10146
+ case 0:
10147
+ epoch = this.timing.adBreakEpoch;
10148
+ this.recreateAdController("new_request");
10149
+ generation = this.controllerGeneration;
10150
+ adPlayer = this.host.getAdPlayer();
10151
+ requestToken = ++this.timing.adRequestTokenCounter;
10152
+ this.timing.activeAdRequestToken = requestToken;
10153
+ this.currentPodSource = "edge";
10154
+ this.edgeRequestsInBreak++;
10155
+ this.setSlotState("REQUESTING", trigger);
10156
+ this.beginFunnelRequest(adPlayer, requestToken, trigger, "edge");
10157
+ this.currentVastUrl = requestUrl;
10158
+ params = new URL(requestUrl).searchParams;
10159
+ this.logOrchestratorFunnel("edge_request_sent", {
10160
+ trigger: trigger,
10161
+ attempt: this.edgeRequestsInBreak,
10162
+ endpoint: describeEdgeUrl(requestUrl),
10163
+ pmxd: (_params_get = params.get("pmxd")) !== null && _params_get !== void 0 ? _params_get : void 0,
10164
+ pmad: (_params_get1 = params.get("pmad")) !== null && _params_get1 !== void 0 ? _params_get1 : void 0
10165
+ });
10166
+ _state.label = 1;
10167
+ case 1:
10168
+ _state.trys.push([
10169
+ 1,
10170
+ 4,
10171
+ ,
10172
+ 5
10173
+ ]);
10174
+ this.timing.startAdRequestWatchdog(requestToken);
10175
+ return [
10176
+ 4,
10177
+ this.callController(function() {
10178
+ return adPlayer.requestAds(requestUrl, {
10179
+ source: "edge"
10180
+ });
10181
+ })
10182
+ ];
10183
+ case 2:
10184
+ _state.sent();
10185
+ this.timing.clearAdRequestWatchdog();
10186
+ if (this.isStale(epoch, generation)) {
10187
+ this.logOrchestratorFunnel("stale_request_result_ignored", {
10188
+ requestId: requestToken,
10189
+ source: "edge"
10190
+ });
10191
+ return [
10192
+ 2,
10193
+ "stale"
10194
+ ];
10195
+ }
10196
+ remainingMs = this.timing.getRemainingAdMs();
10197
+ remainingAds = Math.max(1, Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolvePodParams().maxAds - this.timing.totalAdsInBreak));
10198
+ podCount = adPlayer.limitPodToBudget ? adPlayer.limitPodToBudget(remainingMs, remainingAds) : (_ref = (_adPlayer_getPodAdCount = adPlayer.getPodAdCount) === null || _adPlayer_getPodAdCount === void 0 ? void 0 : _adPlayer_getPodAdCount.call(adPlayer)) !== null && _ref !== void 0 ? _ref : 0;
10199
+ if (classifyEdgeVastResponse({
10200
+ podAdCount: podCount
10201
+ }) !== "fill") {
10202
+ throw new Error("".concat(EDGE_POD_EXCEEDS_BUDGET, ": no Edge ad fits ").concat(remainingMs, "ms"));
10203
+ }
10204
+ this.setSlotState("READY", "edge_vast_ready");
10205
+ this.logOrchestratorFunnel("edge_fill", {
10206
+ podAdCount: podCount,
10207
+ podDurationMs: (_adPlayer_getPodTotalDurationMs = adPlayer.getPodTotalDurationMs) === null || _adPlayer_getPodTotalDurationMs === void 0 ? void 0 : _adPlayer_getPodTotalDurationMs.call(adPlayer),
10208
+ remainingMs: remainingMs
10209
+ });
10210
+ sendAdLoadedTracking(this.host.config.licenseKey, {
10211
+ source: "hls",
10212
+ vastUrl: requestUrl,
10213
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
10214
+ }, this.analyticsContext).catch(function() {});
10215
+ this.timing.startAdFailsafeTimer(requestToken);
10216
+ return [
10217
+ 4,
10218
+ this.callController(function() {
10219
+ return adPlayer.play();
10220
+ })
10221
+ ];
10222
+ case 3:
10223
+ _state.sent();
10224
+ if (this.isStale(epoch, generation)) return [
10225
+ 2,
10226
+ "stale"
10227
+ ];
10228
+ if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {
10229
+ this.timing.scheduleAdStopAtBreakBoundary();
10230
+ }
10231
+ adPlayer.setAdVolume(getAdAudioVolume(adPlayer));
10232
+ return [
10233
+ 2,
10234
+ "fill"
10235
+ ];
10236
+ case 4:
10237
+ error = _state.sent();
10238
+ this.timing.clearAdRequestWatchdog();
10239
+ this.timing.clearAdFailsafeTimer();
10240
+ if (this.timing.activeAdRequestToken === requestToken) {
10241
+ this.timing.activeAdRequestToken = null;
10242
+ }
10243
+ errorMessage = error === null || error === void 0 ? void 0 : error.message;
10244
+ if (this.isStale(epoch, generation)) {
10245
+ this.logOrchestratorFunnel("stale_request_result_ignored", {
10246
+ requestId: requestToken,
10247
+ source: "edge",
10248
+ errorMessage: errorMessage
10249
+ });
10250
+ return [
10251
+ 2,
10252
+ "stale"
10253
+ ];
10254
+ }
10255
+ classification = classifyEdgeVastResponse({
10256
+ podAdCount: 0,
10257
+ error: error
10258
+ });
10259
+ diag = this.requestDiagnostics.get(requestToken);
10260
+ if (diag && !diag.failureReason) diag.failureReason = "edge_".concat(classification, ": ").concat(errorMessage);
10261
+ this.markEdgeExhausted("edge_".concat(classification), {
10262
+ errorMessage: errorMessage
10263
+ });
10264
+ return [
10265
+ 2,
10266
+ "fallback"
10267
+ ];
10268
+ case 5:
10269
+ return [
10270
+ 2
10271
+ ];
10272
+ }
10273
+ });
10274
+ }).call(this);
10275
+ }
10276
+ },
10277
+ {
10278
+ key: "continueAfterEdgeOutcome",
10279
+ value: function continueAfterEdgeOutcome(outcome, epoch) {
10280
+ if (outcome !== "fallback") return;
10281
+ if (!this.inAdBreak || epoch !== this.timing.adBreakEpoch) return;
10282
+ if (this.debug) {
10283
+ console.log("[AdBreak][EDGE] No usable Edge pod; checking with GAM for the remaining break");
10284
+ }
10285
+ this.setSlotState("NEEDS_NEXT_AD", "edge_fallback");
10286
+ this.requestNextAd("edge_fallback");
10287
+ }
10288
+ },
9862
10289
  {
9863
10290
  // ───────────────────────────────────────────────────────────────
9864
10291
  // Next-ad scheduling (single flight)
@@ -9914,7 +10341,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9914
10341
  value: function getStopRequestingReason(remainingMs) {
9915
10342
  if (this.breakSource === "vmap") {
9916
10343
  if (this.adPodQueue.length === 0) return "vmap_queue_empty";
9917
- } else if (this.breakSource !== "scte35" || !this.followUpBaseVastUrl) {
10344
+ } else if (this.breakSource !== "scte35" || !this.followUpBaseVastUrl && !this.canRequestEdge()) {
9918
10345
  return "no_follow_up_source";
9919
10346
  }
9920
10347
  if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {
@@ -9926,7 +10353,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9926
10353
  if (this.timing.totalAdRequestsInBreak >= this.timing.maxTotalAdRequestsPerBreak) {
9927
10354
  return "request_cap";
9928
10355
  }
9929
- if (this.timing.isGamInCooldown()) {
10356
+ if (!this.canRequestEdge() && this.timing.isGamInCooldown()) {
9930
10357
  return "gam_cooldown";
9931
10358
  }
9932
10359
  if (this.isBreakTimeBounded() && remainingMs < this.getMinRemainingMsToRequestAd()) {
@@ -10020,10 +10447,33 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10020
10447
  key: "requestFollowUpAd",
10021
10448
  value: function requestFollowUpAd(trigger) {
10022
10449
  return _async_to_generator(function() {
10023
- var url, epoch, unused;
10450
+ var edgeUrl, epoch2, outcome, url, epoch, unused;
10024
10451
  return _ts_generator(this, function(_state) {
10025
10452
  switch(_state.label){
10026
10453
  case 0:
10454
+ if (!this.canRequestEdge()) return [
10455
+ 3,
10456
+ 2
10457
+ ];
10458
+ edgeUrl = this.prepareEdgePodRequest();
10459
+ if (!edgeUrl) {
10460
+ this.requestNextAd("".concat(trigger, ":edge_unavailable"));
10461
+ return [
10462
+ 2
10463
+ ];
10464
+ }
10465
+ epoch2 = this.timing.adBreakEpoch;
10466
+ return [
10467
+ 4,
10468
+ this.runEdgePod(edgeUrl, "edge_".concat(trigger))
10469
+ ];
10470
+ case 1:
10471
+ outcome = _state.sent();
10472
+ this.continueAfterEdgeOutcome(outcome, epoch2);
10473
+ return [
10474
+ 2
10475
+ ];
10476
+ case 2:
10027
10477
  if (this.breakSource === "vmap") {
10028
10478
  url = this.adPodQueue.shift();
10029
10479
  } else if (this.followUpBaseVastUrl) {
@@ -10034,32 +10484,32 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10034
10484
  ];
10035
10485
  this.noteVastUrlGenerated(ensureVideoAdType(url), trigger);
10036
10486
  epoch = this.timing.adBreakEpoch;
10037
- _state.label = 1;
10038
- case 1:
10487
+ _state.label = 3;
10488
+ case 3:
10039
10489
  _state.trys.push([
10040
- 1,
10041
10490
  3,
10491
+ 5,
10042
10492
  ,
10043
- 4
10493
+ 6
10044
10494
  ]);
10045
10495
  return [
10046
10496
  4,
10047
10497
  this.playSingleAd(url, trigger)
10048
10498
  ];
10049
- case 2:
10499
+ case 4:
10050
10500
  _state.sent();
10051
10501
  return [
10052
10502
  3,
10053
- 4
10503
+ 6
10054
10504
  ];
10055
- case 3:
10505
+ case 5:
10056
10506
  unused = _state.sent();
10057
10507
  this.continueAfterRequestFailure(epoch);
10058
10508
  return [
10059
10509
  3,
10060
- 4
10510
+ 6
10061
10511
  ];
10062
- case 4:
10512
+ case 6:
10063
10513
  return [
10064
10514
  2
10065
10515
  ];
@@ -10172,7 +10622,11 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10172
10622
  case "gam_http_request_sent":
10173
10623
  diag.gamRequestSent++;
10174
10624
  break;
10625
+ case "edge_http_request_sent":
10626
+ diag.edgeRequestSent++;
10627
+ break;
10175
10628
  case "gam_response_received":
10629
+ case "edge_response_received":
10176
10630
  diag.vastHttpStatus = payload.httpStatus;
10177
10631
  break;
10178
10632
  case "vast_parsed":
@@ -10359,6 +10813,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10359
10813
  {
10360
10814
  key: "beginFunnelRequest",
10361
10815
  value: function beginFunnelRequest(adPlayer, requestToken, trigger) {
10816
+ var source = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : "gam";
10362
10817
  var _adPlayer_setFunnelContext;
10363
10818
  if (this.controllerCallInFlight) {
10364
10819
  this.logOrchestratorFunnel("duplicate_request_detected", {
@@ -10373,7 +10828,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10373
10828
  requestId: requestToken,
10374
10829
  controllerId: this.controllerGeneration,
10375
10830
  trigger: trigger,
10831
+ source: source,
10376
10832
  gamRequestSent: 0,
10833
+ edgeRequestSent: 0,
10377
10834
  wrapperDepth: 0,
10378
10835
  inlineResolved: false,
10379
10836
  mediaCandidateCount: 0,
@@ -10504,6 +10961,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10504
10961
  this.timing.activeAdRequestToken = requestToken;
10505
10962
  ap = this.host.getAdPlayer();
10506
10963
  budgetedUrl = this.withCurrentPodBudget(vastTagUrl);
10964
+ this.currentPodSource = "gam";
10507
10965
  this.setSlotState("REQUESTING", trigger);
10508
10966
  this.beginFunnelRequest(ap, requestToken, trigger);
10509
10967
  requestUrl = this.applyOpportunityFloor(budgetedUrl);
@@ -10651,6 +11109,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10651
11109
  requests: requests,
10652
11110
  requestRetries: requestRetries,
10653
11111
  gamResponses: count("gam_response_received"),
11112
+ edgeRequests: count("edge_request_sent"),
11113
+ edgeFills: count("edge_fill"),
11114
+ edgeEmptySentinels: count("edge_empty_sentinel"),
11115
+ edgeFallbacks: countPrefix("edge_fallback:"),
10654
11116
  requestsSuppressed: count("request_suppressed"),
10655
11117
  duplicates: count("duplicate_request_detected") + count("duplicate_break_start"),
10656
11118
  filled: count("vast_received"),
@@ -10747,6 +11209,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10747
11209
  this.breakSource = void 0;
10748
11210
  this.followUpBaseVastUrl = void 0;
10749
11211
  this.unusableResponsesInBreak = 0;
11212
+ this.resetEdgeStateForBreak();
10750
11213
  adPlayer.stop().catch(function() {});
10751
11214
  if (!alreadyEnded) this.logBreakFunnel(reason);
10752
11215
  this.opportunityFloor = void 0;
@@ -11060,7 +11523,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11060
11523
  });
11061
11524
  return;
11062
11525
  }
11063
- this.timing.consecutiveFailures++;
11526
+ if (this.currentPodSource === "edge") {
11527
+ this.markEdgeExhausted("edge_playback_failed", {
11528
+ reason: reason
11529
+ });
11530
+ } else {
11531
+ this.timing.consecutiveFailures++;
11532
+ }
11064
11533
  var diag = this.currentRequestId != null ? this.requestDiagnostics.get(this.currentRequestId) : void 0;
11065
11534
  if (diag && !diag.failureReason) diag.failureReason = reason;
11066
11535
  if (this.debug) {
@@ -11091,7 +11560,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11091
11560
  if (this.config.adFloorMaxCents != null) floorBounds.maxCents = this.config.adFloorMaxCents;
11092
11561
  if (this.config.adFloorStepCents != null) floorBounds.stepCents = this.config.adFloorStepCents;
11093
11562
  this.floorLadder = new FloorLadderController(this.config.adFloorLadder, floorBounds);
11563
+ this.floorLadderEnabled = this.config.adFloorLadderEnabled === true;
11094
11564
  this.warnOnInvalidFloorLadder(this.floorLadder.validate());
11565
+ this.edgePodBaseUrl = resolveEdgePodBaseUrl(this.config);
11095
11566
  this.adPlayer = this.createAdPlayer(false);
11096
11567
  this.palNonce = createPalNonceManager();
11097
11568
  this.cueManager = new Scte35CueManager(!!this.config.debugAdTiming, {
@@ -11191,11 +11662,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11191
11662
  generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
11192
11663
  return _this.generatePodVastUrl(base, breakDurationMs);
11193
11664
  },
11665
+ getEdgePodBaseUrl: function getEdgePodBaseUrl() {
11666
+ return _this.edgePodBaseUrl;
11667
+ },
11194
11668
  getFloorSnapshot: function getFloorSnapshot(position) {
11195
- return _this.floorLadder.snapshotFor({
11669
+ return _this.floorLadderEnabled ? _this.floorLadder.snapshotFor({
11196
11670
  position: position,
11197
11671
  isCtv: _this.isCtvEnvironment()
11198
- });
11672
+ }) : void 0;
11199
11673
  },
11200
11674
  onAdClick: function onAdClick() {
11201
11675
  return _this.palNonce.sendAdClick();
@@ -11246,11 +11720,43 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11246
11720
  return report;
11247
11721
  }
11248
11722
  },
11723
+ {
11724
+ key: "setAdFloorLadderEnabled",
11725
+ value: function setAdFloorLadderEnabled(enabled) {
11726
+ this.floorLadderEnabled = enabled;
11727
+ if (enabled) this.warnOnInvalidFloorLadder(this.floorLadder.validate());
11728
+ }
11729
+ },
11730
+ {
11731
+ key: "isAdFloorLadderEnabled",
11732
+ value: function isAdFloorLadderEnabled() {
11733
+ return this.floorLadderEnabled;
11734
+ }
11735
+ },
11736
+ {
11737
+ key: "setEdgePodRequest",
11738
+ value: function setEdgePodRequest(update) {
11739
+ if (update.enableEdgePodRequest === this.config.enableEdgePodRequest && update.edgePodUrl === this.config.edgePodUrl) {
11740
+ return;
11741
+ }
11742
+ if (update.enableEdgePodRequest === void 0) delete this.config.enableEdgePodRequest;
11743
+ else this.config.enableEdgePodRequest = update.enableEdgePodRequest;
11744
+ if (update.edgePodUrl === void 0) delete this.config.edgePodUrl;
11745
+ else this.config.edgePodUrl = update.edgePodUrl;
11746
+ this.edgePodBaseUrl = resolveEdgePodBaseUrl(this.config);
11747
+ }
11748
+ },
11749
+ {
11750
+ key: "getEdgePodUrl",
11751
+ value: function getEdgePodUrl() {
11752
+ return this.edgePodBaseUrl;
11753
+ }
11754
+ },
11249
11755
  {
11250
11756
  key: "warnOnInvalidFloorLadder",
11251
11757
  value: function warnOnInvalidFloorLadder(report) {
11252
11758
  var config = this.floorLadder.get();
11253
- if (report.ok || !config.enabled) return;
11759
+ if (report.ok || !this.floorLadderEnabled || !config.enabled) return;
11254
11760
  console.warn("[AdBreak][FLOOR] configuration has issues; invalid floors will not be sent", {
11255
11761
  errors: report.errors,
11256
11762
  configurationVersion: config.configurationVersion,
@@ -11983,6 +12489,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11983
12489
  this.timing.destroy();
11984
12490
  this.adBreak.clearPendingAdBreak();
11985
12491
  this.placeholder.destroy();
12492
+ 0;
11986
12493
  if (this.timeUpdateHandler) {
11987
12494
  this.video.removeEventListener("timeupdate", this.timeUpdateHandler);
11988
12495
  delete this.timeUpdateHandler;
@@ -12088,7 +12595,7 @@ var CRITICAL_PROPS = [
12088
12595
  var CONTROLS_HIDE_DELAY = 3e3;
12089
12596
  var DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;
12090
12597
  var StormcloudVideoPlayerComponent = React.memo(function(props) {
12091
- var src = props.src, autoplay = props.autoplay, muted = props.muted, lowLatencyMode = props.lowLatencyMode, allowNativeHls = props.allowNativeHls, isLiveStream = props.isLiveStream, driftToleranceMs = props.driftToleranceMs, immediateManifestAds = props.immediateManifestAds, debugAdTiming = props.debugAdTiming, showCustomControls = props.showCustomControls, hideLoadingIndicator = props.hideLoadingIndicator, onVolumeToggle = props.onVolumeToggle, onFullscreenToggle = props.onFullscreenToggle, onControlClick = props.onControlClick, onReady = props.onReady, wrapperClassName = props.wrapperClassName, wrapperStyle = props.wrapperStyle, className = props.className, style = props.style, controls = props.controls, playsInline = props.playsInline, preload = props.preload, poster = props.poster, children = props.children, licenseKey = props.licenseKey, vastMode = props.vastMode, vastTagUrl = props.vastTagUrl, isVmap = props.isVmap, vmapUrl = props.vmapUrl, minSegmentsBeforePlay = props.minSegmentsBeforePlay, ctvAdRequest = props.ctvAdRequest, programTitle = props.programTitle, channelName = props.channelName, minRemainingMsToStartAd = props.minRemainingMsToStartAd, minRemainingMsToRequestAd = props.minRemainingMsToRequestAd, maxNoFillsPerBreak = props.maxNoFillsPerBreak, adFloorLadder = props.adFloorLadder, adFloorMinCents = props.adFloorMinCents, adFloorMaxCents = props.adFloorMaxCents, adFloorStepCents = props.adFloorStepCents, restVideoAttrs = _object_without_properties(props, [
12598
+ var src = props.src, autoplay = props.autoplay, muted = props.muted, lowLatencyMode = props.lowLatencyMode, allowNativeHls = props.allowNativeHls, isLiveStream = props.isLiveStream, driftToleranceMs = props.driftToleranceMs, immediateManifestAds = props.immediateManifestAds, debugAdTiming = props.debugAdTiming, showCustomControls = props.showCustomControls, hideLoadingIndicator = props.hideLoadingIndicator, onVolumeToggle = props.onVolumeToggle, onFullscreenToggle = props.onFullscreenToggle, onControlClick = props.onControlClick, onReady = props.onReady, wrapperClassName = props.wrapperClassName, wrapperStyle = props.wrapperStyle, className = props.className, style = props.style, controls = props.controls, playsInline = props.playsInline, preload = props.preload, poster = props.poster, children = props.children, licenseKey = props.licenseKey, vastMode = props.vastMode, vastTagUrl = props.vastTagUrl, isVmap = props.isVmap, vmapUrl = props.vmapUrl, minSegmentsBeforePlay = props.minSegmentsBeforePlay, ctvAdRequest = props.ctvAdRequest, programTitle = props.programTitle, channelName = props.channelName, minRemainingMsToStartAd = props.minRemainingMsToStartAd, minRemainingMsToRequestAd = props.minRemainingMsToRequestAd, maxNoFillsPerBreak = props.maxNoFillsPerBreak, adFloorLadderEnabled = props.adFloorLadderEnabled, adFloorLadder = props.adFloorLadder, adFloorMinCents = props.adFloorMinCents, adFloorMaxCents = props.adFloorMaxCents, adFloorStepCents = props.adFloorStepCents, enableEdgePodRequest = props.enableEdgePodRequest, edgePodUrl = props.edgePodUrl, restVideoAttrs = _object_without_properties(props, [
12092
12599
  "src",
12093
12600
  "autoplay",
12094
12601
  "muted",
@@ -12125,10 +12632,13 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
12125
12632
  "minRemainingMsToStartAd",
12126
12633
  "minRemainingMsToRequestAd",
12127
12634
  "maxNoFillsPerBreak",
12635
+ "adFloorLadderEnabled",
12128
12636
  "adFloorLadder",
12129
12637
  "adFloorMinCents",
12130
12638
  "adFloorMaxCents",
12131
- "adFloorStepCents"
12639
+ "adFloorStepCents",
12640
+ "enableEdgePodRequest",
12641
+ "edgePodUrl"
12132
12642
  ]);
12133
12643
  var adFloorLadderKey = JSON.stringify(adFloorLadder !== null && adFloorLadder !== void 0 ? adFloorLadder : null);
12134
12644
  var videoRef = useRef(null);
@@ -12329,10 +12839,13 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
12329
12839
  if (minRemainingMsToStartAd !== void 0) cfg.minRemainingMsToStartAd = minRemainingMsToStartAd;
12330
12840
  if (minRemainingMsToRequestAd !== void 0) cfg.minRemainingMsToRequestAd = minRemainingMsToRequestAd;
12331
12841
  if (maxNoFillsPerBreak !== void 0) cfg.maxNoFillsPerBreak = maxNoFillsPerBreak;
12842
+ if (adFloorLadderEnabled !== void 0) cfg.adFloorLadderEnabled = adFloorLadderEnabled;
12332
12843
  if (adFloorLadder !== void 0) cfg.adFloorLadder = adFloorLadder;
12333
12844
  if (adFloorMinCents !== void 0) cfg.adFloorMinCents = adFloorMinCents;
12334
12845
  if (adFloorMaxCents !== void 0) cfg.adFloorMaxCents = adFloorMaxCents;
12335
12846
  if (adFloorStepCents !== void 0) cfg.adFloorStepCents = adFloorStepCents;
12847
+ if (enableEdgePodRequest !== void 0) cfg.enableEdgePodRequest = enableEdgePodRequest;
12848
+ if (edgePodUrl !== void 0) cfg.edgePodUrl = edgePodUrl;
12336
12849
  var player = new StormcloudVideoPlayer(cfg);
12337
12850
  playerRef.current = player;
12338
12851
  appliedFloorLadderKeyRef.current = adFloorLadderKey;
@@ -12381,6 +12894,25 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
12381
12894
  }, [
12382
12895
  adFloorLadderKey
12383
12896
  ]);
12897
+ useEffect(function() {
12898
+ if (!playerRef.current) return;
12899
+ var enabled = adFloorLadderEnabled === true;
12900
+ if (playerRef.current.isAdFloorLadderEnabled() === enabled) return;
12901
+ playerRef.current.setAdFloorLadderEnabled(enabled);
12902
+ }, [
12903
+ adFloorLadderEnabled
12904
+ ]);
12905
+ useEffect(function() {
12906
+ if (!playerRef.current) return;
12907
+ playerRef.current.setEdgePodRequest(_object_spread({}, enableEdgePodRequest !== void 0 ? {
12908
+ enableEdgePodRequest: enableEdgePodRequest
12909
+ } : {}, edgePodUrl !== void 0 ? {
12910
+ edgePodUrl: edgePodUrl
12911
+ } : {}));
12912
+ }, [
12913
+ enableEdgePodRequest,
12914
+ edgePodUrl
12915
+ ]);
12384
12916
  useEffect(function() {
12385
12917
  if (!playerRef.current) return;
12386
12918
  var checkAdStatus = function checkAdStatus() {
@@ -13457,6 +13989,9 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
13457
13989
  }
13458
13990
  }
13459
13991
  }
13992
+ if (prevProps.adFloorLadderEnabled !== nextProps.adFloorLadderEnabled || prevProps.enableEdgePodRequest !== nextProps.enableEdgePodRequest || prevProps.edgePodUrl !== nextProps.edgePodUrl) {
13993
+ return false;
13994
+ }
13460
13995
  if (JSON.stringify((_prevProps_adFloorLadder = prevProps.adFloorLadder) !== null && _prevProps_adFloorLadder !== void 0 ? _prevProps_adFloorLadder : null) !== JSON.stringify((_nextProps_adFloorLadder = nextProps.adFloorLadder) !== null && _nextProps_adFloorLadder !== void 0 ? _nextProps_adFloorLadder : null)) {
13461
13996
  return false;
13462
13997
  }