stormcloud-video-player 0.8.69 → 0.8.70

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,59 @@ 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
+ function resolveEdgePodBaseUrl(config) {
9438
+ var _config_edgePodUrl;
9439
+ if (config.enableEdgePodRequest !== true) return void 0;
9440
+ var raw = (_config_edgePodUrl = config.edgePodUrl) === null || _config_edgePodUrl === void 0 ? void 0 : _config_edgePodUrl.trim();
9441
+ if (!raw) {
9442
+ console.warn("[AdBreak][EDGE] enableEdgePodRequest is true but edgePodUrl is missing; using GAM only");
9443
+ return void 0;
9444
+ }
9445
+ try {
9446
+ var url = new URL(raw);
9447
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
9448
+ throw new Error("unsupported protocol ".concat(url.protocol));
9449
+ }
9450
+ return url.toString();
9451
+ } catch (unused) {
9452
+ console.warn("[AdBreak][EDGE] edgePodUrl is not a valid http(s) URL; using GAM only");
9453
+ return void 0;
9454
+ }
9455
+ }
9456
+ function buildEdgePodUrl(baseUrl, remainingMs, remainingAdLimit) {
9457
+ var url = new URL(baseUrl);
9458
+ var maxMs = Math.max(0, Math.floor(remainingMs));
9459
+ var maxAds = Math.max(1, Math.min(EDGE_POD_MAX_ADS, Math.floor(remainingAdLimit)));
9460
+ url.searchParams.set("pmxd", String(maxMs));
9461
+ url.searchParams.set("pmad", String(maxAds));
9462
+ url.searchParams.set("duration", String(Math.floor(maxMs / 1e3)));
9463
+ url.searchParams.set("count", String(maxAds));
9464
+ return url.toString();
9465
+ }
9466
+ function classifyEdgeVastResponse(result) {
9467
+ var _ref;
9468
+ var _result_error;
9469
+ if (result.error == null) {
9470
+ return result.podAdCount > 0 ? "fill" : "no_fill";
9471
+ }
9472
+ 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);
9473
+ if (/no ads available|fill rejected|no media file|no ad loaded/i.test(message) || message.includes(EDGE_POD_EXCEEDS_BUDGET)) {
9474
+ return "no_fill";
9475
+ }
9476
+ return "invalid";
9477
+ }
9478
+ function describeEdgeUrl(url) {
9479
+ try {
9480
+ var parsed = new URL(url);
9481
+ return "".concat(parsed.origin).concat(parsed.pathname);
9482
+ } catch (unused) {
9483
+ var _url_split_;
9484
+ return (_url_split_ = url.split("?")[0]) !== null && _url_split_ !== void 0 ? _url_split_ : "";
9485
+ }
9486
+ }
9333
9487
  // src/player/PlayerControls.ts
