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.cjs CHANGED
@@ -2700,7 +2700,7 @@ function createHlsAdPlayer(contentVideo, options) {
2700
2700
  img.onload = null;
2701
2701
  img.onerror = null;
2702
2702
  inFlightBeacons.delete(img);
2703
- console.log("[HlsAdPlayer] Tracking pixel settled (".concat(outcome, "): ").concat(trackingUrl));
2703
+ console.log("[HlsAdPlayer] Tracking pixel settled (".concat(outcome, "): ").concat(trackingHost));
2704
2704
  if (outcome !== "load") {
2705
2705
  logFunnel("tracking_request_settled", {
2706
2706
  reason: outcome,
@@ -2718,7 +2718,7 @@ function createHlsAdPlayer(contentVideo, options) {
2718
2718
  return release("timeout");
2719
2719
  }, BEACON_TIMEOUT_MS);
2720
2720
  img.src = trackingUrl;
2721
- console.log("[HlsAdPlayer] Fired tracking pixel: ".concat(trackingUrl));
2721
+ console.log("[HlsAdPlayer] Fired tracking pixel: ".concat(trackingHost));
2722
2722
  logFunnel("tracking_request_created", {
2723
2723
  trackingHost: trackingHost,
2724
2724
  errorCode: options2 === null || options2 === void 0 ? void 0 : options2.errorCode
@@ -3172,7 +3172,7 @@ function createHlsAdPlayer(contentVideo, options) {
3172
3172
  });
3173
3173
  }
3174
3174
  if (parsed.type === "wrapper") {
3175
- console.log("[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ".concat(parsed.vastAdTagUri));
3175
+ console.log("[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ".concat(redactUrl(parsed.vastAdTagUri)));
3176
3176
  }
3177
3177
  return parsed;
3178
3178
  }
@@ -3364,8 +3364,8 @@ function createHlsAdPlayer(contentVideo, options) {
3364
3364
  switch(_state.label){
3365
3365
  case 0:
3366
3366
  attempt++;
3367
- if (kind === "gam") {
3368
- logFunnel("gam_http_request_sent", {
3367
+ if (kind !== "wrapper") {
3368
+ logFunnel("".concat(kind, "_http_request_sent"), {
3369
3369
  attempt: attempt,
3370
3370
  credentials: creds
3371
3371
  });
@@ -3385,8 +3385,8 @@ function createHlsAdPlayer(contentVideo, options) {
3385
3385
  ];
3386
3386
  case 1:
3387
3387
  response = _state.sent();
3388
- if (kind === "gam") {
3389
- logFunnel("gam_response_received", {
3388
+ if (kind !== "wrapper") {
3389
+ logFunnel("".concat(kind, "_response_received"), {
3390
3390
  attempt: attempt,
3391
3391
  httpStatus: response.status,
3392
3392
  ok: response.ok,
@@ -3556,8 +3556,7 @@ function createHlsAdPlayer(contentVideo, options) {
3556
3556
  elapsedMs: Date.now() - fetchStartedAt
3557
3557
  });
3558
3558
  }
3559
- console.log("[HlsAdPlayer] VAST XML received");
3560
- console.log("[HlsAdPlayer] VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
3559
+ console.log("[HlsAdPlayer] VAST XML received (length=".concat(vastXml.length, ")"));
3561
3560
  parsed = parseVastXml(vastXml);
3562
3561
  if (parsed.type === "empty") {
3563
3562
  ;
@@ -3598,16 +3597,35 @@ function createHlsAdPlayer(contentVideo, options) {
3598
3597
  });
3599
3598
  }).apply(this, arguments);
3600
3599
  }
3600
+ function isEdgeEmptySentinelAd(adElement) {
3601
+ var _textOf;
3602
+ if ((adElement.getAttribute("id") || "").trim().toLowerCase() === "empty") {
3603
+ return true;
3604
+ }
3605
+ var inLine = adElement.querySelector(":scope > InLine");
3606
+ if (!inLine) return false;
3607
+ if (/^no ad available$/i.test((_textOf = textOf(inLine.querySelector(":scope > AdTitle"))) !== null && _textOf !== void 0 ? _textOf : "")) {
3608
+ return true;
3609
+ }
3610
+ var durations = Array.from(inLine.querySelectorAll(":scope > Creatives > Creative > Linear > Duration")).map(function(el) {
3611
+ return parseVastTime(textOf(el));
3612
+ });
3613
+ return durations.length > 0 && durations.every(function(seconds) {
3614
+ return seconds === 0;
3615
+ });
3616
+ }
3601
3617
  function fetchAndParsePod(vastTagUrl) {
3618
+ var source = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "gam";
3602
3619
  return _async_to_generator(function() {
3603
- 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;
3620
+ 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;
3604
3621
  return _ts_generator(this, function(_state) {
3605
3622
  switch(_state.label){
3606
3623
  case 0:
3607
3624
  lastPodAdElementCount = 0;
3625
+ isEdge = source === "edge";
3608
3626
  return [
3609
3627
  4,
3610
- fetchVastXml(vastTagUrl)
3628
+ fetchVastXml(vastTagUrl, isEdge ? "omit" : "include", source)
3611
3629
  ];
3612
3630
  case 1:
3613
3631
  vastXml = _state.sent();
@@ -3630,7 +3648,6 @@ function createHlsAdPlayer(contentVideo, options) {
3630
3648
  }
3631
3649
  xmlDoc = parseXml(vastXml);
3632
3650
  if (!xmlDoc) {
3633
- console.error("[HlsAdPlayer] Pod VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
3634
3651
  logFunnel("vast_parsed", {
3635
3652
  adElementCount: 0,
3636
3653
  reason: "xml_parse_error"
@@ -3702,12 +3719,24 @@ function createHlsAdPlayer(contentVideo, options) {
3702
3719
  });
3703
3720
  })();
3704
3721
  };
3705
- podElements = adElements.filter(function(el) {
3722
+ candidates = adElements;
3723
+ if (isEdge) {
3724
+ candidates = adElements.filter(function(el) {
3725
+ return !isEdgeEmptySentinelAd(el);
3726
+ });
3727
+ if (candidates.length < adElements.length) {
3728
+ logFunnel("edge_empty_sentinel", {
3729
+ sentinelCount: adElements.length - candidates.length,
3730
+ adElementCount: adElements.length
3731
+ });
3732
+ }
3733
+ }
3734
+ podElements = candidates.filter(function(el) {
3706
3735
  return getAdSequence(el) !== void 0;
3707
3736
  }).sort(function(a, b) {
3708
3737
  return getAdSequence(a) - getAdSequence(b);
3709
3738
  });
3710
- buffet = adElements.filter(function(el) {
3739
+ buffet = candidates.filter(function(el) {
3711
3740
  return getAdSequence(el) === void 0;
3712
3741
  });
3713
3742
  resolveAll = function resolveAll(elements) {
@@ -3864,7 +3893,9 @@ function createHlsAdPlayer(contentVideo, options) {
3864
3893
  lastPodAdElementCount = adElements.length;
3865
3894
  return [
3866
3895
  2,
3867
- ads
3896
+ isEdge ? ads.filter(function(ad) {
3897
+ return ad.duration > 0;
3898
+ }) : ads
3868
3899
  ];
3869
3900
  }
3870
3901
  });
@@ -4865,13 +4896,14 @@ function createHlsAdPlayer(contentVideo, options) {
4865
4896
  contentVideo[AD_CONTAINER_PROP] = adContainerEl;
4866
4897
  attachContainerHandlers();
4867
4898
  },
4868
- requestAds: function requestAds(vastTagUrl) {
4899
+ requestAds: function requestAds(vastTagUrl, requestOptions) {
4869
4900
  return _async_to_generator(function() {
4870
- var ads, preloaded, error;
4901
+ var _ref, source, ads, preloaded, error;
4871
4902
  return _ts_generator(this, function(_state) {
4872
4903
  switch(_state.label){
4873
4904
  case 0:
4874
- console.log("[HlsAdPlayer] Requesting ads:", vastTagUrl);
4905
+ source = (_ref = requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.source) !== null && _ref !== void 0 ? _ref : "gam";
4906
+ console.log("[HlsAdPlayer] Requesting ads (".concat(source, "):"), redactUrl(vastTagUrl));
4875
4907
  if (adPlaying) {
4876
4908
  console.warn("[HlsAdPlayer] Cannot request new ads while an ad is playing");
4877
4909
  return [
@@ -4916,7 +4948,7 @@ function createHlsAdPlayer(contentVideo, options) {
4916
4948
  case 2:
4917
4949
  return [
4918
4950
  4,
4919
- fetchAndParsePod(vastTagUrl)
4951
+ fetchAndParsePod(vastTagUrl, source)
4920
4952
  ];
4921
4953
  case 3:
4922
4954
  ads = _state.sent();
@@ -5326,6 +5358,75 @@ function createHlsAdPlayer(contentVideo, options) {
5326
5358
  return podAds.reduce(function(total, ad) {
5327
5359
  return total + (ad.duration > 0 ? ad.duration * 1e3 : 0);
5328
5360
  }, 0);
5361
+ },
5362
+ limitPodToBudget: function limitPodToBudget(maxDurationMs, maxAds) {
5363
+ if (adPlaying) return podAds.length;
5364
+ var kept = [];
5365
+ var dropped = [];
5366
+ var totalMs = 0;
5367
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
5368
+ try {
5369
+ for(var _iterator = podAds[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
5370
+ var ad = _step.value;
5371
+ var durationMs = Math.round(ad.duration * 1e3);
5372
+ if (kept.length < maxAds && totalMs + durationMs <= maxDurationMs) {
5373
+ kept.push(ad);
5374
+ totalMs += durationMs;
5375
+ } else {
5376
+ dropped.push(ad);
5377
+ }
5378
+ }
5379
+ } catch (err) {
5380
+ _didIteratorError = true;
5381
+ _iteratorError = err;
5382
+ } finally{
5383
+ try {
5384
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
5385
+ _iterator.return();
5386
+ }
5387
+ } finally{
5388
+ if (_didIteratorError) {
5389
+ throw _iteratorError;
5390
+ }
5391
+ }
5392
+ }
5393
+ if (dropped.length > 0) {
5394
+ logFunnel("pod_trimmed_to_budget", {
5395
+ keptCount: kept.length,
5396
+ droppedCount: dropped.length,
5397
+ keptDurationMs: totalMs,
5398
+ maxDurationMs: maxDurationMs,
5399
+ maxAds: maxAds
5400
+ });
5401
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
5402
+ try {
5403
+ for(var _iterator1 = dropped[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
5404
+ var ad1 = _step1.value;
5405
+ resolvedAds.add(ad1);
5406
+ fireTrackingPixels(ad1.trackingUrls.notUsed, {
5407
+ ad: ad1
5408
+ });
5409
+ }
5410
+ } catch (err) {
5411
+ _didIteratorError1 = true;
5412
+ _iteratorError1 = err;
5413
+ } finally{
5414
+ try {
5415
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
5416
+ _iterator1.return();
5417
+ }
5418
+ } finally{
5419
+ if (_didIteratorError1) {
5420
+ throw _iteratorError1;
5421
+ }
5422
+ }
5423
+ }
5424
+ }
5425
+ podAds = kept;
5426
+ podIndex = 0;
5427
+ currentAd = kept[0];
5428
+ currentAdMediaFile = void 0;
5429
+ return kept.length;
5329
5430
  }
5330
5431
  };
5331
5432
  }
@@ -9330,6 +9431,71 @@ var HlsEngine = /*#__PURE__*/ function() {
9330
9431
  ]);
9331
9432
  return HlsEngine;
9332
9433
  }();
9434
+ // src/player/EdgePodRequest.ts
9435
+ var EDGE_POD_MAX_ADS = 10;
9436
+ var EDGE_POD_EXCEEDS_BUDGET = "edge_pod_exceeds_budget";
9437
+ var LICENSE_KEY_PLACEHOLDER = /\{licenseKey\}|%7BlicenseKey%7D/gi;
9438
+ function resolveEdgePodBaseUrl(config) {
9439
+ var _config_edgePodUrl, _config_licenseKey;
9440
+ if (config.enableEdgePodRequest !== true) return void 0;
9441
+ var raw = (_config_edgePodUrl = config.edgePodUrl) === null || _config_edgePodUrl === void 0 ? void 0 : _config_edgePodUrl.trim();
9442
+ if (!raw) {
9443
+ console.warn("[AdBreak][EDGE] enableEdgePodRequest is true but edgePodUrl is missing; using GAM only");
9444
+ return void 0;
9445
+ }
9446
+ var licenseKey = (_config_licenseKey = config.licenseKey) === null || _config_licenseKey === void 0 ? void 0 : _config_licenseKey.trim();
9447
+ if (!licenseKey) {
9448
+ console.warn("[AdBreak][EDGE] enableEdgePodRequest is true but licenseKey is missing; using GAM only");
9449
+ return void 0;
9450
+ }
9451
+ var encodedKey = encodeURIComponent(licenseKey);
9452
+ try {
9453
+ var hasPlaceholder = raw.search(LICENSE_KEY_PLACEHOLDER) !== -1;
9454
+ var url = new URL(hasPlaceholder ? raw.replace(LICENSE_KEY_PLACEHOLDER, encodedKey) : raw);
9455
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
9456
+ throw new Error("unsupported protocol ".concat(url.protocol));
9457
+ }
9458
+ if (!hasPlaceholder) {
9459
+ var path = url.pathname.replace(/\/+$/, "");
9460
+ url.pathname = /\/[^/]+\/pod$/.test(path) ? path.replace(/\/[^/]+\/pod$/, "/".concat(encodedKey, "/pod")) : "".concat(path, "/").concat(encodedKey, "/pod");
9461
+ }
9462
+ return url.toString();
9463
+ } catch (unused) {
9464
+ console.warn("[AdBreak][EDGE] edgePodUrl is not a valid http(s) URL; using GAM only");
9465
+ return void 0;
9466
+ }
9467
+ }
9468
+ function buildEdgePodUrl(baseUrl, remainingMs, remainingAdLimit) {
9469
+ var url = new URL(baseUrl);
9470
+ var maxMs = Math.max(0, Math.floor(remainingMs));
9471
+ var maxAds = Math.max(1, Math.min(EDGE_POD_MAX_ADS, Math.floor(remainingAdLimit)));
9472
+ url.searchParams.set("pmxd", String(maxMs));
9473
+ url.searchParams.set("pmad", String(maxAds));
9474
+ url.searchParams.set("duration", String(Math.floor(maxMs / 1e3)));
9475
+ url.searchParams.set("count", String(maxAds));
9476
+ return url.toString();
9477
+ }
9478
+ function classifyEdgeVastResponse(result) {
9479
+ var _ref;
9480
+ var _result_error;
9481
+ if (result.error == null) {
9482
+ return result.podAdCount > 0 ? "fill" : "no_fill";
9483
+ }
9484
+ 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);
9485
+ if (/no ads available|fill rejected|no media file|no ad loaded/i.test(message) || message.includes(EDGE_POD_EXCEEDS_BUDGET)) {
9486
+ return "no_fill";
9487
+ }
9488
+ return "invalid";
9489
+ }
9490
+ function describeEdgeUrl(url) {
9491
+ try {
9492
+ var parsed = new URL(url);
9493
+ return "".concat(parsed.origin).concat(parsed.pathname);
9494
+ } catch (unused) {
9495
+ var _url_split_;
9496
+ return (_url_split_ = url.split("?")[0]) !== null && _url_split_ !== void 0 ? _url_split_ : "";
9497
+ }
9498
+ }
9333
9499
  // src/player/PlayerControls.ts
9334
9500
  function getAdAudioVolume(adPlayer) {
9335
9501
  return adPlayer.getOriginalMutedState() ? 0 : adPlayer.getOriginalVolume();
@@ -9488,6 +9654,8 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9488
9654
  this.controllerCallInFlight = false;
9489
9655
  this.playbackStartedForCurrentRequest = false;
9490
9656
  this.opportunityEpoch = -1;
9657
+ this.edgeExhaustedForBreak = false;
9658
+ this.edgeRequestsInBreak = 0;
9491
9659
  this.adPodQueue = [];
9492
9660
  this.defaultMinRemainingMsToRequestAd = 1e4;
9493
9661
  this.defaultMaxNoFillsPerBreak = 2;
@@ -9638,7 +9806,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9638
9806
  _this.timing.clearAdRequestWatchdog();
9639
9807
  _this.timing.activeAdRequestToken = null;
9640
9808
  _this.showAds = true;
9641
- _this.timing.resetGamNoFillCounter();
9809
+ if (_this.currentPodSource !== "edge") {
9810
+ _this.timing.resetGamNoFillCounter();
9811
+ }
9642
9812
  if (_this.inAdBreak && _this.timing.expectedAdBreakDurationMs != null && _this.timing.getAdBreakEndWallClockMs() == null) {
9643
9813
  _this.timing.scheduleAdStopAtBreakBoundary();
9644
9814
  if (_this.debug) {
@@ -9770,6 +9940,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9770
9940
  key: "beginVmapBreak",
9771
9941
  value: function beginVmapBreak(breakKey, position) {
9772
9942
  this.breakSource = "vmap";
9943
+ this.resetEdgeStateForBreak();
9773
9944
  this.followUpBaseVastUrl = void 0;
9774
9945
  this.unusableResponsesInBreak = 0;
9775
9946
  this.timing.totalAdRequestsInBreak = 0;
@@ -9781,7 +9952,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9781
9952
  key: "handleAdStart",
9782
9953
  value: function handleAdStart(marker) {
9783
9954
  return _async_to_generator(function() {
9784
- var baseVastUrl, adBreakDurationMs, currentMuted, currentVolume, epoch, hasPrefetchedUrl, mode, podPlayed;
9955
+ var baseVastUrl, edgeConfigured, adBreakDurationMs, currentMuted, currentVolume, epoch, hasPrefetchedUrl, mode, edgeUrl, outcome, podPlayed;
9785
9956
  return _ts_generator(this, function(_state) {
9786
9957
  switch(_state.label){
9787
9958
  case 0:
@@ -9795,7 +9966,8 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9795
9966
  ];
9796
9967
  }
9797
9968
  baseVastUrl = this.adConfig.apiVastTagUrl;
9798
- if (!baseVastUrl) {
9969
+ edgeConfigured = !!this.host.getEdgePodBaseUrl();
9970
+ if (!baseVastUrl && !edgeConfigured) {
9799
9971
  console.warn("[AdBreak] SCTE-35 break started but no direct VAST tag is configured");
9800
9972
  this.clearPendingAdBreak();
9801
9973
  return [
@@ -9811,6 +9983,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9811
9983
  this.breakSource = "scte35";
9812
9984
  this.followUpBaseVastUrl = baseVastUrl;
9813
9985
  this.unusableResponsesInBreak = 0;
9986
+ this.resetEdgeStateForBreak();
9814
9987
  this.setSlotState("NEEDS_NEXT_AD", "scte35_break_start");
9815
9988
  if (this.adConfig.podAssignedByPrefetch) {
9816
9989
  this.adConfig.podAssignedByPrefetch = false;
@@ -9832,7 +10005,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9832
10005
  this.noteOpportunity("scte35", this.cueManager.activeScte35BreakKey, "midroll");
9833
10006
  epoch = this.timing.adBreakEpoch;
9834
10007
  hasPrefetchedUrl = !!(this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0);
9835
- if (!(adBreakDurationMs == null && !hasPrefetchedUrl)) return [
10008
+ if (!(adBreakDurationMs == null && (!hasPrefetchedUrl || edgeConfigured))) return [
9836
10009
  3,
9837
10010
  2
9838
10011
  ];
@@ -9851,11 +10024,46 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9851
10024
  mode = this.host.config.isLiveStream ? "LIVE" : "VOD";
9852
10025
  console.log("[AdBreak] ".concat(mode, " break start: target duration=").concat(adBreakDurationMs != null ? "".concat(adBreakDurationMs, "ms") : "unknown"));
9853
10026
  }
10027
+ if (!edgeConfigured) return [
10028
+ 3,
10029
+ 5
10030
+ ];
10031
+ edgeUrl = this.canRequestEdge() ? this.prepareEdgePodRequest() : void 0;
10032
+ if (!edgeUrl) return [
10033
+ 3,
10034
+ 4
10035
+ ];
10036
+ this.clearPendingAdBreak();
9854
10037
  return [
9855
10038
  4,
9856
- this.startOptimizedPod(baseVastUrl, adBreakDurationMs)
10039
+ this.runEdgePod(edgeUrl, "edge_break_start")
9857
10040
  ];
9858
10041
  case 3:
10042
+ outcome = _state.sent();
10043
+ this.continueAfterEdgeOutcome(outcome, epoch);
10044
+ return [
10045
+ 2
10046
+ ];
10047
+ case 4:
10048
+ if (!this.edgeExhaustedForBreak) {
10049
+ this.markEdgeExhausted("not_eligible_at_break_start", {
10050
+ isLive: this.isLiveBreak(),
10051
+ durationMs: this.timing.expectedAdBreakDurationMs
10052
+ });
10053
+ }
10054
+ _state.label = 5;
10055
+ case 5:
10056
+ if (!baseVastUrl) {
10057
+ this.requestNextAd("no_gam_source");
10058
+ return [
10059
+ 2
10060
+ ];
10061
+ }
10062
+ return [
10063
+ 4,
10064
+ this.startOptimizedPod(baseVastUrl, adBreakDurationMs)
10065
+ ];
10066
+ case 6:
9859
10067
  podPlayed = _state.sent();
9860
10068
  if (!podPlayed && this.inAdBreak && epoch === this.timing.adBreakEpoch) {
9861
10069
  this.setSlotState("NEEDS_NEXT_AD", "initial_request_failed");
@@ -9947,6 +10155,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9947
10155
  adPlayer = this.host.getAdPlayer();
9948
10156
  requestToken = ++this.timing.adRequestTokenCounter;
9949
10157
  this.timing.activeAdRequestToken = requestToken;
10158
+ this.currentPodSource = "gam";
9950
10159
  this.setSlotState("REQUESTING", "initial_pod");
9951
10160
  this.beginFunnelRequest(adPlayer, requestToken, "initial_pod");
9952
10161
  requestUrl = this.applyOpportunityFloor(podUrl);
@@ -10063,6 +10272,224 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10063
10272
  }).call(this);
10064
10273
  }
10065
10274
  },
10275
+ {
10276
+ // ───────────────────────────────────────────────────────────────
10277
+ // Edge-first pods (live SCTE-35 only, GAM fallback)
10278
+ // ───────────────────────────────────────────────────────────────
10279
+ key: "resetEdgeStateForBreak",
10280
+ value: function resetEdgeStateForBreak() {
10281
+ this.edgeExhaustedForBreak = false;
10282
+ this.edgeRequestsInBreak = 0;
10283
+ this.currentPodSource = void 0;
10284
+ }
10285
+ },
10286
+ {
10287
+ key: "isLiveBreak",
10288
+ value: function isLiveBreak() {
10289
+ return this.host.isLiveStream() || this.host.config.isLiveStream === true;
10290
+ }
10291
+ },
10292
+ {
10293
+ key: "canRequestEdge",
10294
+ value: function canRequestEdge() {
10295
+ return this.breakSource === "scte35" && !this.edgeExhaustedForBreak && !!this.host.getEdgePodBaseUrl() && this.isLiveBreak() && this.timing.expectedAdBreakDurationMs != null && this.edgeRequestsInBreak < this.timing.maxTotalAdRequestsPerBreak;
10296
+ }
10297
+ },
10298
+ {
10299
+ key: "markEdgeExhausted",
10300
+ value: function markEdgeExhausted(reason) {
10301
+ var extra = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
10302
+ this.edgeExhaustedForBreak = true;
10303
+ this.countFunnelStage("edge_fallback:".concat(reason));
10304
+ this.logOrchestratorFunnel("edge_exhausted", _object_spread({
10305
+ reason: reason,
10306
+ edgeRequests: this.edgeRequestsInBreak,
10307
+ remainingMs: this.timing.getRemainingAdMs()
10308
+ }, extra));
10309
+ }
10310
+ },
10311
+ {
10312
+ /**
10313
+ * Builds the next Edge request from the budget left right now, or marks Edge
10314
+ * exhausted for this break. Synchronous on purpose: callers must reach the
10315
+ * REQUESTING state in the same tick so a second completion event cannot race
10316
+ * in a parallel request.
10317
+ */ key: "prepareEdgePodRequest",
10318
+ value: function prepareEdgePodRequest() {
10319
+ var baseUrl = this.host.getEdgePodBaseUrl();
10320
+ if (!baseUrl) return void 0;
10321
+ var remainingMs = this.timing.getRemainingAdMs();
10322
+ var remainingAds = Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolvePodParams().maxAds - this.timing.totalAdsInBreak);
10323
+ if (remainingAds < 1) {
10324
+ this.markEdgeExhausted("ad_capacity_reached", {
10325
+ adsInBreak: this.timing.totalAdsInBreak
10326
+ });
10327
+ return void 0;
10328
+ }
10329
+ if (remainingMs < this.getMinRemainingMsToRequestAd()) {
10330
+ this.markEdgeExhausted("insufficient_break_time", {
10331
+ remainingMs: remainingMs
10332
+ });
10333
+ return void 0;
10334
+ }
10335
+ try {
10336
+ return buildEdgePodUrl(baseUrl, remainingMs, remainingAds);
10337
+ } catch (unused) {
10338
+ this.markEdgeExhausted("invalid_edge_url");
10339
+ return void 0;
10340
+ }
10341
+ }
10342
+ },
10343
+ {
10344
+ key: "runEdgePod",
10345
+ value: function runEdgePod(requestUrl, trigger) {
10346
+ return _async_to_generator(function() {
10347
+ var _params_get, _params_get1, epoch, generation, adPlayer, requestToken, params, _ref, _adPlayer_getPodAdCount, _adPlayer_getPodTotalDurationMs, remainingMs, remainingAds, podCount, error, errorMessage, classification, diag;
10348
+ return _ts_generator(this, function(_state) {
10349
+ switch(_state.label){
10350
+ case 0:
10351
+ epoch = this.timing.adBreakEpoch;
10352
+ this.recreateAdController("new_request");
10353
+ generation = this.controllerGeneration;
10354
+ adPlayer = this.host.getAdPlayer();
10355
+ requestToken = ++this.timing.adRequestTokenCounter;
10356
+ this.timing.activeAdRequestToken = requestToken;
10357
+ this.currentPodSource = "edge";
10358
+ this.edgeRequestsInBreak++;
10359
+ this.setSlotState("REQUESTING", trigger);
10360
+ this.beginFunnelRequest(adPlayer, requestToken, trigger, "edge");
10361
+ this.currentVastUrl = requestUrl;
10362
+ params = new URL(requestUrl).searchParams;
10363
+ this.logOrchestratorFunnel("edge_request_sent", {
10364
+ trigger: trigger,
10365
+ attempt: this.edgeRequestsInBreak,
10366
+ endpoint: describeEdgeUrl(requestUrl),
10367
+ pmxd: (_params_get = params.get("pmxd")) !== null && _params_get !== void 0 ? _params_get : void 0,
10368
+ pmad: (_params_get1 = params.get("pmad")) !== null && _params_get1 !== void 0 ? _params_get1 : void 0
10369
+ });
10370
+ _state.label = 1;
10371
+ case 1:
10372
+ _state.trys.push([
10373
+ 1,
10374
+ 4,
10375
+ ,
10376
+ 5
10377
+ ]);
10378
+ this.timing.startAdRequestWatchdog(requestToken);
10379
+ return [
10380
+ 4,
10381
+ this.callController(function() {
10382
+ return adPlayer.requestAds(requestUrl, {
10383
+ source: "edge"
10384
+ });
10385
+ })
10386
+ ];
10387
+ case 2:
10388
+ _state.sent();
10389
+ this.timing.clearAdRequestWatchdog();
10390
+ if (this.isStale(epoch, generation)) {
10391
+ this.logOrchestratorFunnel("stale_request_result_ignored", {
10392
+ requestId: requestToken,
10393
+ source: "edge"
10394
+ });
10395
+ return [
10396
+ 2,
10397
+ "stale"
10398
+ ];
10399
+ }
10400
+ remainingMs = this.timing.getRemainingAdMs();
10401
+ remainingAds = Math.max(1, Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolvePodParams().maxAds - this.timing.totalAdsInBreak));
10402
+ 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;
10403
+ if (classifyEdgeVastResponse({
10404
+ podAdCount: podCount
10405
+ }) !== "fill") {
10406
+ throw new Error("".concat(EDGE_POD_EXCEEDS_BUDGET, ": no Edge ad fits ").concat(remainingMs, "ms"));
10407
+ }
10408
+ this.setSlotState("READY", "edge_vast_ready");
10409
+ this.logOrchestratorFunnel("edge_fill", {
10410
+ podAdCount: podCount,
10411
+ podDurationMs: (_adPlayer_getPodTotalDurationMs = adPlayer.getPodTotalDurationMs) === null || _adPlayer_getPodTotalDurationMs === void 0 ? void 0 : _adPlayer_getPodTotalDurationMs.call(adPlayer),
10412
+ remainingMs: remainingMs
10413
+ });
10414
+ sendAdLoadedTracking(this.host.config.licenseKey, {
10415
+ source: "hls",
10416
+ vastUrl: requestUrl,
10417
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
10418
+ }, this.analyticsContext).catch(function() {});
10419
+ this.timing.startAdFailsafeTimer(requestToken);
10420
+ return [
10421
+ 4,
10422
+ this.callController(function() {
10423
+ return adPlayer.play();
10424
+ })
10425
+ ];
10426
+ case 3:
10427
+ _state.sent();
10428
+ if (this.isStale(epoch, generation)) return [
10429
+ 2,
10430
+ "stale"
10431
+ ];
10432
+ if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {
10433
+ this.timing.scheduleAdStopAtBreakBoundary();
10434
+ }
10435
+ adPlayer.setAdVolume(getAdAudioVolume(adPlayer));
10436
+ return [
10437
+ 2,
10438
+ "fill"
10439
+ ];
10440
+ case 4:
10441
+ error = _state.sent();
10442
+ this.timing.clearAdRequestWatchdog();
10443
+ this.timing.clearAdFailsafeTimer();
10444
+ if (this.timing.activeAdRequestToken === requestToken) {
10445
+ this.timing.activeAdRequestToken = null;
10446
+ }
10447
+ errorMessage = error === null || error === void 0 ? void 0 : error.message;
10448
+ if (this.isStale(epoch, generation)) {
10449
+ this.logOrchestratorFunnel("stale_request_result_ignored", {
10450
+ requestId: requestToken,
10451
+ source: "edge",
10452
+ errorMessage: errorMessage
10453
+ });
10454
+ return [
10455
+ 2,
10456
+ "stale"
10457
+ ];
10458
+ }
10459
+ classification = classifyEdgeVastResponse({
10460
+ podAdCount: 0,
10461
+ error: error
10462
+ });
10463
+ diag = this.requestDiagnostics.get(requestToken);
10464
+ if (diag && !diag.failureReason) diag.failureReason = "edge_".concat(classification, ": ").concat(errorMessage);
10465
+ this.markEdgeExhausted("edge_".concat(classification), {
10466
+ errorMessage: errorMessage
10467
+ });
10468
+ return [
10469
+ 2,
10470
+ "fallback"
10471
+ ];
10472
+ case 5:
10473
+ return [
10474
+ 2
10475
+ ];
10476
+ }
10477
+ });
10478
+ }).call(this);
10479
+ }
10480
+ },
10481
+ {
10482
+ key: "continueAfterEdgeOutcome",
10483
+ value: function continueAfterEdgeOutcome(outcome, epoch) {
10484
+ if (outcome !== "fallback") return;
10485
+ if (!this.inAdBreak || epoch !== this.timing.adBreakEpoch) return;
10486
+ if (this.debug) {
10487
+ console.log("[AdBreak][EDGE] No usable Edge pod; checking with GAM for the remaining break");
10488
+ }
10489
+ this.setSlotState("NEEDS_NEXT_AD", "edge_fallback");
10490
+ this.requestNextAd("edge_fallback");
10491
+ }
10492
+ },
10066
10493
  {
10067
10494
  // ───────────────────────────────────────────────────────────────
10068
10495
  // Next-ad scheduling (single flight)
@@ -10118,7 +10545,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10118
10545
  value: function getStopRequestingReason(remainingMs) {
10119
10546
  if (this.breakSource === "vmap") {
10120
10547
  if (this.adPodQueue.length === 0) return "vmap_queue_empty";
10121
- } else if (this.breakSource !== "scte35" || !this.followUpBaseVastUrl) {
10548
+ } else if (this.breakSource !== "scte35" || !this.followUpBaseVastUrl && !this.canRequestEdge()) {
10122
10549
  return "no_follow_up_source";
10123
10550
  }
10124
10551
  if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {
@@ -10130,7 +10557,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10130
10557
  if (this.timing.totalAdRequestsInBreak >= this.timing.maxTotalAdRequestsPerBreak) {
10131
10558
  return "request_cap";
10132
10559
  }
10133
- if (this.timing.isGamInCooldown()) {
10560
+ if (!this.canRequestEdge() && this.timing.isGamInCooldown()) {
10134
10561
  return "gam_cooldown";
10135
10562
  }
10136
10563
  if (this.isBreakTimeBounded() && remainingMs < this.getMinRemainingMsToRequestAd()) {
@@ -10224,10 +10651,33 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10224
10651
  key: "requestFollowUpAd",
10225
10652
  value: function requestFollowUpAd(trigger) {
10226
10653
  return _async_to_generator(function() {
10227
- var url, epoch, unused;
10654
+ var edgeUrl, epoch2, outcome, url, epoch, unused;
10228
10655
  return _ts_generator(this, function(_state) {
10229
10656
  switch(_state.label){
10230
10657
  case 0:
10658
+ if (!this.canRequestEdge()) return [
10659
+ 3,
10660
+ 2
10661
+ ];
10662
+ edgeUrl = this.prepareEdgePodRequest();
10663
+ if (!edgeUrl) {
10664
+ this.requestNextAd("".concat(trigger, ":edge_unavailable"));
10665
+ return [
10666
+ 2
10667
+ ];
10668
+ }
10669
+ epoch2 = this.timing.adBreakEpoch;
10670
+ return [
10671
+ 4,
10672
+ this.runEdgePod(edgeUrl, "edge_".concat(trigger))
10673
+ ];
10674
+ case 1:
10675
+ outcome = _state.sent();
10676
+ this.continueAfterEdgeOutcome(outcome, epoch2);
10677
+ return [
10678
+ 2
10679
+ ];
10680
+ case 2:
10231
10681
  if (this.breakSource === "vmap") {
10232
10682
  url = this.adPodQueue.shift();
10233
10683
  } else if (this.followUpBaseVastUrl) {
@@ -10238,32 +10688,32 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10238
10688
  ];
10239
10689
  this.noteVastUrlGenerated(ensureVideoAdType(url), trigger);
10240
10690
  epoch = this.timing.adBreakEpoch;
10241
- _state.label = 1;
10242
- case 1:
10691
+ _state.label = 3;
10692
+ case 3:
10243
10693
  _state.trys.push([
10244
- 1,
10245
10694
  3,
10695
+ 5,
10246
10696
  ,
10247
- 4
10697
+ 6
10248
10698
  ]);
10249
10699
  return [
10250
10700
  4,
10251
10701
  this.playSingleAd(url, trigger)
10252
10702
  ];
10253
- case 2:
10703
+ case 4:
10254
10704
  _state.sent();
10255
10705
  return [
10256
10706
  3,
10257
- 4
10707
+ 6
10258
10708
  ];
10259
- case 3:
10709
+ case 5:
10260
10710
  unused = _state.sent();
10261
10711
  this.continueAfterRequestFailure(epoch);
10262
10712
  return [
10263
10713
  3,
10264
- 4
10714
+ 6
10265
10715
  ];
10266
- case 4:
10716
+ case 6:
10267
10717
  return [
10268
10718
  2
10269
10719
  ];
@@ -10376,7 +10826,11 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10376
10826
  case "gam_http_request_sent":
10377
10827
  diag.gamRequestSent++;
10378
10828
  break;
10829
+ case "edge_http_request_sent":
10830
+ diag.edgeRequestSent++;
10831
+ break;
10379
10832
  case "gam_response_received":
10833
+ case "edge_response_received":
10380
10834
  diag.vastHttpStatus = payload.httpStatus;
10381
10835
  break;
10382
10836
  case "vast_parsed":
@@ -10563,6 +11017,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10563
11017
  {
10564
11018
  key: "beginFunnelRequest",
10565
11019
  value: function beginFunnelRequest(adPlayer, requestToken, trigger) {
11020
+ var source = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : "gam";
10566
11021
  var _adPlayer_setFunnelContext;
10567
11022
  if (this.controllerCallInFlight) {
10568
11023
  this.logOrchestratorFunnel("duplicate_request_detected", {
@@ -10577,7 +11032,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10577
11032
  requestId: requestToken,
10578
11033
  controllerId: this.controllerGeneration,
10579
11034
  trigger: trigger,
11035
+ source: source,
10580
11036
  gamRequestSent: 0,
11037
+ edgeRequestSent: 0,
10581
11038
  wrapperDepth: 0,
10582
11039
  inlineResolved: false,
10583
11040
  mediaCandidateCount: 0,
@@ -10708,6 +11165,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10708
11165
  this.timing.activeAdRequestToken = requestToken;
10709
11166
  ap = this.host.getAdPlayer();
10710
11167
  budgetedUrl = this.withCurrentPodBudget(vastTagUrl);
11168
+ this.currentPodSource = "gam";
10711
11169
  this.setSlotState("REQUESTING", trigger);
10712
11170
  this.beginFunnelRequest(ap, requestToken, trigger);
10713
11171
  requestUrl = this.applyOpportunityFloor(budgetedUrl);
@@ -10855,6 +11313,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10855
11313
  requests: requests,
10856
11314
  requestRetries: requestRetries,
10857
11315
  gamResponses: count("gam_response_received"),
11316
+ edgeRequests: count("edge_request_sent"),
11317
+ edgeFills: count("edge_fill"),
11318
+ edgeEmptySentinels: count("edge_empty_sentinel"),
11319
+ edgeFallbacks: countPrefix("edge_fallback:"),
10858
11320
  requestsSuppressed: count("request_suppressed"),
10859
11321
  duplicates: count("duplicate_request_detected") + count("duplicate_break_start"),
10860
11322
  filled: count("vast_received"),
@@ -10951,6 +11413,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10951
11413
  this.breakSource = void 0;
10952
11414
  this.followUpBaseVastUrl = void 0;
10953
11415
  this.unusableResponsesInBreak = 0;
11416
+ this.resetEdgeStateForBreak();
10954
11417
  adPlayer.stop().catch(function() {});
10955
11418
  if (!alreadyEnded) this.logBreakFunnel(reason);
10956
11419
  this.opportunityFloor = void 0;
@@ -11264,7 +11727,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11264
11727
  });
11265
11728
  return;
11266
11729
  }
11267
- this.timing.consecutiveFailures++;
11730
+ if (this.currentPodSource === "edge") {
11731
+ this.markEdgeExhausted("edge_playback_failed", {
11732
+ reason: reason
11733
+ });
11734
+ } else {
11735
+ this.timing.consecutiveFailures++;
11736
+ }
11268
11737
  var diag = this.currentRequestId != null ? this.requestDiagnostics.get(this.currentRequestId) : void 0;
11269
11738
  if (diag && !diag.failureReason) diag.failureReason = reason;
11270
11739
  if (this.debug) {
@@ -11294,7 +11763,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11294
11763
  if (this.config.adFloorMaxCents != null) floorBounds.maxCents = this.config.adFloorMaxCents;
11295
11764
  if (this.config.adFloorStepCents != null) floorBounds.stepCents = this.config.adFloorStepCents;
11296
11765
  this.floorLadder = new FloorLadderController(this.config.adFloorLadder, floorBounds);
11766
+ this.floorLadderEnabled = this.config.adFloorLadderEnabled === true;
11297
11767
  this.warnOnInvalidFloorLadder(this.floorLadder.validate());
11768
+ this.edgePodBaseUrl = resolveEdgePodBaseUrl(this.config);
11298
11769
  this.adPlayer = this.createAdPlayer(false);
11299
11770
  this.palNonce = createPalNonceManager();
11300
11771
  this.cueManager = new Scte35CueManager(!!this.config.debugAdTiming, {
@@ -11394,11 +11865,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11394
11865
  generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
11395
11866
  return _this.generatePodVastUrl(base, breakDurationMs);
11396
11867
  },
11868
+ getEdgePodBaseUrl: function getEdgePodBaseUrl() {
11869
+ return _this.edgePodBaseUrl;
11870
+ },
11397
11871
  getFloorSnapshot: function getFloorSnapshot(position) {
11398
- return _this.floorLadder.snapshotFor({
11872
+ return _this.floorLadderEnabled ? _this.floorLadder.snapshotFor({
11399
11873
  position: position,
11400
11874
  isCtv: _this.isCtvEnvironment()
11401
- });
11875
+ }) : void 0;
11402
11876
  },
11403
11877
  onAdClick: function onAdClick() {
11404
11878
  return _this.palNonce.sendAdClick();
@@ -11449,11 +11923,43 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11449
11923
  return report;
11450
11924
  }
11451
11925
  },
11926
+ {
11927
+ key: "setAdFloorLadderEnabled",
11928
+ value: function setAdFloorLadderEnabled(enabled) {
11929
+ this.floorLadderEnabled = enabled;
11930
+ if (enabled) this.warnOnInvalidFloorLadder(this.floorLadder.validate());
11931
+ }
11932
+ },
11933
+ {
11934
+ key: "isAdFloorLadderEnabled",
11935
+ value: function isAdFloorLadderEnabled() {
11936
+ return this.floorLadderEnabled;
11937
+ }
11938
+ },
11939
+ {
11940
+ key: "setEdgePodRequest",
11941
+ value: function setEdgePodRequest(update) {
11942
+ if (update.enableEdgePodRequest === this.config.enableEdgePodRequest && update.edgePodUrl === this.config.edgePodUrl) {
11943
+ return;
11944
+ }
11945
+ if (update.enableEdgePodRequest === void 0) delete this.config.enableEdgePodRequest;
11946
+ else this.config.enableEdgePodRequest = update.enableEdgePodRequest;
11947
+ if (update.edgePodUrl === void 0) delete this.config.edgePodUrl;
11948
+ else this.config.edgePodUrl = update.edgePodUrl;
11949
+ this.edgePodBaseUrl = resolveEdgePodBaseUrl(this.config);
11950
+ }
11951
+ },
11952
+ {
11953
+ key: "getEdgePodUrl",
11954
+ value: function getEdgePodUrl() {
11955
+ return this.edgePodBaseUrl;
11956
+ }
11957
+ },
11452
11958
  {
11453
11959
  key: "warnOnInvalidFloorLadder",
11454
11960
  value: function warnOnInvalidFloorLadder(report) {
11455
11961
  var config = this.floorLadder.get();
11456
- if (report.ok || !config.enabled) return;
11962
+ if (report.ok || !this.floorLadderEnabled || !config.enabled) return;
11457
11963
  console.warn("[AdBreak][FLOOR] configuration has issues; invalid floors will not be sent", {
11458
11964
  errors: report.errors,
11459
11965
  configurationVersion: config.configurationVersion,
@@ -12186,6 +12692,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
12186
12692
  this.timing.destroy();
12187
12693
  this.adBreak.clearPendingAdBreak();
12188
12694
  this.placeholder.destroy();
12695
+ 0;
12189
12696
  if (this.timeUpdateHandler) {
12190
12697
  this.video.removeEventListener("timeupdate", this.timeUpdateHandler);
12191
12698
  delete this.timeUpdateHandler;
@@ -12291,7 +12798,7 @@ var CRITICAL_PROPS = [
12291
12798
  var CONTROLS_HIDE_DELAY = 3e3;
12292
12799
  var DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;
12293
12800
  var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12294
- 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, [
12801
+ 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, [
12295
12802
  "src",
12296
12803
  "autoplay",
12297
12804
  "muted",
@@ -12328,10 +12835,13 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12328
12835
  "minRemainingMsToStartAd",
12329
12836
  "minRemainingMsToRequestAd",
12330
12837
  "maxNoFillsPerBreak",
12838
+ "adFloorLadderEnabled",
12331
12839
  "adFloorLadder",
12332
12840
  "adFloorMinCents",
12333
12841
  "adFloorMaxCents",
12334
- "adFloorStepCents"
12842
+ "adFloorStepCents",
12843
+ "enableEdgePodRequest",
12844
+ "edgePodUrl"
12335
12845
  ]);
12336
12846
  var adFloorLadderKey = JSON.stringify(adFloorLadder !== null && adFloorLadder !== void 0 ? adFloorLadder : null);
12337
12847
  var videoRef = (0, import_react.useRef)(null);
@@ -12532,10 +13042,13 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12532
13042
  if (minRemainingMsToStartAd !== void 0) cfg.minRemainingMsToStartAd = minRemainingMsToStartAd;
12533
13043
  if (minRemainingMsToRequestAd !== void 0) cfg.minRemainingMsToRequestAd = minRemainingMsToRequestAd;
12534
13044
  if (maxNoFillsPerBreak !== void 0) cfg.maxNoFillsPerBreak = maxNoFillsPerBreak;
13045
+ if (adFloorLadderEnabled !== void 0) cfg.adFloorLadderEnabled = adFloorLadderEnabled;
12535
13046
  if (adFloorLadder !== void 0) cfg.adFloorLadder = adFloorLadder;
12536
13047
  if (adFloorMinCents !== void 0) cfg.adFloorMinCents = adFloorMinCents;
12537
13048
  if (adFloorMaxCents !== void 0) cfg.adFloorMaxCents = adFloorMaxCents;
12538
13049
  if (adFloorStepCents !== void 0) cfg.adFloorStepCents = adFloorStepCents;
13050
+ if (enableEdgePodRequest !== void 0) cfg.enableEdgePodRequest = enableEdgePodRequest;
13051
+ if (edgePodUrl !== void 0) cfg.edgePodUrl = edgePodUrl;
12539
13052
  var player = new StormcloudVideoPlayer(cfg);
12540
13053
  playerRef.current = player;
12541
13054
  appliedFloorLadderKeyRef.current = adFloorLadderKey;
@@ -12584,6 +13097,25 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12584
13097
  }, [
12585
13098
  adFloorLadderKey
12586
13099
  ]);
13100
+ (0, import_react.useEffect)(function() {
13101
+ if (!playerRef.current) return;
13102
+ var enabled = adFloorLadderEnabled === true;
13103
+ if (playerRef.current.isAdFloorLadderEnabled() === enabled) return;
13104
+ playerRef.current.setAdFloorLadderEnabled(enabled);
13105
+ }, [
13106
+ adFloorLadderEnabled
13107
+ ]);
13108
+ (0, import_react.useEffect)(function() {
13109
+ if (!playerRef.current) return;
13110
+ playerRef.current.setEdgePodRequest(_object_spread({}, enableEdgePodRequest !== void 0 ? {
13111
+ enableEdgePodRequest: enableEdgePodRequest
13112
+ } : {}, edgePodUrl !== void 0 ? {
13113
+ edgePodUrl: edgePodUrl
13114
+ } : {}));
13115
+ }, [
13116
+ enableEdgePodRequest,
13117
+ edgePodUrl
13118
+ ]);
12587
13119
  (0, import_react.useEffect)(function() {
12588
13120
  if (!playerRef.current) return;
12589
13121
  var checkAdStatus = function checkAdStatus() {
@@ -13660,6 +14192,9 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
13660
14192
  }
13661
14193
  }
13662
14194
  }
14195
+ if (prevProps.adFloorLadderEnabled !== nextProps.adFloorLadderEnabled || prevProps.enableEdgePodRequest !== nextProps.enableEdgePodRequest || prevProps.edgePodUrl !== nextProps.edgePodUrl) {
14196
+ return false;
14197
+ }
13663
14198
  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)) {
13664
14199
  return false;
13665
14200
  }