stormcloud-video-player 0.3.55 → 0.3.57

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.
@@ -692,7 +692,7 @@ function createImaController(video, options) {
692
692
  adVideo.style.height = "100%";
693
693
  adVideo.style.objectFit = "contain";
694
694
  adVideo.style.backgroundColor = "transparent";
695
- adVideo.style.zIndex = "15";
695
+ adVideo.style.zIndex = "2";
696
696
  adVideo.playsInline = true;
697
697
  adVideo.volume = originalVolume;
698
698
  adVideo.muted = originalMutedState;
@@ -985,7 +985,7 @@ function createImaController(video, options) {
985
985
  container.style.alignItems = "center";
986
986
  container.style.justifyContent = "center";
987
987
  container.style.pointerEvents = "none";
988
- container.style.zIndex = "10";
988
+ container.style.zIndex = "30";
989
989
  container.style.backgroundColor = "#000";
990
990
  container.style.transition = "opacity 0.3s ease-in-out";
991
991
  container.style.opacity = "0";
@@ -1100,7 +1100,7 @@ function createImaController(video, options) {
1100
1100
  container.style.alignItems = "center";
1101
1101
  container.style.justifyContent = "center";
1102
1102
  container.style.pointerEvents = "none";
1103
- container.style.zIndex = "10";
1103
+ container.style.zIndex = "30";
1104
1104
  container.style.backgroundColor = "transparent";
1105
1105
  container.style.transition = "opacity 0.3s ease-in-out, background-color 0.3s ease-in-out";
1106
1106
  container.style.opacity = "0";
@@ -2015,7 +2015,7 @@ function createHlsAdPlayer(contentVideo, options) {
2015
2015
  container.style.alignItems = "center";
2016
2016
  container.style.justifyContent = "center";
2017
2017
  container.style.pointerEvents = "none";
2018
- container.style.zIndex = "10";
2018
+ container.style.zIndex = "30";
2019
2019
  container.style.backgroundColor = "#000";
2020
2020
  (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
2021
2021
  adContainerEl = container;
@@ -3239,6 +3239,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3239
3239
  this.inAdBreak = false;
3240
3240
  this.ptsDriftEmaMs = 0;
3241
3241
  this.adPodQueue = [];
3242
+ this.vmapBreaks = [];
3243
+ this.consumedVmapBreakIds = /* @__PURE__ */ new Set();
3242
3244
  this.lastHeartbeatTime = 0;
3243
3245
  this.currentAdIndex = 0;
3244
3246
  this.totalAdsInBreak = 0;
@@ -3793,13 +3795,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3793
3795
  _this.activeAdRequestToken = null;
3794
3796
  _this.showAds = true;
3795
3797
  _this.resetGamNoFillCounter();
3796
- if (_this.inAdBreak && _this.expectedAdBreakDurationMs != null) {
3797
- if (_this.adStopTimerId == null) {
3798
- _this.currentAdBreakStartWallClockMs = Date.now();
3799
- _this.scheduleAdStopCountdown(_this.expectedAdBreakDurationMs);
3800
- if (_this.config.debugAdTiming) {
3801
- console.log("[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)");
3802
- }
3798
+ if (_this.inAdBreak && _this.expectedAdBreakDurationMs != null && _this.adStopTimerId == null) {
3799
+ _this.scheduleAdStopCountdown(_this.getRemainingAdMs());
3800
+ if (_this.config.debugAdTiming) {
3801
+ console.log("[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)");
3803
3802
  }
3804
3803
  }
3805
3804
  var currentMuted = _this.video.muted;
@@ -3862,6 +3861,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3862
3861
  this.ima.showPlaceholder();
3863
3862
  this.isShowingPlaceholder = true;
3864
3863
  }
3864
+ var preservedMutedState = this.ima.getOriginalMutedState();
3865
+ var preservedVolumeState = this.ima.getOriginalVolume();
3865
3866
  if (this.ima) {
3866
3867
  try {
3867
3868
  this.ima.destroy();
@@ -3876,7 +3877,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3876
3877
  var continueLiveStreamDuringAds = this.shouldContinueLiveStreamDuringAds();
3877
3878
  this.ima = this.createAdPlayer(continueLiveStreamDuringAds);
3878
3879
  this.ima.initialize();
3879
- this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
3880
+ this.ima.updateOriginalMutedState(preservedMutedState, preservedVolumeState);
3880
3881
  this.attachImaEventListeners();
3881
3882
  if (shouldShowPlaceholder) {
3882
3883
  this.showPlaceholderLayer();
@@ -4192,12 +4193,17 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4192
4193
  }
4193
4194
  }
4194
4195
  if (this.inAdBreak) {
4195
- if (this.expectedAdBreakDurationMs == null && marker.durationSeconds != null) {
4196
- this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;
4197
- if (this.config.debugAdTiming) {
4198
- console.log("[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ".concat(this.expectedAdBreakDurationMs, "ms"));
4196
+ if (marker.durationSeconds != null) {
4197
+ var newDurationMs = marker.durationSeconds * 1e3;
4198
+ if (this.expectedAdBreakDurationMs == null || newDurationMs > this.expectedAdBreakDurationMs) {
4199
+ this.expectedAdBreakDurationMs = newDurationMs;
4200
+ var elapsedMs = this.currentAdBreakStartWallClockMs != null ? Date.now() - this.currentAdBreakStartWallClockMs : 0;
4201
+ var remainingMs = Math.max(0, newDurationMs - elapsedMs);
4202
+ this.scheduleAdStopCountdown(remainingMs);
4203
+ if (this.config.debugAdTiming) {
4204
+ console.log("[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ".concat(newDurationMs, "ms, remaining: ").concat(remainingMs, "ms"));
4205
+ }
4199
4206
  }
4200
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
4201
4207
  }
4202
4208
  return;
4203
4209
  }
@@ -4273,9 +4279,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4273
4279
  this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;
4274
4280
  }
4275
4281
  if (this.expectedAdBreakDurationMs != null && this.currentAdBreakStartWallClockMs != null) {
4276
- var elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;
4277
- var remainingMs = Math.max(0, this.expectedAdBreakDurationMs - elapsedMs);
4278
- this.scheduleAdStopCountdown(remainingMs);
4282
+ var elapsedMs1 = Date.now() - this.currentAdBreakStartWallClockMs;
4283
+ var remainingMs1 = Math.max(0, this.expectedAdBreakDurationMs - elapsedMs1);
4284
+ this.scheduleAdStopCountdown(remainingMs1);
4279
4285
  }
4280
4286
  if (!this.ima.isAdPlaying() && this.activeAdRequestToken === null && this.adRequestQueue.length > 0) {
4281
4287
  this.tryNextAvailableAdWithRateLimit();
@@ -4567,6 +4573,18 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4567
4573
  return _ts_generator(this, function(_state) {
4568
4574
  switch(_state.label){
4569
4575
  case 0:
4576
+ if (!this.config.vmapUrl) return [
4577
+ 3,
4578
+ 2
4579
+ ];
4580
+ return [
4581
+ 4,
4582
+ this.fetchAndParseVmap(this.config.vmapUrl)
4583
+ ];
4584
+ case 1:
4585
+ _state.sent();
4586
+ _state.label = 2;
4587
+ case 2:
4570
4588
  vastMode = this.config.vastMode || "default";
4571
4589
  if (this.config.debugAdTiming) {
4572
4590
  console.log("[StormcloudVideoPlayer] VAST mode:", vastMode);
@@ -4612,7 +4630,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4612
4630
  headers: headers
4613
4631
  })
4614
4632
  ];
4615
- case 1:
4633
+ case 3:
4616
4634
  response = _state.sent();
4617
4635
  if (!response.ok) {
4618
4636
  if (this.config.debugAdTiming) {
@@ -4626,7 +4644,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4626
4644
  4,
4627
4645
  response.json()
4628
4646
  ];
4629
- case 2:
4647
+ case 4:
4630
4648
  data = _state.sent();
4631
4649
  imaPayload = (_data_response = data.response) === null || _data_response === void 0 ? void 0 : (_data_response_ima = _data_response.ima) === null || _data_response_ima === void 0 ? void 0 : (_data_response_ima_publisherdeskima = _data_response_ima["publisherdesk.ima"]) === null || _data_response_ima_publisherdeskima === void 0 ? void 0 : _data_response_ima_publisherdeskima.payload;
4632
4650
  if (imaPayload) {
@@ -4654,6 +4672,171 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4654
4672
  }).call(this);
4655
4673
  }
4656
4674
  },
4675
+ {
4676
+ key: "fetchAndParseVmap",
4677
+ value: function fetchAndParseVmap(vmapUrl) {
4678
+ return _async_to_generator(function() {
4679
+ var response, vmapXml, error;
4680
+ return _ts_generator(this, function(_state) {
4681
+ switch(_state.label){
4682
+ case 0:
4683
+ if (!vmapUrl.trim()) {
4684
+ return [
4685
+ 2
4686
+ ];
4687
+ }
4688
+ _state.label = 1;
4689
+ case 1:
4690
+ _state.trys.push([
4691
+ 1,
4692
+ 4,
4693
+ ,
4694
+ 5
4695
+ ]);
4696
+ return [
4697
+ 4,
4698
+ fetch(vmapUrl)
4699
+ ];
4700
+ case 2:
4701
+ response = _state.sent();
4702
+ if (!response.ok) {
4703
+ throw new Error("Failed to fetch VMAP (".concat(response.status, ")"));
4704
+ }
4705
+ return [
4706
+ 4,
4707
+ response.text()
4708
+ ];
4709
+ case 3:
4710
+ vmapXml = _state.sent();
4711
+ this.vmapBreaks = this.parseVmapToBreaks(vmapXml);
4712
+ this.consumedVmapBreakIds.clear();
4713
+ if (this.config.debugAdTiming) {
4714
+ console.log("[StormcloudVideoPlayer] Loaded ".concat(this.vmapBreaks.length, " VMAP ad break(s) from:"), vmapUrl);
4715
+ }
4716
+ return [
4717
+ 3,
4718
+ 5
4719
+ ];
4720
+ case 4:
4721
+ error = _state.sent();
4722
+ this.vmapBreaks = [];
4723
+ this.consumedVmapBreakIds.clear();
4724
+ if (this.config.debugAdTiming) {
4725
+ console.warn("[StormcloudVideoPlayer] Failed to load VMAP:", error);
4726
+ }
4727
+ return [
4728
+ 3,
4729
+ 5
4730
+ ];
4731
+ case 5:
4732
+ return [
4733
+ 2
4734
+ ];
4735
+ }
4736
+ });
4737
+ }).call(this);
4738
+ }
4739
+ },
4740
+ {
4741
+ key: "parseVmapToBreaks",
4742
+ value: function parseVmapToBreaks(vmapXml) {
4743
+ var _this = this;
4744
+ if (typeof DOMParser === "undefined") {
4745
+ return [];
4746
+ }
4747
+ var doc = new DOMParser().parseFromString(vmapXml, "application/xml");
4748
+ if (doc.querySelector("parsererror")) {
4749
+ if (this.config.debugAdTiming) {
4750
+ console.warn("[StormcloudVideoPlayer] Invalid VMAP XML received");
4751
+ }
4752
+ return [];
4753
+ }
4754
+ var adBreakNodes = Array.from(doc.querySelectorAll("AdBreak, vmap\\:AdBreak"));
4755
+ var parsed = [];
4756
+ adBreakNodes.forEach(function(node, index) {
4757
+ var timeOffsetRaw = (node.getAttribute("timeOffset") || "").trim();
4758
+ var startTimeMs = _this.parseVmapTimeOffsetToMs(timeOffsetRaw);
4759
+ if (startTimeMs == null) {
4760
+ return;
4761
+ }
4762
+ var adTagNode = node.querySelector("AdTagURI, vmap\\:AdTagURI");
4763
+ var adTagUrl = ((adTagNode === null || adTagNode === void 0 ? void 0 : adTagNode.textContent) || "").trim();
4764
+ if (!adTagUrl) {
4765
+ return;
4766
+ }
4767
+ var breakId = node.getAttribute("breakId") || "vmap-break-".concat(index, "-").concat(timeOffsetRaw || "unknown");
4768
+ parsed.push({
4769
+ id: breakId,
4770
+ startTimeMs: startTimeMs,
4771
+ vastTagUrl: adTagUrl
4772
+ });
4773
+ });
4774
+ parsed.sort(function(a, b) {
4775
+ var aStart = a.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : a.startTimeMs;
4776
+ var bStart = b.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : b.startTimeMs;
4777
+ return aStart - bStart;
4778
+ });
4779
+ return parsed;
4780
+ }
4781
+ },
4782
+ {
4783
+ key: "parseVmapTimeOffsetToMs",
4784
+ value: function parseVmapTimeOffsetToMs(timeOffset) {
4785
+ if (!timeOffset) {
4786
+ return void 0;
4787
+ }
4788
+ var normalized = timeOffset.trim().toLowerCase();
4789
+ if (normalized === "start") {
4790
+ return 0;
4791
+ }
4792
+ if (normalized === "end") {
4793
+ return -1;
4794
+ }
4795
+ var hms = timeOffset.match(/^(\d{1,2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?$/);
4796
+ if (hms) {
4797
+ var _hms = _sliced_to_array(hms, 5), hh = _hms[1], mm = _hms[2], ss = _hms[3], tmp = _hms[4], ms = tmp === void 0 ? "0" : tmp;
4798
+ var hours = Number(hh);
4799
+ var minutes = Number(mm);
4800
+ var seconds = Number(ss);
4801
+ var millis = Number(ms.padEnd(3, "0").slice(0, 3));
4802
+ return (hours * 3600 + minutes * 60 + seconds) * 1e3 + millis;
4803
+ }
4804
+ var percent = timeOffset.match(/^(\d+(?:\.\d+)?)%$/);
4805
+ if (percent) {
4806
+ var ratio = Number(percent[1]) / 100;
4807
+ var durationSec = this.video.duration;
4808
+ if (Number.isFinite(durationSec) && durationSec > 0) {
4809
+ return Math.floor(durationSec * 1e3 * ratio);
4810
+ }
4811
+ return void 0;
4812
+ }
4813
+ return void 0;
4814
+ }
4815
+ },
4816
+ {
4817
+ key: "getAdBreakKey",
4818
+ value: function getAdBreakKey(adBreak) {
4819
+ if (adBreak.id) {
4820
+ return adBreak.id;
4821
+ }
4822
+ return "".concat(adBreak.startTimeMs, "-").concat(adBreak.vastTagUrl || "");
4823
+ }
4824
+ },
4825
+ {
4826
+ key: "resolveBreakStartMs",
4827
+ value: function resolveBreakStartMs(adBreak) {
4828
+ if (adBreak.startTimeMs >= 0) {
4829
+ return adBreak.startTimeMs;
4830
+ }
4831
+ if (adBreak.startTimeMs === -1) {
4832
+ var durationSec = this.video.duration;
4833
+ if (Number.isFinite(durationSec) && durationSec > 0) {
4834
+ return Math.floor(durationSec * 1e3);
4835
+ }
4836
+ }
4837
+ return void 0;
4838
+ }
4839
+ },
4657
4840
  {
4658
4841
  key: "getCurrentAdIndex",
4659
4842
  value: function getCurrentAdIndex() {
@@ -4666,6 +4849,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4666
4849
  return this.totalAdsInBreak;
4667
4850
  }
4668
4851
  },
4852
+ {
4853
+ key: "getAdRemainingMs",
4854
+ value: function getAdRemainingMs() {
4855
+ return this.getRemainingAdMs();
4856
+ }
4857
+ },
4669
4858
  {
4670
4859
  key: "generateVastUrlsWithCorrelators",
4671
4860
  value: function generateVastUrlsWithCorrelators(baseUrl, count) {
@@ -4744,10 +4933,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4744
4933
  var scheduled = this.findCurrentOrNextBreak(this.video.currentTime * 1e3);
4745
4934
  var tags = this.selectVastTagsForBreak(scheduled);
4746
4935
  var baseVastUrl;
4747
- if (this.apiVastTagUrl) {
4748
- baseVastUrl = this.apiVastTagUrl;
4749
- } else if (tags && tags.length > 0 && tags[0]) {
4936
+ if (tags && tags.length > 0 && tags[0]) {
4750
4937
  baseVastUrl = tags[0];
4938
+ } else if (this.apiVastTagUrl) {
4939
+ baseVastUrl = this.apiVastTagUrl;
4751
4940
  } else {
4752
4941
  if (this.config.debugAdTiming) {
4753
4942
  console.warn("[StormcloudVideoPlayer] No VAST URL available for prefetch");
@@ -5197,11 +5386,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5197
5386
  switch(_state.label){
5198
5387
  case 0:
5199
5388
  scheduled = this.findCurrentOrNextBreak(this.video.currentTime * 1e3);
5389
+ if (scheduled) {
5390
+ this.consumedVmapBreakIds.add(this.getAdBreakKey(scheduled));
5391
+ }
5200
5392
  tags = this.selectVastTagsForBreak(scheduled);
5201
- if (this.apiVastTagUrl) {
5202
- baseVastUrl = this.apiVastTagUrl;
5203
- } else if (tags && tags.length > 0 && tags[0]) {
5393
+ if (tags && tags.length > 0 && tags[0]) {
5204
5394
  baseVastUrl = tags[0];
5395
+ } else if (this.apiVastTagUrl) {
5396
+ baseVastUrl = this.apiVastTagUrl;
5205
5397
  } else {
5206
5398
  this.clearPendingAdBreak();
5207
5399
  return [
@@ -5315,9 +5507,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5315
5507
  ];
5316
5508
  case 2:
5317
5509
  _state.sent();
5318
- if (this.expectedAdBreakDurationMs != null) {
5319
- this.currentAdBreakStartWallClockMs = Date.now();
5320
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
5510
+ if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
5511
+ this.scheduleAdStopCountdown(this.getRemainingAdMs());
5321
5512
  }
5322
5513
  adVolume = currentMuted ? 0 : currentVolume;
5323
5514
  this.ima.setAdVolume(adVolume);
@@ -5358,9 +5549,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5358
5549
  ];
5359
5550
  case 6:
5360
5551
  _state.sent();
5361
- if (this.expectedAdBreakDurationMs != null) {
5362
- this.currentAdBreakStartWallClockMs = Date.now();
5363
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
5552
+ if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
5553
+ this.scheduleAdStopCountdown(this.getRemainingAdMs());
5364
5554
  }
5365
5555
  adVolume1 = currentMuted ? 0 : currentVolume;
5366
5556
  this.ima.setAdVolume(adVolume1);
@@ -5414,9 +5604,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5414
5604
  ];
5415
5605
  case 10:
5416
5606
  _state.sent();
5417
- if (this.expectedAdBreakDurationMs != null) {
5418
- this.currentAdBreakStartWallClockMs = Date.now();
5419
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
5607
+ if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
5608
+ this.scheduleAdStopCountdown(this.getRemainingAdMs());
5420
5609
  }
5421
5610
  adVolume2 = currentMuted ? 0 : currentVolume;
5422
5611
  this.ima.setAdVolume(adVolume2);
@@ -5767,8 +5956,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5767
5956
  case 2:
5768
5957
  _state.sent();
5769
5958
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
5770
- this.currentAdBreakStartWallClockMs = Date.now();
5771
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
5959
+ this.scheduleAdStopCountdown(this.getRemainingAdMs());
5772
5960
  }
5773
5961
  currentMuted = this.video.muted;
5774
5962
  currentVolume = this.video.volume;
@@ -6080,15 +6268,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6080
6268
  {
6081
6269
  key: "findCurrentOrNextBreak",
6082
6270
  value: function findCurrentOrNextBreak(nowMs) {
6083
- var schedule = [];
6271
+ var schedule = this.vmapBreaks;
6084
6272
  var candidate;
6085
6273
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
6086
6274
  try {
6087
6275
  for(var _iterator = schedule[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
6088
6276
  var b = _step.value;
6089
- var _this_config_driftToleranceMs;
6277
+ var _this_config_driftToleranceMs, _this_resolveBreakStartMs;
6278
+ if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {
6279
+ continue;
6280
+ }
6281
+ var breakStartMs = this.resolveBreakStartMs(b);
6282
+ if (breakStartMs == null) {
6283
+ continue;
6284
+ }
6090
6285
  var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
6091
- if (b.startTimeMs <= nowMs + tol && (candidate == null || b.startTimeMs > (candidate.startTimeMs || 0))) {
6286
+ if (breakStartMs <= nowMs + tol && (candidate == null || breakStartMs > ((_this_resolveBreakStartMs = this.resolveBreakStartMs(candidate)) !== null && _this_resolveBreakStartMs !== void 0 ? _this_resolveBreakStartMs : 0))) {
6092
6287
  candidate = b;
6093
6288
  }
6094
6289
  }
@@ -6112,11 +6307,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6112
6307
  {
6113
6308
  key: "onTimeUpdate",
6114
6309
  value: function onTimeUpdate(currentTimeSec) {
6115
- if (this.ima.isAdPlaying()) return;
6310
+ var _this = this;
6311
+ if (this.ima.isAdPlaying() || this.inAdBreak) return;
6116
6312
  var nowMs = currentTimeSec * 1e3;
6117
6313
  var breakToPlay = this.findBreakForTime(nowMs);
6118
6314
  if (breakToPlay) {
6119
- this.handleMidAdJoin(breakToPlay, nowMs);
6315
+ void this.handleMidAdJoin(breakToPlay, nowMs).catch(function(error) {
6316
+ if (_this.config.debugAdTiming) {
6317
+ console.warn("[StormcloudVideoPlayer] Mid-roll VMAP join failed gracefully:", error);
6318
+ }
6319
+ });
6120
6320
  }
6121
6321
  }
6122
6322
  },
@@ -6124,40 +6324,76 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6124
6324
  key: "handleMidAdJoin",
6125
6325
  value: function handleMidAdJoin(adBreak, nowMs) {
6126
6326
  return _async_to_generator(function() {
6127
- var _adBreak_durationMs, durationMs, endMs, remainingMs, tags, first, rest;
6327
+ var _adBreak_durationMs, _this_config_driftToleranceMs, key, breakStartMs, durationMs, endMs, tol, inWindow, remainingMs, tags, first, rest, error;
6128
6328
  return _ts_generator(this, function(_state) {
6129
6329
  switch(_state.label){
6130
6330
  case 0:
6331
+ key = this.getAdBreakKey(adBreak);
6332
+ if (this.consumedVmapBreakIds.has(key)) {
6333
+ return [
6334
+ 2
6335
+ ];
6336
+ }
6337
+ breakStartMs = this.resolveBreakStartMs(adBreak);
6338
+ if (breakStartMs == null) {
6339
+ return [
6340
+ 2
6341
+ ];
6342
+ }
6131
6343
  durationMs = (_adBreak_durationMs = adBreak.durationMs) !== null && _adBreak_durationMs !== void 0 ? _adBreak_durationMs : 0;
6132
- endMs = adBreak.startTimeMs + durationMs;
6133
- if (!(durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs)) return [
6344
+ endMs = breakStartMs + durationMs;
6345
+ tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
6346
+ inWindow = durationMs > 0 ? nowMs > breakStartMs && nowMs < endMs : nowMs + tol >= breakStartMs;
6347
+ if (!inWindow) return [
6134
6348
  3,
6135
- 2
6349
+ 4
6136
6350
  ];
6137
- remainingMs = endMs - nowMs;
6351
+ this.consumedVmapBreakIds.add(key);
6352
+ remainingMs = durationMs > 0 ? Math.max(0, endMs - nowMs) : 0;
6138
6353
  tags = this.selectVastTagsForBreak(adBreak) || (this.apiVastTagUrl ? [
6139
6354
  this.apiVastTagUrl
6140
6355
  ] : void 0);
6141
6356
  if (!(tags && tags.length > 0)) return [
6142
6357
  3,
6143
- 2
6358
+ 4
6144
6359
  ];
6145
6360
  first = tags[0];
6146
6361
  rest = tags.slice(1);
6147
6362
  this.adPodQueue = rest;
6148
6363
  this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
6364
+ _state.label = 1;
6365
+ case 1:
6366
+ _state.trys.push([
6367
+ 1,
6368
+ 3,
6369
+ ,
6370
+ 4
6371
+ ]);
6149
6372
  return [
6150
6373
  4,
6151
6374
  this.playSingleAd(first)
6152
6375
  ];
6153
- case 1:
6376
+ case 2:
6154
6377
  _state.sent();
6155
6378
  this.inAdBreak = true;
6156
6379
  this.expectedAdBreakDurationMs = remainingMs;
6157
6380
  this.currentAdBreakStartWallClockMs = Date.now();
6158
6381
  this.scheduleAdStopCountdown(remainingMs);
6159
- _state.label = 2;
6160
- case 2:
6382
+ return [
6383
+ 3,
6384
+ 4
6385
+ ];
6386
+ case 3:
6387
+ error = _state.sent();
6388
+ this.adPodQueue = [];
6389
+ if (this.config.debugAdTiming) {
6390
+ console.warn("[StormcloudVideoPlayer] Mid-roll VMAP ad request failed:", error);
6391
+ }
6392
+ return [
6393
+ 3,
6394
+ 4
6395
+ ];
6396
+ case 4:
6161
6397
  return [
6162
6398
  2
6163
6399
  ];
@@ -6473,8 +6709,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6473
6709
  case 5:
6474
6710
  _state.sent();
6475
6711
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
6476
- this.currentAdBreakStartWallClockMs = Date.now();
6477
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
6712
+ this.scheduleAdStopCountdown(this.getRemainingAdMs());
6478
6713
  }
6479
6714
  currentMuted = this.video.muted;
6480
6715
  currentVolume = this.video.volume;
@@ -6524,8 +6759,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6524
6759
  case 8:
6525
6760
  _state.sent();
6526
6761
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
6527
- this.currentAdBreakStartWallClockMs = Date.now();
6528
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
6762
+ this.scheduleAdStopCountdown(this.getRemainingAdMs());
6529
6763
  }
6530
6764
  currentMuted1 = this.video.muted;
6531
6765
  currentVolume1 = this.video.volume;
@@ -6863,13 +7097,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6863
7097
  {
6864
7098
  key: "findBreakForTime",
6865
7099
  value: function findBreakForTime(nowMs) {
6866
- var schedule = [];
7100
+ var _this_config_driftToleranceMs;
7101
+ var schedule = this.vmapBreaks;
7102
+ var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
6867
7103
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
6868
7104
  try {
6869
7105
  for(var _iterator = schedule[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
6870
7106
  var b = _step.value;
6871
- var end = (b.startTimeMs || 0) + (b.durationMs || 0);
6872
- if (nowMs >= (b.startTimeMs || 0) && (b.durationMs ? nowMs < end : true)) {
7107
+ if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {
7108
+ continue;
7109
+ }
7110
+ var breakStartMs = this.resolveBreakStartMs(b);
7111
+ if (breakStartMs == null) {
7112
+ continue;
7113
+ }
7114
+ var end = breakStartMs + (b.durationMs || 0);
7115
+ if (nowMs >= breakStartMs && (b.durationMs ? nowMs < end : nowMs <= breakStartMs + tol)) {
6873
7116
  return b;
6874
7117
  }
6875
7118
  }
@@ -7101,13 +7344,15 @@ var CRITICAL_PROPS = [
7101
7344
  "src",
7102
7345
  "allowNativeHls",
7103
7346
  "licenseKey",
7347
+ "vmapUrl",
7104
7348
  "lowLatencyMode",
7105
7349
  "driftToleranceMs",
7106
7350
  "vastMode"
7107
7351
  ];
7108
7352
  var CONTROLS_HIDE_DELAY = 3e3;
7353
+ var DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;
7109
7354
  var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7110
- var src = props.src, autoplay = props.autoplay, muted = props.muted, lowLatencyMode = props.lowLatencyMode, allowNativeHls = props.allowNativeHls, 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, adPlayerType = props.adPlayerType, minSegmentsBeforePlay = props.minSegmentsBeforePlay, restVideoAttrs = _object_without_properties(props, [
7355
+ var src = props.src, autoplay = props.autoplay, muted = props.muted, lowLatencyMode = props.lowLatencyMode, allowNativeHls = props.allowNativeHls, 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, vmapUrl = props.vmapUrl, adPlayerType = props.adPlayerType, minSegmentsBeforePlay = props.minSegmentsBeforePlay, restVideoAttrs = _object_without_properties(props, [
7111
7356
  "src",
7112
7357
  "autoplay",
7113
7358
  "muted",
@@ -7134,6 +7379,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7134
7379
  "licenseKey",
7135
7380
  "vastMode",
7136
7381
  "vastTagUrl",
7382
+ "vmapUrl",
7137
7383
  "adPlayerType",
7138
7384
  "minSegmentsBeforePlay"
7139
7385
  ]);
@@ -7145,7 +7391,8 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7145
7391
  var _import_react_default_useState = _sliced_to_array(import_react.default.useState({
7146
7392
  showAds: false,
7147
7393
  currentIndex: 0,
7148
- totalAds: 0
7394
+ totalAds: 0,
7395
+ remainingSeconds: 0
7149
7396
  }), 2), adStatus = _import_react_default_useState[0], setAdStatus = _import_react_default_useState[1];
7150
7397
  var _import_react_default_useState1 = _sliced_to_array(import_react.default.useState(true), 2), shouldShowNativeControls = _import_react_default_useState1[0], setShouldShowNativeControls = _import_react_default_useState1[1];
7151
7398
  var _import_react_default_useState2 = _sliced_to_array(import_react.default.useState(false), 2), isMuted = _import_react_default_useState2[0], setIsMuted = _import_react_default_useState2[1];
@@ -7164,6 +7411,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7164
7411
  var _import_react_default_useState15 = _sliced_to_array(import_react.default.useState(true), 2), controlsVisible = _import_react_default_useState15[0], setControlsVisible = _import_react_default_useState15[1];
7165
7412
  var _import_react_default_useState16 = _sliced_to_array(import_react.default.useState(typeof window !== "undefined" ? window.innerWidth : 1920), 2), viewportWidth = _import_react_default_useState16[0], setViewportWidth = _import_react_default_useState16[1];
7166
7413
  var _import_react_default_useState17 = _sliced_to_array(import_react.default.useState(typeof window !== "undefined" ? window.innerHeight > window.innerWidth : false), 2), isPortrait = _import_react_default_useState17[0], setIsPortrait = _import_react_default_useState17[1];
7414
+ var _import_react_default_useState18 = _sliced_to_array(import_react.default.useState(DEFAULT_PLAYER_ASPECT_RATIO), 2), playerAspectRatio = _import_react_default_useState18[0], setPlayerAspectRatio = _import_react_default_useState18[1];
7167
7415
  var getResponsiveScale = function getResponsiveScale() {
7168
7416
  if (viewportWidth < 480) return 0.7;
7169
7417
  if (viewportWidth < 768) return 0.8;
@@ -7273,6 +7521,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7273
7521
  src,
7274
7522
  allowNativeHls,
7275
7523
  licenseKey,
7524
+ vmapUrl,
7276
7525
  lowLatencyMode,
7277
7526
  driftToleranceMs,
7278
7527
  vastMode
@@ -7315,6 +7564,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7315
7564
  if (licenseKey !== void 0) cfg.licenseKey = licenseKey;
7316
7565
  if (vastMode !== void 0) cfg.vastMode = vastMode;
7317
7566
  if (vastTagUrl !== void 0) cfg.vastTagUrl = vastTagUrl;
7567
+ if (vmapUrl !== void 0) cfg.vmapUrl = vmapUrl;
7318
7568
  if (adPlayerType !== void 0) cfg.adPlayerType = adPlayerType;
7319
7569
  if (minSegmentsBeforePlay !== void 0) cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;
7320
7570
  var player = new StormcloudVideoPlayer(cfg);
@@ -7366,15 +7616,18 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7366
7616
  var showAds = showAdsFromMethod || showAdsFromAttribute;
7367
7617
  var currentIndex = playerRef.current.getCurrentAdIndex();
7368
7618
  var totalAds = playerRef.current.getTotalAdsInBreak();
7619
+ var remainingMs = playerRef.current.getAdRemainingMs();
7620
+ var remainingSeconds = showAds ? Math.max(0, Math.ceil(remainingMs / 1e3)) : 0;
7369
7621
  setAdStatus(function(prev) {
7370
- if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds) {
7622
+ if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds || prev.remainingSeconds !== remainingSeconds) {
7371
7623
  if (showAds && !prev.showAds) {
7372
7624
  setShowCenterPlay(false);
7373
7625
  }
7374
7626
  return {
7375
7627
  showAds: showAds,
7376
7628
  currentIndex: currentIndex,
7377
- totalAds: totalAds
7629
+ totalAds: totalAds,
7630
+ remainingSeconds: remainingSeconds
7378
7631
  };
7379
7632
  }
7380
7633
  return prev;
@@ -7432,8 +7685,11 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7432
7685
  (0, import_react.useEffect)(function() {
7433
7686
  if (!videoRef.current) return;
7434
7687
  var handleLoadedMetadata = function handleLoadedMetadata() {
7435
- if (videoRef.current) {
7436
- var video2 = videoRef.current;
7688
+ var video2 = videoRef.current;
7689
+ if (video2) {
7690
+ if (video2.videoWidth > 0 && video2.videoHeight > 0) {
7691
+ setPlayerAspectRatio(video2.videoWidth / video2.videoHeight);
7692
+ }
7437
7693
  void video2.offsetHeight;
7438
7694
  }
7439
7695
  if (debugAdTiming) {
@@ -7549,6 +7805,11 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7549
7805
  }, [
7550
7806
  debugAdTiming
7551
7807
  ]);
7808
+ (0, import_react.useEffect)(function() {
7809
+ setPlayerAspectRatio(DEFAULT_PLAYER_ASPECT_RATIO);
7810
+ }, [
7811
+ src
7812
+ ]);
7552
7813
  (0, import_react.useEffect)(function() {
7553
7814
  return function() {
7554
7815
  if (controlsTimerRef.current) {
@@ -7561,7 +7822,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7561
7822
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, {
7562
7823
  children: [
7563
7824
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", {
7564
- children: "\n @keyframes sc-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n @keyframes sc-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.6; }\n }\n @keyframes sc-fade-in {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n .sc-wrapper:fullscreen,\n .sc-wrapper:has(*:fullscreen) {\n border-radius: 0 !important;\n box-shadow: none !important;\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n .sc-ctrl-btn {\n background: none;\n border: none;\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n padding: 8px;\n transition: background 0.15s ease, opacity 0.15s ease;\n opacity: 0.9;\n }\n .sc-ctrl-btn:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n .sc-ctrl-btn:active {\n opacity: 0.7;\n }\n .sc-controls-bar {\n transition: opacity 0.35s ease, transform 0.35s ease;\n }\n .sc-progress-track:hover .sc-progress-thumb {\n transform: translate(-50%, -50%) scale(1) !important;\n }\n .sc-loading-hidden .sc-loading-indicator {\n display: none !important;\n }\n "
7825
+ children: "\n @keyframes sc-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n @keyframes sc-loading-glow {\n 0%, 100% { opacity: 0.85; transform: scale(1); }\n 50% { opacity: 1; transform: scale(1.05); }\n }\n @keyframes sc-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.6; }\n }\n @keyframes sc-fade-in {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n .sc-wrapper:fullscreen,\n .sc-wrapper:has(*:fullscreen) {\n border-radius: 0 !important;\n box-shadow: none !important;\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n .sc-ctrl-btn {\n background: none;\n border: none;\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n padding: 8px;\n transition: background 0.15s ease, opacity 0.15s ease;\n opacity: 0.9;\n }\n .sc-ctrl-btn:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n .sc-ctrl-btn:active {\n opacity: 0.7;\n }\n .sc-controls-bar {\n transition: opacity 0.35s ease, transform 0.35s ease;\n }\n .sc-progress-track:hover .sc-progress-thumb {\n transform: translate(-50%, -50%) scale(1) !important;\n }\n .sc-loading-hidden .sc-loading-indicator {\n display: none !important;\n }\n "
7565
7826
  }),
7566
7827
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7567
7828
  ref: wrapperRef,
@@ -7579,6 +7840,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7579
7840
  width: isFullscreen ? "100vw" : "100%",
7580
7841
  height: isFullscreen ? "100vh" : "auto",
7581
7842
  minHeight: isFullscreen ? "100vh" : "auto",
7843
+ aspectRatio: isFullscreen ? void 0 : playerAspectRatio,
7582
7844
  maxWidth: isFullscreen ? "100vw" : "100%",
7583
7845
  maxHeight: isFullscreen ? "100vh" : "none",
7584
7846
  zIndex: isFullscreen ? 999999 : void 0,
@@ -7593,7 +7855,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7593
7855
  style: _object_spread({
7594
7856
  display: "block",
7595
7857
  width: "100%",
7596
- height: isFullscreen ? "100%" : "auto",
7858
+ height: "100%",
7597
7859
  maxWidth: "100%",
7598
7860
  maxHeight: isFullscreen ? "100%" : "none",
7599
7861
  objectFit: isFullscreen ? "cover" : "contain",
@@ -7607,18 +7869,44 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7607
7869
  }, restVideoAttrs), {
7608
7870
  children: children
7609
7871
  })),
7610
- (isLoading || isBuffering) && !hideLoadingIndicator && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaSpinner, {
7872
+ (isLoading || isBuffering) && !hideLoadingIndicator && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7611
7873
  className: "sc-loading-indicator",
7612
- size: 40,
7613
- color: "rgba(255, 255, 255, 0.85)",
7614
7874
  style: {
7615
7875
  position: "absolute",
7616
- top: "calc(50% - 20px)",
7617
- left: "calc(50% - 20px)",
7876
+ top: "50%",
7877
+ left: "50%",
7878
+ transform: "translate(-50%, -50%)",
7618
7879
  zIndex: 20,
7619
- animation: "sc-spin 0.9s linear infinite",
7620
- filter: "drop-shadow(0 2px 8px rgba(0, 0, 0, 0.6))"
7621
- }
7880
+ width: "".concat(Math.max(34, 38 * responsiveScale), "px"),
7881
+ height: "".concat(Math.max(34, 38 * responsiveScale), "px"),
7882
+ display: "flex",
7883
+ alignItems: "center",
7884
+ justifyContent: "center",
7885
+ animation: "sc-loading-glow 1.4s ease-in-out infinite",
7886
+ filter: "drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55))"
7887
+ },
7888
+ children: [
7889
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7890
+ style: {
7891
+ position: "absolute",
7892
+ inset: 0,
7893
+ borderRadius: "50%",
7894
+ border: "3px solid rgba(255, 255, 255, 0.25)",
7895
+ borderTopColor: "#ff0000",
7896
+ borderRightColor: "rgba(255, 255, 255, 0.85)",
7897
+ animation: "sc-spin 0.8s linear infinite"
7898
+ }
7899
+ }),
7900
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7901
+ style: {
7902
+ width: "7px",
7903
+ height: "7px",
7904
+ borderRadius: "50%",
7905
+ background: "#ff0000",
7906
+ boxShadow: "0 0 10px rgba(255, 0, 0, 0.65)"
7907
+ }
7908
+ })
7909
+ ]
7622
7910
  }),
7623
7911
  showLicenseWarning && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7624
7912
  style: {
@@ -7662,6 +7950,48 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7662
7950
  })
7663
7951
  ]
7664
7952
  }),
7953
+ adStatus.showAds && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7954
+ style: {
7955
+ position: "absolute",
7956
+ top: "".concat(12 * responsiveScale, "px"),
7957
+ left: "".concat(12 * responsiveScale, "px"),
7958
+ zIndex: 50,
7959
+ display: "flex",
7960
+ alignItems: "center",
7961
+ gap: "8px",
7962
+ pointerEvents: "none",
7963
+ animation: "sc-fade-in 0.3s ease"
7964
+ },
7965
+ children: [
7966
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7967
+ style: {
7968
+ background: "rgba(234, 179, 8, 0.95)",
7969
+ color: "#111",
7970
+ padding: "".concat(4 * responsiveScale, "px ").concat(12 * responsiveScale, "px"),
7971
+ borderRadius: "6px",
7972
+ fontSize: "".concat(11 * responsiveScale, "px"),
7973
+ fontWeight: 700,
7974
+ letterSpacing: "0.08em",
7975
+ textTransform: "uppercase",
7976
+ boxShadow: "0 2px 12px rgba(234, 179, 8, 0.35)"
7977
+ },
7978
+ children: "Ad"
7979
+ }),
7980
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7981
+ style: {
7982
+ background: "rgba(0, 0, 0, 0.58)",
7983
+ color: "rgba(255, 255, 255, 0.92)",
7984
+ padding: "".concat(4 * responsiveScale, "px ").concat(10 * responsiveScale, "px"),
7985
+ borderRadius: "6px",
7986
+ fontSize: "".concat(11 * responsiveScale, "px"),
7987
+ fontWeight: 600,
7988
+ border: "1px solid rgba(255, 255, 255, 0.1)",
7989
+ boxShadow: "0 2px 10px rgba(0, 0, 0, 0.25)"
7990
+ },
7991
+ children: "".concat(Math.max(1, adStatus.currentIndex), " of ").concat(Math.max(Math.max(1, adStatus.currentIndex), adStatus.totalAds))
7992
+ })
7993
+ ]
7994
+ }),
7665
7995
  showCenterPlay && !isLoading && !isBuffering && !showLicenseWarning && !adStatus.showAds && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7666
7996
  onClick: handleCenterPlayClick,
7667
7997
  style: {
@@ -7801,7 +8131,8 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7801
8131
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7802
8132
  style: {
7803
8133
  display: "flex",
7804
- alignItems: "center"
8134
+ alignItems: "center",
8135
+ paddingRight: "".concat(6 * responsiveScale, "px")
7805
8136
  },
7806
8137
  onMouseEnter: function onMouseEnter() {
7807
8138
  return setShowVolumeSlider(true);
@@ -7830,13 +8161,13 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7830
8161
  }),
7831
8162
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7832
8163
  style: {
7833
- width: showVolumeSlider ? "".concat(62 * responsiveScale, "px") : "0px",
8164
+ width: showVolumeSlider ? "".concat(68 * responsiveScale, "px") : "0px",
7834
8165
  overflow: "hidden",
7835
8166
  transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
7836
8167
  display: "flex",
7837
8168
  alignItems: "center",
7838
- paddingLeft: showVolumeSlider ? "2px" : "0",
7839
- paddingRight: showVolumeSlider ? "4px" : "0"
8169
+ paddingLeft: showVolumeSlider ? "".concat(3 * responsiveScale, "px") : "0",
8170
+ paddingRight: showVolumeSlider ? "".concat(8 * responsiveScale, "px") : "0"
7840
8171
  },
7841
8172
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7842
8173
  style: {
@@ -8083,7 +8414,8 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
8083
8414
  alignItems: "center",
8084
8415
  background: "rgba(0, 0, 0, 0.6)",
8085
8416
  borderRadius: "".concat(18 * responsiveScale, "px"),
8086
- padding: "2px"
8417
+ padding: "2px",
8418
+ paddingRight: "".concat(8 * responsiveScale, "px")
8087
8419
  },
8088
8420
  onMouseEnter: function onMouseEnter() {
8089
8421
  return setShowVolumeSlider(true);
@@ -8112,13 +8444,13 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
8112
8444
  }),
8113
8445
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8114
8446
  style: {
8115
- width: showVolumeSlider ? "".concat(62 * responsiveScale, "px") : "0px",
8447
+ width: showVolumeSlider ? "".concat(68 * responsiveScale, "px") : "0px",
8116
8448
  overflow: "hidden",
8117
8449
  transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
8118
8450
  display: "flex",
8119
8451
  alignItems: "center",
8120
- paddingLeft: showVolumeSlider ? "2px" : "0",
8121
- paddingRight: showVolumeSlider ? "6px" : "0"
8452
+ paddingLeft: showVolumeSlider ? "".concat(3 * responsiveScale, "px") : "0",
8453
+ paddingRight: showVolumeSlider ? "".concat(10 * responsiveScale, "px") : "0"
8122
8454
  },
8123
8455
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8124
8456
  style: {