9334
9488
  function getAdAudioVolume(adPlayer) {
9335
9489
  return adPlayer.getOriginalMutedState() ? 0 : adPlayer.getOriginalVolume();
@@ -9488,6 +9642,8 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9488
9642
  this.controllerCallInFlight = false;
9489
9643
  this.playbackStartedForCurrentRequest = false;
9490
9644
  this.opportunityEpoch = -1;
9645
+ this.edgeExhaustedForBreak = false;
9646
+ this.edgeRequestsInBreak = 0;
9491
9647
  this.adPodQueue = [];
9492
9648
  this.defaultMinRemainingMsToRequestAd = 1e4;
9493
9649
  this.defaultMaxNoFillsPerBreak = 2;
@@ -9638,7 +9794,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9638
9794
  _this.timing.clearAdRequestWatchdog();
9639
9795
  _this.timing.activeAdRequestToken = null;
9640
9796
  _this.showAds = true;
9641
- _this.timing.resetGamNoFillCounter();
9797
+ if (_this.currentPodSource !== "edge") {
9798
+ _this.timing.resetGamNoFillCounter();
9799
+ }
9642
9800
  if (_this.inAdBreak && _this.timing.expectedAdBreakDurationMs != null && _this.timing.getAdBreakEndWallClockMs() == null) {
9643
9801
  _this.timing.scheduleAdStopAtBreakBoundary();
9644
9802
  if (_this.debug) {
@@ -9770,6 +9928,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9770
9928
  key: "beginVmapBreak",
9771
9929
  value: function beginVmapBreak(breakKey, position) {
9772
9930
  this.breakSource = "vmap";
9931
+ this.resetEdgeStateForBreak();
9773
9932
  this.followUpBaseVastUrl = void 0;
9774
9933
  this.unusableResponsesInBreak = 0;
9775
9934
  this.timing.totalAdRequestsInBreak = 0;
@@ -9781,7 +9940,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9781
9940
  key: "handleAdStart",
9782
9941
  value: function handleAdStart(marker) {
9783
9942
  return _async_to_generator(function() {
9784
- var baseVastUrl, adBreakDurationMs, currentMuted, currentVolume, epoch, hasPrefetchedUrl, mode, podPlayed;
9943
+ var baseVastUrl, edgeConfigured, adBreakDurationMs, currentMuted, currentVolume, epoch, hasPrefetchedUrl, mode, edgeUrl, outcome, podPlayed;
9785
9944
  return _ts_generator(this, function(_state) {
9786
9945
  switch(_state.label){
9787
9946
  case 0:
@@ -9795,7 +9954,8 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9795
9954
  ];
9796
9955
  }
9797
9956
  baseVastUrl = this.adConfig.apiVastTagUrl;
9798
- if (!baseVastUrl) {
9957
+ edgeConfigured = !!this.host.getEdgePodBaseUrl();
9958
+ if (!baseVastUrl && !edgeConfigured) {
9799
9959
  console.warn("[AdBreak] SCTE-35 break started but no direct VAST tag is configured");
9800
9960
  this.clearPendingAdBreak();
9801
9961
  return [
@@ -9811,6 +9971,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9811
9971
  this.breakSource = "scte35";
9812
9972
  this.followUpBaseVastUrl = baseVastUrl;
9813
9973
  this.unusableResponsesInBreak = 0;
9974
+ this.resetEdgeStateForBreak();
9814
9975
  this.setSlotState("NEEDS_NEXT_AD", "scte35_break_start");
9815
9976
  if (this.adConfig.podAssignedByPrefetch) {
9816
9977
  this.adConfig.podAssignedByPrefetch = false;
@@ -9832,7 +9993,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9832
9993
  this.noteOpportunity("scte35", this.cueManager.activeScte35BreakKey, "midroll");
9833
9994
  epoch = this.timing.adBreakEpoch;
9834
9995
  hasPrefetchedUrl = !!(this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0);
9835
- if (!(adBreakDurationMs == null && !hasPrefetchedUrl)) return [
9996
+ if (!(adBreakDurationMs == null && (!hasPrefetchedUrl || edgeConfigured))) return [
9836
9997
  3,
9837
9998
  2
9838
9999
  ];
@@ -9851,11 +10012,46 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9851
10012
  mode = this.host.config.isLiveStream ? "LIVE" : "VOD";
9852
10013
  console.log("[AdBreak] ".concat(mode, " break start: target duration=").concat(adBreakDurationMs != null ? "".concat(adBreakDurationMs, "ms") : "unknown"));
9853
10014
  }
10015
+ if (!edgeConfigured) return [
10016
+ 3,
10017
+ 5
10018
+ ];
10019
+ edgeUrl = this.canRequestEdge() ? this.prepareEdgePodRequest() : void 0;
10020
+ if (!edgeUrl) return [
10021
+ 3,
10022
+ 4
10023
+ ];
10024
+ this.clearPendingAdBreak();
9854
10025
  return [
9855
10026
  4,
9856
- this.startOptimizedPod(baseVastUrl, adBreakDurationMs)
10027
+ this.runEdgePod(edgeUrl, "edge_break_start")
9857
10028
  ];
9858
10029
  case 3:
10030
+ outcome = _state.sent();
10031
+ this.continueAfterEdgeOutcome(outcome, epoch);
10032
+ return [
10033
+ 2
10034
+ ];
10035
+ case 4:
10036
+ if (!this.edgeExhaustedForBreak) {
10037
+ this.markEdgeExhausted("not_eligible_at_break_start", {
10038
+ isLive: this.isLiveBreak(),
10039
+ durationMs: this.timing.expectedAdBreakDurationMs
10040
+ });
10041
+ }
10042
+ _state.label = 5;
10043
+ case 5:
10044
+ if (!baseVastUrl) {
10045
+ this.requestNextAd("no_gam_source");
10046
+ return [
10047
+ 2
10048
+ ];
10049
+ }
10050
+ return [
10051
+ 4,
10052
+ this.startOptimizedPod(baseVastUrl, adBreakDurationMs)
10053
+ ];
10054
+ case 6:
9859
10055
  podPlayed = _state.sent();
9860
10056
  if (!podPlayed && this.inAdBreak && epoch === this.timing.adBreakEpoch) {
9861
10057
  this.setSlotState("NEEDS_NEXT_AD", "initial_request_failed");
@@ -9947,6 +10143,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
9947
10143
  adPlayer = this.host.getAdPlayer();
9948
10144
  requestToken = ++this.timing.adRequestTokenCounter;
9949
10145
  this.timing.activeAdRequestToken = requestToken;
10146
+ this.currentPodSource = "gam";
9950
10147
  this.setSlotState("REQUESTING", "initial_pod");
9951
10148
  this.beginFunnelRequest(adPlayer, requestToken, "initial_pod");
9952
10149
  requestUrl = this.applyOpportunityFloor(podUrl);
@@ -10063,6 +10260,224 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10063
10260
  }).call(this);
10064
10261
  }
10065
10262
  },
10263
+ {
10264
+ // ───────────────────────────────────────────────────────────────
10265
+ // Edge-first pods (live SCTE-35 only, GAM fallback)
10266
+ // ───────────────────────────────────────────────────────────────
10267
+ key: "resetEdgeStateForBreak",
10268
+ value: function resetEdgeStateForBreak() {
10269
+ this.edgeExhaustedForBreak = false;
10270
+ this.edgeRequestsInBreak = 0;
10271
+ this.currentPodSource = void 0;
10272
+ }
10273
+ },
10274
+ {
10275
+ key: "isLiveBreak",
10276
+ value: function isLiveBreak() {
10277
+ return this.host.isLiveStream() || this.host.config.isLiveStream === true;
10278
+ }
10279
+ },
10280
+ {
10281
+ key: "canRequestEdge",
10282
+ value: function canRequestEdge() {
10283
+ return this.breakSource === "scte35" && !this.edgeExhaustedForBreak && !!this.host.getEdgePodBaseUrl() && this.isLiveBreak() && this.timing.expectedAdBreakDurationMs != null && this.edgeRequestsInBreak < this.timing.maxTotalAdRequestsPerBreak;
10284
+ }
10285
+ },
10286
+ {
10287
+ key: "markEdgeExhausted",
10288
+ value: function markEdgeExhausted(reason) {
10289
+ var extra = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
10290
+ this.edgeExhaustedForBreak = true;
10291
+ this.countFunnelStage("edge_fallback:".concat(reason));
10292
+ this.logOrchestratorFunnel("edge_exhausted", _object_spread({
10293
+ reason: reason,
10294
+ edgeRequests: this.edgeRequestsInBreak,
10295
+ remainingMs: this.timing.getRemainingAdMs()
10296
+ }, extra));
10297
+ }
10298
+ },
10299
+ {
10300
+ /**
10301
+ * Builds the next Edge request from the budget left right now, or marks Edge
10302
+ * exhausted for this break. Synchronous on purpose: callers must reach the
10303
+ * REQUESTING state in the same tick so a second completion event cannot race
10304
+ * in a parallel request.
10305
+ */ key: "prepareEdgePodRequest",
10306
+ value: function prepareEdgePodRequest() {
10307
+ var baseUrl = this.host.getEdgePodBaseUrl();
10308
+ if (!baseUrl) return void 0;
10309
+ var remainingMs = this.timing.getRemainingAdMs();
10310
+ var remainingAds = Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolvePodParams().maxAds - this.timing.totalAdsInBreak);
10311
+ if (remainingAds < 1) {
10312
+ this.markEdgeExhausted("ad_capacity_reached", {
10313
+ adsInBreak: this.timing.totalAdsInBreak
10314
+ });
10315
+ return void 0;
10316
+ }
10317
+ if (remainingMs < this.getMinRemainingMsToRequestAd()) {
10318
+ this.markEdgeExhausted("insufficient_break_time", {
10319
+ remainingMs: remainingMs
10320
+ });
10321
+ return void 0;
10322
+ }
10323
+ try {
10324
+ return buildEdgePodUrl(baseUrl, remainingMs, remainingAds);
10325
+ } catch (unused) {
10326
+ this.markEdgeExhausted("invalid_edge_url");
10327
+ return void 0;
10328
+ }
10329
+ }
10330
+ },
10331
+ {
10332
+ key: "runEdgePod",
10333
+ value: function runEdgePod(requestUrl, trigger) {
10334
+ return _async_to_generator(function() {
10335
+ var _params_get, _params_get1, epoch, generation, adPlayer, requestToken, params, _ref, _adPlayer_getPodAdCount, _adPlayer_getPodTotalDurationMs, remainingMs, remainingAds, podCount, error, errorMessage, classification, diag;
10336
+ return _ts_generator(this, function(_state) {
10337
+ switch(_state.label){
10338
+ case 0:
10339
+ epoch = this.timing.adBreakEpoch;
10340
+ this.recreateAdController("new_request");
10341
+ generation = this.controllerGeneration;
10342
+ adPlayer = this.host.getAdPlayer();
10343
+ requestToken = ++this.timing.adRequestTokenCounter;
10344
+ this.timing.activeAdRequestToken = requestToken;
10345
+ this.currentPodSource = "edge";
10346
+ this.edgeRequestsInBreak++;
10347
+ this.setSlotState("REQUESTING", trigger);
10348
+ this.beginFunnelRequest(adPlayer, requestToken, trigger, "edge");
10349
+ this.currentVastUrl = requestUrl;
10350
+ params = new URL(requestUrl).searchParams;
10351
+ this.logOrchestratorFunnel("edge_request_sent", {
10352
+ trigger: trigger,
10353
+ attempt: this.edgeRequestsInBreak,
10354
+ endpoint: describeEdgeUrl(requestUrl),
10355
+ pmxd: (_params_get = params.get("pmxd")) !== null && _params_get !== void 0 ? _params_get : void 0,
10356
+ pmad: (_params_get1 = params.get("pmad")) !== null && _params_get1 !== void 0 ? _params_get1 : void 0
10357
+ });
10358
+ _state.label = 1;
10359
+ case 1:
10360
+ _state.trys.push([
10361
+ 1,
10362
+ 4,
10363
+ ,
10364
+ 5
10365
+ ]);
10366
+ this.timing.startAdRequestWatchdog(requestToken);
10367
+ return [
10368
+ 4,
10369
+ this.callController(function() {
10370
+ return adPlayer.requestAds(requestUrl, {
10371
+ source: "edge"
10372
+ });
10373
+ })
10374
+ ];
10375
+ case 2:
10376
+ _state.sent();
10377
+ this.timing.clearAdRequestWatchdog();
10378
+ if (this.isStale(epoch, generation)) {
10379
+ this.logOrchestratorFunnel("stale_request_result_ignored", {
10380
+ requestId: requestToken,
10381
+ source: "edge"
10382
+ });
10383
+ return [
10384
+ 2,
10385
+ "stale"
10386
+ ];
10387
+ }
10388
+ remainingMs = this.timing.getRemainingAdMs();
10389
+ remainingAds = Math.max(1, Math.min(EDGE_POD_MAX_ADS, this.adConfig.resolvePodParams().maxAds - this.timing.totalAdsInBreak));
10390
+ 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;
10391
+ if (classifyEdgeVastResponse({
10392
+ podAdCount: podCount
10393
+ }) !== "fill") {
10394
+ throw new Error("".concat(EDGE_POD_EXCEEDS_BUDGET, ": no Edge ad fits ").concat(remainingMs, "ms"));
10395
+ }
10396
+ this.setSlotState("READY", "edge_vast_ready");
10397
+ this.logOrchestratorFunnel("edge_fill", {
10398
+ podAdCount: podCount,
10399
+ podDurationMs: (_adPlayer_getPodTotalDurationMs = adPlayer.getPodTotalDurationMs) === null || _adPlayer_getPodTotalDurationMs === void 0 ? void 0 : _adPlayer_getPodTotalDurationMs.call(adPlayer),
10400
+ remainingMs: remainingMs
10401
+ });
10402
+ sendAdLoadedTracking(this.host.config.licenseKey, {
10403
+ source: "hls",
10404
+ vastUrl: requestUrl,
10405
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
10406
+ }, this.analyticsContext).catch(function() {});
10407
+ this.timing.startAdFailsafeTimer(requestToken);
10408
+ return [
10409
+ 4,
10410
+ this.callController(function() {
10411
+ return adPlayer.play();
10412
+ })
10413
+ ];
10414
+ case 3:
10415
+ _state.sent();
10416
+ if (this.isStale(epoch, generation)) return [
10417
+ 2,
10418
+ "stale"
10419
+ ];
10420
+ if (this.timing.expectedAdBreakDurationMs != null && this.timing.getAdBreakEndWallClockMs() == null) {
10421
+ this.timing.scheduleAdStopAtBreakBoundary();
10422
+ }
10423
+ adPlayer.setAdVolume(getAdAudioVolume(adPlayer));
10424
+ return [
10425
+ 2,
10426
+ "fill"
10427
+ ];
10428
+ case 4:
10429
+ error = _state.sent();
10430
+ this.timing.clearAdRequestWatchdog();
10431
+ this.timing.clearAdFailsafeTimer();
10432
+ if (this.timing.activeAdRequestToken === requestToken) {
10433
+ this.timing.activeAdRequestToken = null;
10434
+ }
10435
+ errorMessage = error === null || error === void 0 ? void 0 : error.message;
10436
+ if (this.isStale(epoch, generation)) {
10437
+ this.logOrchestratorFunnel("stale_request_result_ignored", {
10438
+ requestId: requestToken,
10439
+ source: "edge",
10440
+ errorMessage: errorMessage
10441
+ });
10442
+ return [
10443
+ 2,
10444
+ "stale"
10445
+ ];
10446
+ }
10447
+ classification = classifyEdgeVastResponse({
10448
+ podAdCount: 0,
10449
+ error: error
10450
+ });
10451
+ diag = this.requestDiagnostics.get(requestToken);
10452
+ if (diag && !diag.failureReason) diag.failureReason = "edge_".concat(classification, ": ").concat(errorMessage);
10453
+ this.markEdgeExhausted("edge_".concat(classification), {
10454
+ errorMessage: errorMessage
10455
+ });
10456
+ return [
10457
+ 2,
10458
+ "fallback"
10459
+ ];
10460
+ case 5:
10461
+ return [
10462
+ 2
10463
+ ];
10464
+ }
10465
+ });
10466
+ }).call(this);
10467
+ }
10468
+ },
10469
+ {
10470
+ key: "continueAfterEdgeOutcome",
10471
+ value: function continueAfterEdgeOutcome(outcome, epoch) {
10472
+ if (outcome !== "fallback") return;
10473
+ if (!this.inAdBreak || epoch !== this.timing.adBreakEpoch) return;
10474
+ if (this.debug) {
10475
+ console.log("[AdBreak][EDGE] No usable Edge pod; checking with GAM for the remaining break");
10476
+ }
10477
+ this.setSlotState("NEEDS_NEXT_AD", "edge_fallback");
10478
+ this.requestNextAd("edge_fallback");
10479
+ }
10480
+ },
10066
10481
  {
10067
10482
  // ───────────────────────────────────────────────────────────────
10068
10483
  // Next-ad scheduling (single flight)
@@ -10118,7 +10533,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10118
10533
  value: function getStopRequestingReason(remainingMs) {
10119
10534
  if (this.breakSource === "vmap") {
10120
10535
  if (this.adPodQueue.length === 0) return "vmap_queue_empty";
10121
- } else if (this.breakSource !== "scte35" || !this.followUpBaseVastUrl) {
10536
+ } else if (this.breakSource !== "scte35" || !this.followUpBaseVastUrl && !this.canRequestEdge()) {
10122
10537
  return "no_follow_up_source";
10123
10538
  }
10124
10539
  if (this.timing.consecutiveFailures >= this.timing.maxConsecutiveFailures) {
@@ -10130,7 +10545,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10130
10545
  if (this.timing.totalAdRequestsInBreak >= this.timing.maxTotalAdRequestsPerBreak) {
10131
10546
  return "request_cap";
10132
10547
  }
10133
- if (this.timing.isGamInCooldown()) {
10548
+ if (!this.canRequestEdge() && this.timing.isGamInCooldown()) {
10134
10549
  return "gam_cooldown";
10135
10550
  }
10136
10551
  if (this.isBreakTimeBounded() && remainingMs < this.getMinRemainingMsToRequestAd()) {
@@ -10224,10 +10639,33 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10224
10639
  key: "requestFollowUpAd",
10225
10640
  value: function requestFollowUpAd(trigger) {
10226
10641
  return _async_to_generator(function() {
10227
- var url, epoch, unused;
10642
+ var edgeUrl, epoch2, outcome, url, epoch, unused;
10228
10643
  return _ts_generator(this, function(_state) {
10229
10644
  switch(_state.label){
10230
10645
  case 0:
10646
+ if (!this.canRequestEdge()) return [
10647
+ 3,
10648
+ 2
10649
+ ];
10650
+ edgeUrl = this.prepareEdgePodRequest();
10651
+ if (!edgeUrl) {
10652
+ this.requestNextAd("".concat(trigger, ":edge_unavailable"));
10653
+ return [
10654
+ 2
10655
+ ];
10656
+ }
10657
+ epoch2 = this.timing.adBreakEpoch;
10658
+ return [
10659
+ 4,
10660
+ this.runEdgePod(edgeUrl, "edge_".concat(trigger))
10661
+ ];
10662
+ case 1:
10663
+ outcome = _state.sent();
10664
+ this.continueAfterEdgeOutcome(outcome, epoch2);
10665
+ return [
10666
+ 2
10667
+ ];
10668
+ case 2:
10231
10669
  if (this.breakSource === "vmap") {
10232
10670
  url = this.adPodQueue.shift();
10233
10671
  } else if (this.followUpBaseVastUrl) {
@@ -10238,32 +10676,32 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10238
10676
  ];
10239
10677
  this.noteVastUrlGenerated(ensureVideoAdType(url), trigger);
10240
10678
  epoch = this.timing.adBreakEpoch;
10241
- _state.label = 1;
10242
- case 1:
10679
+ _state.label = 3;
10680
+ case 3:
10243
10681
  _state.trys.push([
10244
- 1,
10245
10682
  3,
10683
+ 5,
10246
10684
  ,
10247
- 4
10685
+ 6
10248
10686
  ]);
10249
10687
  return [
10250
10688
  4,
10251
10689
  this.playSingleAd(url, trigger)
10252
10690
  ];
10253
- case 2:
10691
+ case 4:
10254
10692
  _state.sent();
10255
10693
  return [
10256
10694
  3,
10257
- 4
10695
+ 6
10258
10696
  ];
10259
- case 3:
10697
+ case 5:
10260
10698
  unused = _state.sent();
10261
10699
  this.continueAfterRequestFailure(epoch);
10262
10700
  return [
10263
10701
  3,
10264
- 4
10702
+ 6
10265
10703
  ];
10266
- case 4:
10704
+ case 6:
10267
10705
  return [
10268
10706
  2
10269
10707
  ];
@@ -10376,7 +10814,11 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10376
10814
  case "gam_http_request_sent":
10377
10815
  diag.gamRequestSent++;
10378
10816
  break;
10817
+ case "edge_http_request_sent":
10818
+ diag.edgeRequestSent++;
10819
+ break;
10379
10820
  case "gam_response_received":
10821
+ case "edge_response_received":
10380
10822
  diag.vastHttpStatus = payload.httpStatus;
10381
10823
  break;
10382
10824
  case "vast_parsed":
@@ -10563,6 +11005,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10563
11005
  {
10564
11006
  key: "beginFunnelRequest",
10565
11007
  value: function beginFunnelRequest(adPlayer, requestToken, trigger) {
11008
+ var source = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : "gam";
10566
11009
  var _adPlayer_setFunnelContext;
10567
11010
  if (this.controllerCallInFlight) {
10568
11011
  this.logOrchestratorFunnel("duplicate_request_detected", {
@@ -10577,7 +11020,9 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10577
11020
  requestId: requestToken,
10578
11021
  controllerId: this.controllerGeneration,
10579
11022
  trigger: trigger,
11023
+ source: source,
10580
11024
  gamRequestSent: 0,
11025
+ edgeRequestSent: 0,
10581
11026
  wrapperDepth: 0,
10582
11027
  inlineResolved: false,
10583
11028
  mediaCandidateCount: 0,
@@ -10708,6 +11153,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10708
11153
  this.timing.activeAdRequestToken = requestToken;
10709
11154
  ap = this.host.getAdPlayer();
10710
11155
  budgetedUrl = this.withCurrentPodBudget(vastTagUrl);
11156
+ this.currentPodSource = "gam";
10711
11157
  this.setSlotState("REQUESTING", trigger);
10712
11158
  this.beginFunnelRequest(ap, requestToken, trigger);
10713
11159
  requestUrl = this.applyOpportunityFloor(budgetedUrl);
@@ -10855,6 +11301,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10855
11301
  requests: requests,
10856
11302
  requestRetries: requestRetries,
10857
11303
  gamResponses: count("gam_response_received"),
11304
+ edgeRequests: count("edge_request_sent"),
11305
+ edgeFills: count("edge_fill"),
11306
+ edgeEmptySentinels: count("edge_empty_sentinel"),
11307
+ edgeFallbacks: countPrefix("edge_fallback:"),
10858
11308
  requestsSuppressed: count("request_suppressed"),
10859
11309
  duplicates: count("duplicate_request_detected") + count("duplicate_break_start"),
10860
11310
  filled: count("vast_received"),
@@ -10951,6 +11401,7 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
10951
11401
  this.breakSource = void 0;
10952
11402
  this.followUpBaseVastUrl = void 0;
10953
11403
  this.unusableResponsesInBreak = 0;
11404
+ this.resetEdgeStateForBreak();
10954
11405
  adPlayer.stop().catch(function() {});
10955
11406
  if (!alreadyEnded) this.logBreakFunnel(reason);
10956
11407
  this.opportunityFloor = void 0;
@@ -11264,7 +11715,13 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
11264
11715
  });
11265
11716
  return;
11266
11717
  }
11267
- this.timing.consecutiveFailures++;
11718
+ if (this.currentPodSource === "edge") {
11719
+ this.markEdgeExhausted("edge_playback_failed", {
11720
+ reason: reason
11721
+ });
11722
+ } else {
11723
+ this.timing.consecutiveFailures++;
11724
+ }
11268
11725
  var diag = this.currentRequestId != null ? this.requestDiagnostics.get(this.currentRequestId) : void 0;
11269
11726
  if (diag && !diag.failureReason) diag.failureReason = reason;
11270
11727
  if (this.debug) {
@@ -11294,7 +11751,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11294
11751
  if (this.config.adFloorMaxCents != null) floorBounds.maxCents = this.config.adFloorMaxCents;
11295
11752
  if (this.config.adFloorStepCents != null) floorBounds.stepCents = this.config.adFloorStepCents;
11296
11753
  this.floorLadder = new FloorLadderController(this.config.adFloorLadder, floorBounds);
11754
+ this.floorLadderEnabled = this.config.adFloorLadderEnabled === true;
11297
11755
  this.warnOnInvalidFloorLadder(this.floorLadder.validate());
11756
+ this.edgePodBaseUrl = resolveEdgePodBaseUrl(this.config);
11298
11757
  this.adPlayer = this.createAdPlayer(false);
11299
11758
  this.palNonce = createPalNonceManager();
11300
11759
  this.cueManager = new Scte35CueManager(!!this.config.debugAdTiming, {
@@ -11394,11 +11853,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11394
11853
  generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
11395
11854
  return _this.generatePodVastUrl(base, breakDurationMs);
11396
11855
  },
11856
+ getEdgePodBaseUrl: function getEdgePodBaseUrl() {
11857
+ return _this.edgePodBaseUrl;
11858
+ },
11397
11859
  getFloorSnapshot: function getFloorSnapshot(position) {
11398
- return _this.floorLadder.snapshotFor({
11860
+ return _this.floorLadderEnabled ? _this.floorLadder.snapshotFor({
11399
11861
  position: position,
11400
11862
  isCtv: _this.isCtvEnvironment()
11401
- });
11863
+ }) : void 0;
11402
11864
  },
11403
11865
  onAdClick: function onAdClick() {
11404
11866
  return _this.palNonce.sendAdClick();
@@ -11449,11 +11911,24 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
11449
11911
  return report;
11450
11912
  }
11451
11913
  },
11914
+ {
11915
+ key: "setAdFloorLadderEnabled",
11916
+ value: function setAdFloorLadderEnabled(enabled) {
11917
+ this.floorLadderEnabled = enabled;
11918
+ if (enabled) this.warnOnInvalidFloorLadder(this.floorLadder.validate());
11919
+ }
11920
+ },
11921
+ {
11922
+ key: "isAdFloorLadderEnabled",
11923
+ value: function isAdFloorLadderEnabled() {
11924
+ return this.floorLadderEnabled;
11925
+ }
11926
+ },
11452
11927
  {
11453
11928
  key: "warnOnInvalidFloorLadder",
11454
11929
  value: function warnOnInvalidFloorLadder(report) {
11455
11930
  var config = this.floorLadder.get();
11456
- if (report.ok || !config.enabled) return;
11931
+ if (report.ok || !this.floorLadderEnabled || !config.enabled) return;
11457
11932
  console.warn("[AdBreak][FLOOR] configuration has issues; invalid floors will not be sent", {
11458
11933
  errors: report.errors,
11459
11934
  configurationVersion: config.configurationVersion,
@@ -12186,6 +12661,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
12186
12661
  this.timing.destroy();
12187
12662
  this.adBreak.clearPendingAdBreak();
12188
12663
  this.placeholder.destroy();
12664
+ 0;
12189
12665
  if (this.timeUpdateHandler) {
12190
12666
  this.video.removeEventListener("timeupdate", this.timeUpdateHandler);
12191
12667
  delete this.timeUpdateHandler;
@@ -12286,12 +12762,14 @@ var CRITICAL_PROPS = [
12286
12762
  "ctvAdRequest",
12287
12763
  "adFloorMinCents",
12288
12764
  "adFloorMaxCents",
12289
- "adFloorStepCents"
12765
+ "adFloorStepCents",
12766
+ "enableEdgePodRequest",
12767
+ "edgePodUrl"
12290
12768
  ];
12291
12769
  var CONTROLS_HIDE_DELAY = 3e3;
12292
12770
  var DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;
12293
12771
  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, [
12772
+ 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
12773
  "src",
12296
12774
  "autoplay",
12297
12775
  "muted",
@@ -12328,10 +12806,13 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12328
12806
  "minRemainingMsToStartAd",
12329
12807
  "minRemainingMsToRequestAd",
12330
12808
  "maxNoFillsPerBreak",
12809
+ "adFloorLadderEnabled",
12331
12810
  "adFloorLadder",
12332
12811
  "adFloorMinCents",
12333
12812
  "adFloorMaxCents",
12334
- "adFloorStepCents"
12813
+ "adFloorStepCents",
12814
+ "enableEdgePodRequest",
12815
+ "edgePodUrl"
12335
12816
  ]);
12336
12817
  var adFloorLadderKey = JSON.stringify(adFloorLadder !== null && adFloorLadder !== void 0 ? adFloorLadder : null);
12337
12818
  var videoRef = (0, import_react.useRef)(null);
@@ -12482,7 +12963,9 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12482
12963
  vastMode,
12483
12964
  adFloorMinCents,
12484
12965
  adFloorMaxCents,
12485
- adFloorStepCents
12966
+ adFloorStepCents,
12967
+ enableEdgePodRequest,
12968
+ edgePodUrl
12486
12969
  ]);
12487
12970
  (0, import_react.useEffect)(function() {
12488
12971
  if (typeof window === "undefined") return;
@@ -12532,10 +13015,13 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12532
13015
  if (minRemainingMsToStartAd !== void 0) cfg.minRemainingMsToStartAd = minRemainingMsToStartAd;
12533
13016
  if (minRemainingMsToRequestAd !== void 0) cfg.minRemainingMsToRequestAd = minRemainingMsToRequestAd;
12534
13017
  if (maxNoFillsPerBreak !== void 0) cfg.maxNoFillsPerBreak = maxNoFillsPerBreak;
13018
+ if (adFloorLadderEnabled !== void 0) cfg.adFloorLadderEnabled = adFloorLadderEnabled;
12535
13019
  if (adFloorLadder !== void 0) cfg.adFloorLadder = adFloorLadder;
12536
13020
  if (adFloorMinCents !== void 0) cfg.adFloorMinCents = adFloorMinCents;
12537
13021
  if (adFloorMaxCents !== void 0) cfg.adFloorMaxCents = adFloorMaxCents;
12538
13022
  if (adFloorStepCents !== void 0) cfg.adFloorStepCents = adFloorStepCents;
13023
+ if (enableEdgePodRequest !== void 0) cfg.enableEdgePodRequest = enableEdgePodRequest;
13024
+ if (edgePodUrl !== void 0) cfg.edgePodUrl = edgePodUrl;
12539
13025
  var player = new StormcloudVideoPlayer(cfg);
12540
13026
  playerRef.current = player;
12541
13027
  appliedFloorLadderKeyRef.current = adFloorLadderKey;
@@ -12584,6 +13070,14 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
12584
13070
  }, [
12585
13071
  adFloorLadderKey
12586
13072
  ]);
13073
+ (0, import_react.useEffect)(function() {
13074
+ if (!playerRef.current) return;
13075
+ var enabled = adFloorLadderEnabled === true;
13076
+ if (playerRef.current.isAdFloorLadderEnabled() === enabled) return;
13077
+ playerRef.current.setAdFloorLadderEnabled(enabled);
13078
+ }, [
13079
+ adFloorLadderEnabled
13080
+ ]);
12587
13081
  (0, import_react.useEffect)(function() {
12588
13082
  if (!playerRef.current) return;
12589
13083
  var checkAdStatus = function checkAdStatus() {
@@ -13660,6 +14154,9 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
13660
14154
  }
13661
14155
  }
13662
14156
  }
14157
+ if (prevProps.adFloorLadderEnabled !== nextProps.adFloorLadderEnabled) {
14158
+ return false;
14159
+ }
13663
14160
  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
14161
  return false;
13665
14162
  }