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.
@@ -2483,7 +2483,7 @@ function createHlsAdPlayer(contentVideo, options) {
2483
2483
  img.onload = null;
2484
2484
  img.onerror = null;
2485
2485
  inFlightBeacons.delete(img);
2486
- console.log("[HlsAdPlayer] Tracking pixel settled (".concat(outcome, "): ").concat(trackingUrl));
2486
+ console.log("[HlsAdPlayer] Tracking pixel settled (".concat(outcome, "): ").concat(trackingHost));
2487
2487
  if (outcome !== "load") {
2488
2488
  logFunnel("tracking_request_settled", {
2489
2489
  reason: outcome,
@@ -2501,7 +2501,7 @@ function createHlsAdPlayer(contentVideo, options) {
2501
2501
  return release("timeout");
2502
2502
  }, BEACON_TIMEOUT_MS);
2503
2503
  img.src = trackingUrl;
2504
- console.log("[HlsAdPlayer] Fired tracking pixel: ".concat(trackingUrl));
2504
+ console.log("[HlsAdPlayer] Fired tracking pixel: ".concat(trackingHost));
2505
2505
  logFunnel("tracking_request_created", {
2506
2506
  trackingHost: trackingHost,
2507
2507
  errorCode: options2 === null || options2 === void 0 ? void 0 : options2.errorCode
@@ -2955,7 +2955,7 @@ function createHlsAdPlayer(contentVideo, options) {
2955
2955
  });
2956
2956
  }
2957
2957
  if (parsed.type === "wrapper") {
2958
- console.log("[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ".concat(parsed.vastAdTagUri));
2958
+ console.log("[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ".concat(redactUrl(parsed.vastAdTagUri)));
2959
2959
  }
2960
2960
  return parsed;
2961
2961
  }
@@ -3147,8 +3147,8 @@ function createHlsAdPlayer(contentVideo, options) {
3147
3147
  switch(_state.label){
3148
3148
  case 0:
3149
3149
  attempt++;
3150
- if (kind === "gam") {
3151
- logFunnel("gam_http_request_sent", {
3150
+ if (kind !== "wrapper") {
3151
+ logFunnel("".concat(kind, "_http_request_sent"), {
3152
3152
  attempt: attempt,
3153
3153
  credentials: creds
3154
3154
  });
@@ -3168,8 +3168,8 @@ function createHlsAdPlayer(contentVideo, options) {
3168
3168
  ];
3169
3169
  case 1:
3170
3170
  response = _state.sent();
3171
- if (kind === "gam") {
3172
- logFunnel("gam_response_received", {
3171
+ if (kind !== "wrapper") {
3172
+ logFunnel("".concat(kind, "_response_received"), {
3173
3173
  attempt: attempt,
3174
3174
  httpStatus: response.status,
3175
3175
  ok: response.ok,
@@ -3339,8 +3339,7 @@ function createHlsAdPlayer(contentVideo, options) {
3339
3339
  elapsedMs: Date.now() - fetchStartedAt
3340
3340
  });
3341
3341
  }
3342
- console.log("[HlsAdPlayer] VAST XML received");
3343
- console.log("[HlsAdPlayer] VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
3342
+ console.log("[HlsAdPlayer] VAST XML received (length=".concat(vastXml.length, ")"));
3344
3343
  parsed = parseVastXml(vastXml);
3345
3344
  if (parsed.type === "empty") {
3346
3345
  ;
@@ -3381,16 +3380,35 @@ function createHlsAdPlayer(contentVideo, options) {
3381
3380
  });
3382
3381
  }).apply(this, arguments);
3383
3382
  }
3383
+ function isEdgeEmptySentinelAd(adElement) {
3384
+ var _textOf;
3385
+ if ((adElement.getAttribute("id") || "").trim().toLowerCase() === "empty") {
3386
+ return true;
3387
+ }
3388
+ var inLine = adElement.querySelector(":scope > InLine");
3389
+ if (!inLine) return false;
3390
+ if (/^no ad available$/i.test((_textOf = textOf(inLine.querySelector(":scope > AdTitle"))) !== null && _textOf !== void 0 ? _textOf : "")) {
3391
+ return true;
3392
+ }
3393
+ var durations = Array.from(inLine.querySelectorAll(":scope > Creatives > Creative > Linear > Duration")).map(function(el) {
3394
+ return parseVastTime(textOf(el));
3395
+ });
3396
+ return durations.length > 0 && durations.every(function(seconds) {
3397
+ return seconds === 0;
3398
+ });
3399
+ }
3384
3400
  function fetchAndParsePod(vastTagUrl) {
3401
+ var source = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "gam";
3385
3402
  return _async_to_generator(function() {
3386
- 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;
3403
+ 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;
3387
3404
  return _ts_generator(this, function(_state) {
3388
3405
  switch(_state.label){
3389
3406
  case 0:
3390
3407
  lastPodAdElementCount = 0;
3408
+ isEdge = source === "edge";
3391
3409
  return [
3392
3410
  4,
3393
- fetchVastXml(vastTagUrl)
3411
+ fetchVastXml(vastTagUrl, isEdge ? "omit" : "include", source)
3394
3412
  ];
3395
3413
  case 1:
3396
3414
  vastXml = _state.sent();
@@ -3413,7 +3431,6 @@ function createHlsAdPlayer(contentVideo, options) {
3413
3431
  }
3414
3432
  xmlDoc = parseXml(vastXml);
3415
3433
  if (!xmlDoc) {
3416
- console.error("[HlsAdPlayer] Pod VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
3417
3434
  logFunnel("vast_parsed", {
3418
3435
  adElementCount: 0,
3419
3436
  reason: "xml_parse_error"
@@ -3485,12 +3502,24 @@ function createHlsAdPlayer(contentVideo, options) {
3485
3502
  });
3486
3503
  })();
3487
3504
  };
3488
- podElements = adElements.filter(function(el) {
3505
+ candidates = adElements;
3506
+ if (isEdge) {
3507
+ candidates = adElements.filter(function(el) {
3508
+ return !isEdgeEmptySentinelAd(el);
3509
+ });
3510
+ if (candidates.length < adElements.length) {
3511
+ logFunnel("edge_empty_sentinel", {
3512
+ sentinelCount: adElements.length - candidates.length,
3513
+ adElementCount: adElements.length
3514
+ });
3515
+ }
3516
+ }
3517
+ podElements = candidates.filter(function(el) {
3489
3518
  return getAdSequence(el) !== void 0;
3490
3519
  }).sort(function(a, b) {
3491
3520
  return getAdSequence(a) - getAdSequence(b);
3492
3521
  });
3493
- buffet = adElements.filter(function(el) {
3522
+ buffet = candidates.filter(function(el) {
3494
3523
  return getAdSequence(el) === void 0;
3495
3524
  });
3496
3525
  resolveAll = function resolveAll(elements) {
@@ -3647,7 +3676,9 @@ function createHlsAdPlayer(contentVideo, options) {
3647
3676
  lastPodAdElementCount = adElements.length;
3648
3677
  return [
3649
3678
  2,
3650
- ads
3679
+ isEdge ? ads.filter(function(ad) {
3680
+ return ad.duration > 0;
3681
+ }) : ads
3651
3682
  ];
3652
3683
  }
3653
3684
  });
@@ -4648,13 +4679,14 @@ function createHlsAdPlayer(contentVideo, options) {
4648
4679
  contentVideo[AD_CONTAINER_PROP] = adContainerEl;
4649
4680
  attachContainerHandlers();
4650
4681
  },
4651
- requestAds: function requestAds(vastTagUrl) {
4682
+ requestAds: function requestAds(vastTagUrl, requestOptions) {
4652
4683
  return _async_to_generator(function() {
4653
- var ads, preloaded, error;
4684
+ var _ref, source, ads, preloaded, error;
4654
4685
  return _ts_generator(this, function(_state) {
4655
4686
  switch(_state.label){
4656
4687
  case 0:
4657
- console.log("[HlsAdPlayer] Requesting ads:", vastTagUrl);
4688
+ source = (_ref = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.source) !== null && _ref !== void 0 ? _ref : "gam";
4689
+ console.log("[HlsAdPlayer] Requesting ads (".concat(source, "):"), redactUrl(vastTagUrl));
4658
4690
  if (adPlaying) {
4659
4691
  console.warn("[HlsAdPlayer] Cannot request new ads while an ad is playing");
4660
4692
  return [
@@ -4699,7 +4731,7 @@ function createHlsAdPlayer(contentVideo, options) {
4699
4731
  case 2:
4700
4732
  return [
4701
4733
  4,
4702
- fetchAndParsePod(vastTagUrl)
4734
+ fetchAndParsePod(vastTagUrl, source)
4703
4735
  ];
4704
4736
  case 3:
4705
4737
  ads = _state.sent();
@@ -5109,6 +5141,75 @@ function createHlsAdPlayer(contentVideo, options) {
5109
5141
  return podAds.reduce(function(total, ad) {
5110
5142
  return total + (ad.duration > 0 ? ad.duration * 1e3 : 0);
5111
5143
  }, 0);
5144
+ },
5145
+ limitPodToBudget: function limitPodToBudget(maxDurationMs, maxAds) {
5146
+ if (adPlaying) return podAds.length;
5147
+ var kept = [];
5148
+ var dropped = [];
5149
+ var totalMs = 0;
5150
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
5151
+ try {
5152
+ for(var _iterator = podAds[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
5153
+ var ad = _step.value;
5154
+ var durationMs = Math.round(ad.duration * 1e3);
5155
+ if (kept.length < maxAds && totalMs + durationMs <= maxDurationMs) {
5156
+ kept.push(ad);
5157
+ totalMs += durationMs;
5158
+ } else {
5159
+ dropped.push(ad);
5160
+ }
5161
+ }
5162
+ } catch (err) {
5163
+ _didIteratorError = true;
5164
+ _iteratorError = err;
5165
+ } finally{
5166
+ try {
5167
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
5168
+ _iterator.return();
5169
+ }
5170
+ } finally{
5171
+ if (_didIteratorError) {
5172
+ throw _iteratorError;
5173
+ }
5174
+ }
5175
+ }
5176
+ if (dropped.length > 0) {
5177
+ logFunnel("pod_trimmed_to_budget", {
5178
+ keptCount: kept.length,
5179
+ droppedCount: dropped.length,
5180
+ keptDurationMs: totalMs,
5181
+ maxDurationMs: maxDurationMs,
5182
+ maxAds: maxAds
5183
+ });
5184
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
5185
+ try {
5186
+ for(var _iterator1 = dropped[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
5187
+ var ad1 = _step1.value;
5188
+ resolvedAds.add(ad1);
5189
+ fireTrackingPixels(ad1.trackingUrls.notUsed, {
5190
+ ad: ad1
5191
+ });
5192
+ }
5193
+ } catch (err) {
5194
+ _didIteratorError1 = true;
5195
+ _iteratorError1 = err;
5196
+ } finally{
5197
+ try {
5198
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
5199
+ _iterator1.return();
5200
+ }
5201
+ } finally{
5202
+ if (_didIteratorError1) {
5203
+ throw _iteratorError1;
5204
+ }
5205
+ }
5206
+ }
5207
+ }
5208
+ podAds = kept;
5209
+ podIndex = 0;
5210
+ currentAd = kept[0];
5211
+ currentAdMediaFile = void 0;
5212
+ return kept.length;
5112
5213
  }
5113
5214
  };
5114
5215
  }
@@ -9107,6 +9208,71 @@ var HlsEngine = /*#__PURE__*/ function() {
9107
9208
  ]);
9108
9209
  return HlsEngine;
9109
9210
  }();
9211
+ // src/player/EdgePodRequest.ts
9212
+ var EDGE_POD_MAX_ADS = 10;
9213
+ var EDGE_POD_EXCEEDS_BUDGET = "edge_pod_exceeds_budget";
9214
+ var LICENSE_KEY_PLACEHOLDER = /\{licenseKey\}|%7BlicenseKey%7D/gi;
9215
+ function resolveEdgePodBaseUrl(config) {
9216
+ var _config_edgePodUrl, _config_licenseKey;
9217
+ if (config.enableEdgePodRequest !== true) return void 0;
9218
+ var raw = (_config_edgePodUrl = config.edgePodUrl) === null || _config_edgePodUrl === void 0 ? void 0 : _config_edgePodUrl.trim();
9219
+ if (!raw) {
9220
+ console.warn("[AdBreak][EDGE] enableEdgePodRequest is true but edgePodUrl is missing; using GAM only");
9221
+ return void 0;
9222
+ }
9223
+ var licenseKey = (_config_licenseKey = config.licenseKey) === null || _config_licenseKey === void 0 ? void 0 : _config_licenseKey.trim();
9224
+ if (!licenseKey) {
9225
+ console.warn("[AdBreak][EDGE] enableEdgePodRequest is true but licenseKey is missing; using GAM only");
9226
+ return void 0;
9227
+ }
9228
+ var encodedKey = encodeURIComponent(licenseKey);
9229
+ try {
9230
+ var hasPlaceholder = raw.search(LICENSE_KEY_PLACEHOLDER) !== -1;
9231
+ var url = new URL(hasPlaceholder ? raw.replace(LICENSE_KEY_PLACEHOLDER, encodedKey) : raw);
9232
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
9233
+ throw new Error("unsupported protocol ".concat(url.protocol));
9234
+ }
9235
+ if (!hasPlaceholder) {
9236
+ var path = url.pathname.replace(/\/+$/, "");
9237
+ url.pathname = /\/[^/]+\/pod$/.test(path) ? path.replace(/\/[^/]+\/pod$/, "/".concat(encodedKey, "/pod")) : "".concat(path, "/").concat(encodedKey, "/pod");
9238
+ }
9239
+ return url.toString();
9240
+ } catch (unused) {
9241
+ console.warn("[AdBreak][EDGE] edgePodUrl is not a valid http(s) URL; using GAM only");
9242
+ return void 0;
9243
+ }
9244
+ }
9245
+ function buildEdgePodUrl(baseUrl, remainingMs, remainingAdLimit) {
9246
+ var url = new URL(baseUrl);
9247
+ var maxMs = Math.max(0, Math.floor(remainingMs));
9248
+ var maxAds = Math.max(1, Math.min(EDGE_POD_MAX_ADS, Math.floor(remainingAdLimit)));
9249
+ url.searchParams.set("pmxd", String(maxMs));
9250
+ url.searchParams.set("pmad", String(maxAds));
9251
+ url.searchParams.set("duration", String(Math.floor(maxMs / 1e3)));
9252
+ url.searchParams.set("count", String(maxAds));
9253
+ return url.toString();
9254
+ }
9255
+ function classifyEdgeVastResponse(result) {
9256
+ var _ref;
9257
+ var _result_error;
9258
+ if (result.error == null) {
9259
+ return result.podAdCount > 0 ? "fill" : "no_fill";
9260
+ }
9261
+ 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);
9262
+ if (/no ads available|fill rejected|no media file|no ad loaded/i.test(message) || message.includes(EDGE_POD_EXCEEDS_BUDGET)) {
9263
+ return "no_fill";
9264
+ }
9265
+ return "invalid";
9266
+ }
9267
+ function describeEdgeUrl(url) {
9268
+ try {
9269
+ var parsed = new URL(url);
9270
+ return "".concat(parsed.origin).concat(parsed.pathname);
9271
+ } catch (unused) {
9272
+ var _url_split_;
9273
+ return (_url_split_ = url.split("?")[0]) !== null && _url_split_ !== void 0 ? _url_split_ : "";
9274
+ }
9275
+ }
9110
9276
  // src/player/PlayerControls.ts
9111
9277
  function getAdAudioVolume(adPlayer) {
9112
9278
  return adPlayer.getOriginalMutedState() ? 0 : adPlayer.getOriginalVolume();
@@ -9265,6 +9431,8 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9265
9431
  this.controllerCallInFlight = false;
9266
9432
  this.playbackStartedForCurrentRequest = false;
9267
9433
  this.opportunityEpoch = -1;
9434
+ this.edgeExhaustedForBreak = false;
9435
+ this.edgeRequestsInBreak = 0;
9268
9436
  this.adPodQueue = [];
9269
9437
  this.defaultMinRemainingMsToRequestAd = 1e4;
9270
9438
  this.defaultMaxNoFillsPerBreak = 2;
@@ -9415,7 +9583,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9415
9583
  _this.timing.clearAdRequestWatchdog();
9416
9584
  _this.timing.activeAdRequestToken = null;
9417
9585
  _this.showAds = true;
9418
- _this.timing.resetGamNoFillCounter();
9586
+ if (_this.currentPodSource !== "edge") {
9587
+ _this.timing.resetGamNoFillCounter();
9588
+ }
9419
9589
  if (_this.inAdBreak && _this.timing.expectedAdBreakDurationMs != null && _this.timing.getAdBreakEndWallClockMs() == null) {
9420
9590
  _this.timing.scheduleAdStopAtBreakBoundary();
9421
9591
  if (_this.debug) {
@@ -9547,6 +9717,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9547
9717
  key: "beginVmapBreak",
9548
9718
  value: function beginVmapBreak(breakKey, position) {
9549
9719
  this.breakSource = "vmap";
9720
+ this.resetEdgeStateForBreak();
9550
9721
  this.followUpBaseVastUrl = void 0;
9551
9722
  this.unusableResponsesInBreak = 0;
9552
9723
  this.timing.totalAdRequestsInBreak = 0;
@@ -9558,7 +9729,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9558
9729
  key: "handleAdStart",
9559
9730
  value: function handleAdStart(marker) {
9560
9731
  return _async_to_generator(function() {
9561
- var baseVastUrl, adBreakDurationMs, currentMuted, currentVolume, epoch, hasPrefetchedUrl, mode, podPlayed;
9732
+ var baseVastUrl, edgeConfigured, adBreakDurationMs, currentMuted, currentVolume, epoch, hasPrefetchedUrl, mode, edgeUrl, outcome, podPlayed;
9562
9733
  return _ts_generator(this, function(_state) {
9563
9734
  switch(_state.label){
9564
9735
  case 0:
@@ -9572,7 +9743,8 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9572
9743
  ];
9573
9744
  }
9574
9745
  baseVastUrl = this.adConfig.apiVastTagUrl;
9575
- if (!baseVastUrl) {
9746
+ edgeConfigured = !!this.host.getEdgePodBaseUrl();
9747
+ if (!baseVastUrl && !edgeConfigured) {
9576
9748
  console.warn("[AdBreak] SCTE-35 break started but no direct VAST tag is configured");
9577
9749
  this.clearPendingAdBreak();
9578
9750
  return [
@@ -9588,6 +9760,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9588
9760
  this.breakSource = "scte35";
9589
9761
  this.followUpBaseVastUrl = baseVastUrl;
9590
9762
  this.unusableResponsesInBreak = 0;
9763
+ this.resetEdgeStateForBreak();
9591
9764
  this.setSlotState("NEEDS_NEXT_AD", "scte35_break_start");
9592
9765
  if (this.adConfig.podAssignedByPrefetch) {
9593
9766
  this.adConfig.podAssignedByPrefetch = false;
@@ -9609,7 +9782,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9609
9782
  this.noteOpportunity("scte35", this.cueManager.activeScte35BreakKey, "midroll");
9610
9783
  epoch = this.timing.adBreakEpoch;
9611
9784
  hasPrefetchedUrl = !!(this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0);
9612
- if (!(adBreakDurationMs == null && !hasPrefetchedUrl)) return [
9785
+ if (!(adBreakDurationMs == null && (!hasPrefetchedUrl || edgeConfigured))) return [
9613
9786
  3,
9614
9787
  2
9615
9788
  ];
@@ -9628,11 +9801,46 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9628
9801
  mode = this.host.config.isLiveStream ? "LIVE" : "VOD";
9629
9802
  console.log("[AdBreak] ".concat(mode, " break start: target duration=").concat(adBreakDurationMs != null ? "".concat(adBreakDurationMs, "ms") : "unknown"));
9630
9803
  }
9804
+ if (!edgeConfigured) return [
9805
+ 3,
9806
+ 5
9807
+ ];
9808
+ edgeUrl = this.canRequestEdge() ? this.prepareEdgePodRequest() : void 0;
9809
+ if (!edgeUrl) return [
9810
+ 3,
9811
+ 4
9812
+ ];
9813
+ this.clearPendingAdBreak();
9631
9814
  return [
9632
9815
  4,
9633
- this.startOptimizedPod(baseVastUrl, adBreakDurationMs)
9816
+ this.runEdgePod(edgeUrl, "edge_break_start")
9634
9817
  ];
9635
9818
  case 3:
9819
+ outcome = _state.sent();
9820
+ this.continueAfterEdgeOutcome(outcome, epoch);
9821
+ return [
9822
+ 2
9823
+ ];
9824
+ case 4:
9825
+ if (!this.edgeExhaustedForBreak) {
9826
+ this.markEdgeExhausted("not_eligible_at_break_start", {
9827
+ isLive: this.isLiveBreak(),
9828
+ durationMs: this.timing.expectedAdBreakDurationMs
9829
+ });
9830
+ }
9831
+ _state.label = 5;
9832
+ case 5:
9833
+ if (!baseVastUrl) {
9834
+ this.requestNextAd("no_gam_source");
9835
+ return [
9836
+ 2
9837
+ ];
9838
+ }
9839
+ return [
9840
+ 4,
9841
+ this.startOptimizedPod(baseVastUrl, adBreakDurationMs)
9842
+ ];
9843
+ case 6:
9636
9844
  podPlayed = _state.sent();
9637
9845
  if (!podPlayed && this.inAdBreak && epoch === this.timing.adBreakEpoch) {
9638
9846
  this.setSlotState("NEEDS_NEXT_AD", "initial_request_failed");
@@ -9724,6 +9932,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9724
9932
  adPlayer = this.host.getAdPlayer();
9725
9933
  requestToken = ++this.timing.adRequestTokenCounter;
9726
9934
  this.timing.activeAdRequestToken = requestToken;
9935
+ this.currentPodSource = "gam";
9727
9936
  this.setSlotState("REQUESTING", "initial_pod");
9728
9937
  this.beginFunnelRequest(adPlayer, requestToken, "initial_pod");
9729
9938
  requestUrl = this.applyOpportunityFloor(podUrl);
@@ -9840,6 +10049,224 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9840
10049
  }).call(this);
9841
10050
  }
9842
10051
  },
10052
+ {
10053
+ // ───────────────────────────────────────────────────────────────
10054
+ // Edge-first pods (live SCTE-35 only, GAM fallback)
10055
+ // ───────────────────────────────────────────────────────────────
10056
+ key: "resetEdgeStateForBreak",
10057
+ value: function resetEdgeStateForBreak() {
10058
+ this.edgeExhaustedForBreak = false;
10059
+ this.edgeRequestsInBreak = 0;
10060
+ this.currentPodSource = void 0;
10061
+ }
10062
+ },
10063
+ {
10064
+ key: "isLiveBreak",
10065
+ value: function isLiveBreak() {
10066
+ return this.host.isLiveStream() || this.host.config.isLiveStream === true;
10067
+ }
10068
+ },
10069
+ {
10070
+ key: "canRequestEdge",
10071
+ value: function canRequestEdge() {
10072
+ return this.breakSource === "scte35" && !this.edgeExhaustedForBreak && !!this.host.getEdgePodBaseUrl() && this.isLiveBreak() && this.timing.expectedAdBreakDurationMs != null && this.edgeRequestsInBreak < this.timing.maxTotalAdRequestsPerBreak;
10073
+ }
10074
+ },
10075
+ {
10076
+ key: "markEdgeExhausted",
10077
+ value: function markEdgeExhausted(reason) {
10078
+ var extra = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
10079
+ this.edgeExhaustedForBreak = true;
10080
+ this.countFunnelStage("edge_fallback:".concat(reason));
10081
+ this.logOrchestratorFunnel("edge_exhausted", _object_spread({
10082
+ reason: reason,
10083
+ edgeRequests: this.edgeRequestsInBreak,
10084
+ remainingMs: this.timing.getRemainingAdMs()
10085
+ }, extra));
10086
+ }
10087
+ },
10088
+ {
10089
+ /**
10090
+ * Builds the next Edge request from the budget left right now, or marks Edge
10091
+ * exhausted for this break. Synchronous on purpose: callers must reach the
10092
+ * REQUESTING state in the same tick so a second completion event cannot race
10093
+ * in a parallel request.
10094
+ */ key: "prepareEdgePodRequest",
10095
+ value: function prepareEdgePodRequest() {
10096
+ var baseUrl = this.host.getEdgePodBaseUrl();
10097
+ if (!baseUrl) return void 0;
10098
+ var remainingMs = this.timing.getRemainingAdMs();
10099
+ var remainingAds = Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolvePodParams().maxAds - this.timing.totalAdsInBreak);
10100
+ if (remainingAds < 1) {
10101
+ this.markEdgeExhausted("ad_capacity_reached", {
10102
+ adsInBreak: this.timing.totalAdsInBreak
10103
+ });
10104
+ return void 0;
10105
+ }
10106
+ if (remainingMs < this.getMinRemainingMsToRequestAd()) {
10107
+ this.markEdgeExhausted("insufficient_break_time", {
10108
+ remainingMs: remainingMs
10109
+ });
10110
+ return void 0;
10111
+ }
10112
+ try {
10113
+ return buildEdgePodUrl(baseUrl, remainingMs, remainingAds);
10114
+ } catch (unused) {
10115
+ this.markEdgeExhausted("invalid_edge_url");
10116
+ return void 0;
10117
+ }
10118
+ }
10119
+ },
10120
+ {
10121
+ key: "runEdgePod",
10122
+ value: function runEdgePod(requestUrl, trigger) {
10123
+ return _async_to_generator(function() {
10124
+ var _params_get, _params_get1, epoch, generation, adPlayer, requestToken, params, _ref, _adPlayer_getPodAdCount, _adPlayer_getPodTotalDurationMs, remainingMs, remainingAds, podCount, error, errorMessage, classification, diag;
10125
+ return _ts_generator(this, function(_state) {
10126
+ switch(_state.label){
10127
+ case 0:
10128
+ epoch = this.timing.adBreakEpoch;
10129
+ this.recreateAdController("new_request");
10130
+ generation = this.controllerGeneration;
10131
+ adPlayer = this.host.getAdPlayer();
10132
+ requestToken = ++this.timing.adRequestTokenCounter;
10133
+ this.timing.activeAdRequestToken = requestToken;
10134
+ this.currentPodSource = "edge";
10135
+ this.edgeRequestsInBreak++;
10136
+ this.setSlotState("REQUESTING", trigger);
10137
+ this.beginFunnelRequest(adPlayer, requestToken, trigger, "edge");
10138
+ this.currentVastUrl = requestUrl;
10139
+ params = new URL(requestUrl).searchParams;
10140
+ this.logOrchestratorFunnel("edge_request_sent", {
10141
+ trigger: trigger,
10142
+ attempt: this.edgeRequestsInBreak,
10143
+ endpoint: describeEdgeUrl(requestUrl),
10144
+ pmxd: (_params_get = params.get("pmxd")) !== null && _params_get !== void 0 ? _params_get : void 0,
10145
+ pmad: (_params_get1 = params.get("pmad")) !== null && _params_get1 !== void 0 ? _params_get1 : void 0
10146
+ });
10147
+ _state.label = 1;
10148
+ case 1:
10149
+ _state.trys.push([
10150
+ 1,
10151
+ 4,
10152
+ ,
10153
+ 5
10154
+ ]);
10155
+ this.timing.startAdRequestWatchdog(requestToken);
10156
+ return [
10157
+ 4,
10158
+ this.callController(function() {
10159
+ return adPlayer.requestAds(requestUrl, {
10160
+ source: "edge"
10161
+ });
10162
+ })
10163
+ ];
10164
+ case 2:
10165
+ _state.sent();
10166
+ this.timing.clearAdRequestWatchdog();
10167
+ if (this.isStale(epoch, generation)) {
10168
+ this.logOrchestratorFunnel("stale_request_result_ignored", {
10169
+ requestId: requestToken,
10170
+ source: "edge"
10171
+ });
10172
+ return [
10173
+ 2,
10174
+ "stale"
10175
+ ];
10176
+ }
10177
+ remainingMs = this.timing.getRemainingAdMs();
10178
+ remainingAds = Math.max(1, Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolvePodParams().maxAds - this.timing.totalAdsInBreak));
10179
+ 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;
10180
+ if (classifyEdgeVastResponse({
10181
+ podAdCount: podCount
10182
+ }) !== "fill") {
10183
+ throw new Error("".concat(EDGE_POD_EXCEEDS_BUDGET, ": no Edge ad fits ").concat(remainingMs, "ms"));
10184
+ }
10185
+ this.setSlotState("READY", "edge_vast_ready");
10186
+ this.logOrchestratorFunnel("edge_fill", {
10187
+ podAdCount: podCount,
10188
+ podDurationMs: (_adPlayer_getPodTotalDurationMs = adPlayer.getPodTotalDurationMs) === null || _adPlayer_getPodTotalDurationMs === void 0 ? void 0 : _adPlayer_getPodTotalDurationMs.call(adPlayer),
10189
+ remainingMs: remainingMs
10190
+ });
10191
+ sendAdLoadedTracking(this.host.config.licenseKey, {
10192
+ source: "hls",
10193
+ vastUrl: requestUrl,
10194
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
10195
+ }, this.analyticsContext).catch(function() {});
10196
+ this.timing.startAdFailsafeTimer(requestToken);
10197
+ return [
10198
+ 4,
10199
+ this.callController(function() {
10200
+ return adPlayer.play();
10201
+ })
10202
+ ];
10203
+ case 3:
10204
+ _state.sent();
10205
+ if (this.isStale(epoch, generation)) return [
10206
+ 2,
10207
+ "stale"
10208
+ ];
10209
+ if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {
10210
+ this.timing.scheduleAdStopAtBreakBoundary();
10211
+ }
10212
+ adPlayer.setAdVolume(getAdAudioVolume(adPlayer));
10213
+ return [
10214
+ 2,
10215
+ "fill"
10216
+ ];
10217
+ case 4:
10218
+ error = _state.sent();
10219
+ this.timing.clearAdRequestWatchdog();
10220
+ this.timing.clearAdFailsafeTimer();
10221
+ if (this.timing.activeAdRequestToken === requestToken) {
10222
+ this.timing.activeAdRequestToken = null;
10223
+ }
10224
+ errorMessage = error === null || error === void 0 ? void 0 : error.message;
10225
+ if (this.isStale(epoch, generation)) {
10226
+ this.logOrchestratorFunnel("stale_request_result_ignored", {
10227
+ requestId: requestToken,
10228
+ source: "edge",
10229
+ errorMessage: errorMessage
10230
+ });
10231
+ return [
10232
+ 2,
10233
+ "stale"
10234
+ ];
10235
+ }
10236
+ classification = classifyEdgeVastResponse({
10237
+ podAdCount: 0,
10238
+ error: error
10239
+ });
10240
+ diag = this.requestDiagnostics.get(requestToken);
10241
+ if (diag && !diag.failureReason) diag.failureReason = "edge_".concat(classification, ": ").concat(errorMessage);
10242
+ this.markEdgeExhausted("edge_".concat(classification), {
10243
+ errorMessage: errorMessage
10244
+ });
10245
+ return [
10246
+ 2,
10247
+ "fallback"
10248
+ ];
10249
+ case 5:
10250
+ return [
10251
+ 2
10252
+ ];
10253
+ }
10254
+ });
10255
+ }).call(this);
10256
+ }
10257
+ },
10258
+ {
10259
+ key: "continueAfterEdgeOutcome",
10260
+ value: function continueAfterEdgeOutcome(outcome, epoch) {
10261
+ if (outcome !== "fallback") return;
10262
+ if (!this.inAdBreak || epoch !== this.timing.adBreakEpoch) return;
10263
+ if (this.debug) {
10264
+ console.log("[AdBreak][EDGE] No usable Edge pod; checking with GAM for the remaining break");
10265
+ }
10266
+ this.setSlotState("NEEDS_NEXT_AD", "edge_fallback");
10267
+ this.requestNextAd("edge_fallback");
10268
+ }
10269
+ },
9843
10270
  {
9844
10271
  // ───────────────────────────────────────────────────────────────
9845
10272
  // Next-ad scheduling (single flight)
@@ -9895,7 +10322,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9895
10322
  value: function getStopRequestingReason(remainingMs) {
9896
10323
  if (this.breakSource === "vmap") {
9897
10324
  if (this.adPodQueue.length === 0) return "vmap_queue_empty";
9898
- } else if (this.breakSource !== "scte35" || !this.followUpBaseVastUrl) {
10325
+ } else if (this.breakSource !== "scte35" || !this.followUpBaseVastUrl && !this.canRequestEdge()) {
9899
10326
  return "no_follow_up_source";
9900
10327
  }
9901
10328
  if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {
@@ -9907,7 +10334,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9907
10334
  if (this.timing.totalAdRequestsInBreak >= this.timing.maxTotalAdRequestsPerBreak) {
9908
10335
  return "request_cap";
9909
10336
  }
9910
- if (this.timing.isGamInCooldown()) {
10337
+ if (!this.canRequestEdge() && this.timing.isGamInCooldown()) {
9911
10338
  return "gam_cooldown";
9912
10339
  }
9913
10340
  if (this.isBreakTimeBounded() && remainingMs < this.getMinRemainingMsToRequestAd()) {
@@ -10001,10 +10428,33 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10001
10428
  key: "requestFollowUpAd",
10002
10429
  value: function requestFollowUpAd(trigger) {
10003
10430
  return _async_to_generator(function() {
10004
- var url, epoch, unused;
10431
+ var edgeUrl, epoch2, outcome, url, epoch, unused;
10005
10432
  return _ts_generator(this, function(_state) {
10006
10433
  switch(_state.label){
10007
10434
  case 0:
10435
+ if (!this.canRequestEdge()) return [
10436
+ 3,
10437
+ 2
10438
+ ];
10439
+ edgeUrl = this.prepareEdgePodRequest();
10440
+ if (!edgeUrl) {
10441
+ this.requestNextAd("".concat(trigger, ":edge_unavailable"));
10442
+ return [
10443
+ 2
10444
+ ];
10445
+ }
10446
+ epoch2 = this.timing.adBreakEpoch;
10447
+ return [
10448
+ 4,
10449
+ this.runEdgePod(edgeUrl, "edge_".concat(trigger))
10450
+ ];
10451
+ case 1:
10452
+ outcome = _state.sent();
10453
+ this.continueAfterEdgeOutcome(outcome, epoch2);
10454
+ return [
10455
+ 2
10456
+ ];
10457
+ case 2:
10008
10458
  if (this.breakSource === "vmap") {
10009
10459
  url = this.adPodQueue.shift();
10010
10460
  } else if (this.followUpBaseVastUrl) {
@@ -10015,32 +10465,32 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10015
10465
  ];
10016
10466
  this.noteVastUrlGenerated(ensureVideoAdType(url), trigger);
10017
10467
  epoch = this.timing.adBreakEpoch;
10018
- _state.label = 1;
10019
- case 1:
10468
+ _state.label = 3;
10469
+ case 3:
10020
10470
  _state.trys.push([
10021
- 1,
10022
10471
  3,
10472
+ 5,
10023
10473
  ,
10024
- 4
10474
+ 6
10025
10475
  ]);
10026
10476
  return [
10027
10477
  4,
10028
10478
  this.playSingleAd(url, trigger)
10029
10479
  ];
10030
- case 2:
10480
+ case 4:
10031
10481
  _state.sent();
10032
10482
  return [
10033
10483
  3,
10034
- 4
10484
+ 6
10035
10485
  ];
10036
- case 3:
10486
+ case 5:
10037
10487
  unused = _state.sent();
10038
10488
  this.continueAfterRequestFailure(epoch);
10039
10489
  return [
10040
10490
  3,
10041
- 4
10491
+ 6
10042
10492
  ];
10043
- case 4:
10493
+ case 6:
10044
10494
  return [
10045
10495
  2
10046
10496
  ];
@@ -10153,7 +10603,11 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10153
10603
  case "gam_http_request_sent":
10154
10604
  diag.gamRequestSent++;
10155
10605
  break;
10606
+ case "edge_http_request_sent":
10607
+ diag.edgeRequestSent++;
10608
+ break;
10156
10609
  case "gam_response_received":
10610
+ case "edge_response_received":
10157
10611
  diag.vastHttpStatus = payload.httpStatus;
10158
10612
  break;
10159
10613
  case "vast_parsed":
@@ -10340,6 +10794,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10340
10794
  {
10341
10795
  key: "beginFunnelRequest",
10342
10796
  value: function beginFunnelRequest(adPlayer, requestToken, trigger) {
10797
+ var source = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : "gam";
10343
10798
  var _adPlayer_setFunnelContext;
10344
10799
  if (this.controllerCallInFlight) {
10345
10800
  this.logOrchestratorFunnel("duplicate_request_detected", {
@@ -10354,7 +10809,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10354
10809
  requestId: requestToken,
10355
10810
  controllerId: this.controllerGeneration,
10356
10811
  trigger: trigger,
10812
+ source: source,
10357
10813
  gamRequestSent: 0,
10814
+ edgeRequestSent: 0,
10358
10815
  wrapperDepth: 0,
10359
10816
  inlineResolved: false,
10360
10817
  mediaCandidateCount: 0,
@@ -10485,6 +10942,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10485
10942
  this.timing.activeAdRequestToken = requestToken;
10486
10943
  ap = this.host.getAdPlayer();
10487
10944
  budgetedUrl = this.withCurrentPodBudget(vastTagUrl);
10945
+ this.currentPodSource = "gam";
10488
10946
  this.setSlotState("REQUESTING", trigger);
10489
10947
  this.beginFunnelRequest(ap, requestToken, trigger);
10490
10948
  requestUrl = this.applyOpportunityFloor(budgetedUrl);
@@ -10632,6 +11090,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10632
11090
  requests: requests,
10633
11091
  requestRetries: requestRetries,
10634
11092
  gamResponses: count("gam_response_received"),
11093
+ edgeRequests: count("edge_request_sent"),
11094
+ edgeFills: count("edge_fill"),
11095
+ edgeEmptySentinels: count("edge_empty_sentinel"),
11096
+ edgeFallbacks: countPrefix("edge_fallback:"),
10635
11097
  requestsSuppressed: count("request_suppressed"),
10636
11098
  duplicates: count("duplicate_request_detected") + count("duplicate_break_start"),
10637
11099
  filled: count("vast_received"),
@@ -10728,6 +11190,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10728
11190
  this.breakSource = void 0;
10729
11191
  this.followUpBaseVastUrl = void 0;
10730
11192
  this.unusableResponsesInBreak = 0;
11193
+ this.resetEdgeStateForBreak();
10731
11194
  adPlayer.stop().catch(function() {});
10732
11195
  if (!alreadyEnded) this.logBreakFunnel(reason);
10733
11196
  this.opportunityFloor = void 0;
@@ -11041,7 +11504,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11041
11504
  });
11042
11505
  return;
11043
11506
  }
11044
- this.timing.consecutiveFailures++;
11507
+ if (this.currentPodSource === "edge") {
11508
+ this.markEdgeExhausted("edge_playback_failed", {
11509
+ reason: reason
11510
+ });
11511
+ } else {
11512
+ this.timing.consecutiveFailures++;
11513
+ }
11045
11514
  var diag = this.currentRequestId != null ? this.requestDiagnostics.get(this.currentRequestId) : void 0;
11046
11515
  if (diag && !diag.failureReason) diag.failureReason = reason;
11047
11516
  if (this.debug) {
@@ -11071,7 +11540,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11071
11540
  if (this.config.adFloorMaxCents != null) floorBounds.maxCents = this.config.adFloorMaxCents;
11072
11541
  if (this.config.adFloorStepCents != null) floorBounds.stepCents = this.config.adFloorStepCents;
11073
11542
  this.floorLadder = new FloorLadderController(this.config.adFloorLadder, floorBounds);
11543
+ this.floorLadderEnabled = this.config.adFloorLadderEnabled === true;
11074
11544
  this.warnOnInvalidFloorLadder(this.floorLadder.validate());
11545
+ this.edgePodBaseUrl = resolveEdgePodBaseUrl(this.config);
11075
11546
  this.adPlayer = this.createAdPlayer(false);
11076
11547
  this.palNonce = createPalNonceManager();
11077
11548
  this.cueManager = new Scte35CueManager(!!this.config.debugAdTiming, {
@@ -11171,11 +11642,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11171
11642
  generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
11172
11643
  return _this.generatePodVastUrl(base, breakDurationMs);
11173
11644
  },
11645
+ getEdgePodBaseUrl: function getEdgePodBaseUrl() {
11646
+ return _this.edgePodBaseUrl;
11647
+ },
11174
11648
  getFloorSnapshot: function getFloorSnapshot(position) {
11175
- return _this.floorLadder.snapshotFor({
11649
+ return _this.floorLadderEnabled ? _this.floorLadder.snapshotFor({
11176
11650
  position: position,
11177
11651
  isCtv: _this.isCtvEnvironment()
11178
- });
11652
+ }) : void 0;
11179
11653
  },
11180
11654
  onAdClick: function onAdClick() {
11181
11655
  return _this.palNonce.sendAdClick();
@@ -11226,11 +11700,43 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11226
11700
  return report;
11227
11701
  }
11228
11702
  },
11703
+ {
11704
+ key: "setAdFloorLadderEnabled",
11705
+ value: function setAdFloorLadderEnabled(enabled) {
11706
+ this.floorLadderEnabled = enabled;
11707
+ if (enabled) this.warnOnInvalidFloorLadder(this.floorLadder.validate());
11708
+ }
11709
+ },
11710
+ {
11711
+ key: "isAdFloorLadderEnabled",
11712
+ value: function isAdFloorLadderEnabled() {
11713
+ return this.floorLadderEnabled;
11714
+ }
11715
+ },
11716
+ {
11717
+ key: "setEdgePodRequest",
11718
+ value: function setEdgePodRequest(update) {
11719
+ if (update.enableEdgePodRequest === this.config.enableEdgePodRequest && update.edgePodUrl === this.config.edgePodUrl) {
11720
+ return;
11721
+ }
11722
+ if (update.enableEdgePodRequest === void 0) delete this.config.enableEdgePodRequest;
11723
+ else this.config.enableEdgePodRequest = update.enableEdgePodRequest;
11724
+ if (update.edgePodUrl === void 0) delete this.config.edgePodUrl;
11725
+ else this.config.edgePodUrl = update.edgePodUrl;
11726
+ this.edgePodBaseUrl = resolveEdgePodBaseUrl(this.config);
11727
+ }
11728
+ },
11729
+ {
11730
+ key: "getEdgePodUrl",
11731
+ value: function getEdgePodUrl() {
11732
+ return this.edgePodBaseUrl;
11733
+ }
11734
+ },
11229
11735
  {
11230
11736
  key: "warnOnInvalidFloorLadder",
11231
11737
  value: function warnOnInvalidFloorLadder(report) {
11232
11738
  var config = this.floorLadder.get();
11233
- if (report.ok || !config.enabled) return;
11739
+ if (report.ok || !this.floorLadderEnabled || !config.enabled) return;
11234
11740
  console.warn("[AdBreak][FLOOR] configuration has issues; invalid floors will not be sent", {
11235
11741
  errors: report.errors,
11236
11742
  configurationVersion: config.configurationVersion,
@@ -11963,6 +12469,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11963
12469
  this.timing.destroy();
11964
12470
  this.adBreak.clearPendingAdBreak();
11965
12471
  this.placeholder.destroy();
12472
+ 0;
11966
12473
  if (this.timeUpdateHandler) {
11967
12474
  this.video.removeEventListener("timeupdate", this.timeUpdateHandler);
11968
12475
  delete this.timeUpdateHandler;
@@ -12068,7 +12575,7 @@ var CRITICAL_PROPS = [
12068
12575
  var CONTROLS_HIDE_DELAY = 3e3;
12069
12576
  var DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;
12070
12577
  var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12071
- 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, [
12578
+ 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, [
12072
12579
  "src",
12073
12580
  "autoplay",
12074
12581
  "muted",
@@ -12105,10 +12612,13 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12105
12612
  "minRemainingMsToStartAd",
12106
12613
  "minRemainingMsToRequestAd",
12107
12614
  "maxNoFillsPerBreak",
12615
+ "adFloorLadderEnabled",
12108
12616
  "adFloorLadder",
12109
12617
  "adFloorMinCents",
12110
12618
  "adFloorMaxCents",
12111
- "adFloorStepCents"
12619
+ "adFloorStepCents",
12620
+ "enableEdgePodRequest",
12621
+ "edgePodUrl"
12112
12622
  ]);
12113
12623
  var adFloorLadderKey = JSON.stringify(adFloorLadder !== null && adFloorLadder !== void 0 ? adFloorLadder : null);
12114
12624
  var videoRef = (0, import_react.useRef)(null);
@@ -12309,10 +12819,13 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12309
12819
  if (minRemainingMsToStartAd !== void 0) cfg.minRemainingMsToStartAd = minRemainingMsToStartAd;
12310
12820
  if (minRemainingMsToRequestAd !== void 0) cfg.minRemainingMsToRequestAd = minRemainingMsToRequestAd;
12311
12821
  if (maxNoFillsPerBreak !== void 0) cfg.maxNoFillsPerBreak = maxNoFillsPerBreak;
12822
+ if (adFloorLadderEnabled !== void 0) cfg.adFloorLadderEnabled = adFloorLadderEnabled;
12312
12823
  if (adFloorLadder !== void 0) cfg.adFloorLadder = adFloorLadder;
12313
12824
  if (adFloorMinCents !== void 0) cfg.adFloorMinCents = adFloorMinCents;
12314
12825
  if (adFloorMaxCents !== void 0) cfg.adFloorMaxCents = adFloorMaxCents;
12315
12826
  if (adFloorStepCents !== void 0) cfg.adFloorStepCents = adFloorStepCents;
12827
+ if (enableEdgePodRequest !== void 0) cfg.enableEdgePodRequest = enableEdgePodRequest;
12828
+ if (edgePodUrl !== void 0) cfg.edgePodUrl = edgePodUrl;
12316
12829
  var player = new StormcloudVideoPlayer(cfg);
12317
12830
  playerRef.current = player;
12318
12831
  appliedFloorLadderKeyRef.current = adFloorLadderKey;
@@ -12361,6 +12874,25 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12361
12874
  }, [
12362
12875
  adFloorLadderKey
12363
12876
  ]);
12877
+ (0, import_react.useEffect)(function() {
12878
+ if (!playerRef.current) return;
12879
+ var enabled = adFloorLadderEnabled === true;
12880
+ if (playerRef.current.isAdFloorLadderEnabled() === enabled) return;
12881
+ playerRef.current.setAdFloorLadderEnabled(enabled);
12882
+ }, [
12883
+ adFloorLadderEnabled
12884
+ ]);
12885
+ (0, import_react.useEffect)(function() {
12886
+ if (!playerRef.current) return;
12887
+ playerRef.current.setEdgePodRequest(_object_spread({}, enableEdgePodRequest !== void 0 ? {
12888
+ enableEdgePodRequest: enableEdgePodRequest
12889
+ } : {}, edgePodUrl !== void 0 ? {
12890
+ edgePodUrl: edgePodUrl
12891
+ } : {}));
12892
+ }, [
12893
+ enableEdgePodRequest,
12894
+ edgePodUrl
12895
+ ]);
12364
12896
  (0, import_react.useEffect)(function() {
12365
12897
  if (!playerRef.current) return;
12366
12898
  var checkAdStatus = function checkAdStatus() {
@@ -13437,6 +13969,9 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
13437
13969
  }
13438
13970
  }
13439
13971
  }
13972
+ if (prevProps.adFloorLadderEnabled !== nextProps.adFloorLadderEnabled || prevProps.enableEdgePodRequest !== nextProps.enableEdgePodRequest || prevProps.edgePodUrl !== nextProps.edgePodUrl) {
13973
+ return false;
13974
+ }
13440
13975
  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)) {
13441
13976
  return false;
13442
13977
  }