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.
package/lib/index.cjs CHANGED
@@ -880,7 +880,7 @@ function createImaController(video, options) {
880
880
  adVideo.style.height = "100%";
881
881
  adVideo.style.objectFit = "contain";
882
882
  adVideo.style.backgroundColor = "transparent";
883
- adVideo.style.zIndex = "15";
883
+ adVideo.style.zIndex = "2";
884
884
  adVideo.playsInline = true;
885
885
  adVideo.volume = originalVolume;
886
886
  adVideo.muted = originalMutedState;
@@ -1173,7 +1173,7 @@ function createImaController(video, options) {
1173
1173
  container.style.alignItems = "center";
1174
1174
  container.style.justifyContent = "center";
1175
1175
  container.style.pointerEvents = "none";
1176
- container.style.zIndex = "10";
1176
+ container.style.zIndex = "30";
1177
1177
  container.style.backgroundColor = "#000";
1178
1178
  container.style.transition = "opacity 0.3s ease-in-out";
1179
1179
  container.style.opacity = "0";
@@ -1288,7 +1288,7 @@ function createImaController(video, options) {
1288
1288
  container.style.alignItems = "center";
1289
1289
  container.style.justifyContent = "center";
1290
1290
  container.style.pointerEvents = "none";
1291
- container.style.zIndex = "10";
1291
+ container.style.zIndex = "30";
1292
1292
  container.style.backgroundColor = "transparent";
1293
1293
  container.style.transition = "opacity 0.3s ease-in-out, background-color 0.3s ease-in-out";
1294
1294
  container.style.opacity = "0";
@@ -2203,7 +2203,7 @@ function createHlsAdPlayer(contentVideo, options) {
2203
2203
  container.style.alignItems = "center";
2204
2204
  container.style.justifyContent = "center";
2205
2205
  container.style.pointerEvents = "none";
2206
- container.style.zIndex = "10";
2206
+ container.style.zIndex = "30";
2207
2207
  container.style.backgroundColor = "#000";
2208
2208
  (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
2209
2209
  adContainerEl = container;
@@ -3427,6 +3427,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3427
3427
  this.inAdBreak = false;
3428
3428
  this.ptsDriftEmaMs = 0;
3429
3429
  this.adPodQueue = [];
3430
+ this.vmapBreaks = [];
3431
+ this.consumedVmapBreakIds = /* @__PURE__ */ new Set();
3430
3432
  this.lastHeartbeatTime = 0;
3431
3433
  this.currentAdIndex = 0;
3432
3434
  this.totalAdsInBreak = 0;
@@ -3981,13 +3983,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3981
3983
  _this.activeAdRequestToken = null;
3982
3984
  _this.showAds = true;
3983
3985
  _this.resetGamNoFillCounter();
3984
- if (_this.inAdBreak && _this.expectedAdBreakDurationMs != null) {
3985
- if (_this.adStopTimerId == null) {
3986
- _this.currentAdBreakStartWallClockMs = Date.now();
3987
- _this.scheduleAdStopCountdown(_this.expectedAdBreakDurationMs);
3988
- if (_this.config.debugAdTiming) {
3989
- console.log("[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)");
3990
- }
3986
+ if (_this.inAdBreak && _this.expectedAdBreakDurationMs != null && _this.adStopTimerId == null) {
3987
+ _this.scheduleAdStopCountdown(_this.getRemainingAdMs());
3988
+ if (_this.config.debugAdTiming) {
3989
+ console.log("[StormcloudVideoPlayer] Starting ad break timer on content_pause (first ad starting)");
3991
3990
  }
3992
3991
  }
3993
3992
  var currentMuted = _this.video.muted;
@@ -4050,6 +4049,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4050
4049
  this.ima.showPlaceholder();
4051
4050
  this.isShowingPlaceholder = true;
4052
4051
  }
4052
+ var preservedMutedState = this.ima.getOriginalMutedState();
4053
+ var preservedVolumeState = this.ima.getOriginalVolume();
4053
4054
  if (this.ima) {
4054
4055
  try {
4055
4056
  this.ima.destroy();
@@ -4064,7 +4065,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4064
4065
  var continueLiveStreamDuringAds = this.shouldContinueLiveStreamDuringAds();
4065
4066
  this.ima = this.createAdPlayer(continueLiveStreamDuringAds);
4066
4067
  this.ima.initialize();
4067
- this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
4068
+ this.ima.updateOriginalMutedState(preservedMutedState, preservedVolumeState);
4068
4069
  this.attachImaEventListeners();
4069
4070
  if (shouldShowPlaceholder) {
4070
4071
  this.showPlaceholderLayer();
@@ -4380,12 +4381,17 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4380
4381
  }
4381
4382
  }
4382
4383
  if (this.inAdBreak) {
4383
- if (this.expectedAdBreakDurationMs == null && marker.durationSeconds != null) {
4384
- this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;
4385
- if (this.config.debugAdTiming) {
4386
- console.log("[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ".concat(this.expectedAdBreakDurationMs, "ms"));
4384
+ if (marker.durationSeconds != null) {
4385
+ var newDurationMs = marker.durationSeconds * 1e3;
4386
+ if (this.expectedAdBreakDurationMs == null || newDurationMs > this.expectedAdBreakDurationMs) {
4387
+ this.expectedAdBreakDurationMs = newDurationMs;
4388
+ var elapsedMs = this.currentAdBreakStartWallClockMs != null ? Date.now() - this.currentAdBreakStartWallClockMs : 0;
4389
+ var remainingMs = Math.max(0, newDurationMs - elapsedMs);
4390
+ this.scheduleAdStopCountdown(remainingMs);
4391
+ if (this.config.debugAdTiming) {
4392
+ console.log("[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ".concat(newDurationMs, "ms, remaining: ").concat(remainingMs, "ms"));
4393
+ }
4387
4394
  }
4388
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
4389
4395
  }
4390
4396
  return;
4391
4397
  }
@@ -4461,9 +4467,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4461
4467
  this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;
4462
4468
  }
4463
4469
  if (this.expectedAdBreakDurationMs != null && this.currentAdBreakStartWallClockMs != null) {
4464
- var elapsedMs = Date.now() - this.currentAdBreakStartWallClockMs;
4465
- var remainingMs = Math.max(0, this.expectedAdBreakDurationMs - elapsedMs);
4466
- this.scheduleAdStopCountdown(remainingMs);
4470
+ var elapsedMs1 = Date.now() - this.currentAdBreakStartWallClockMs;
4471
+ var remainingMs1 = Math.max(0, this.expectedAdBreakDurationMs - elapsedMs1);
4472
+ this.scheduleAdStopCountdown(remainingMs1);
4467
4473
  }
4468
4474
  if (!this.ima.isAdPlaying() && this.activeAdRequestToken === null && this.adRequestQueue.length > 0) {
4469
4475
  this.tryNextAvailableAdWithRateLimit();
@@ -4755,6 +4761,18 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4755
4761
  return _ts_generator(this, function(_state) {
4756
4762
  switch(_state.label){
4757
4763
  case 0:
4764
+ if (!this.config.vmapUrl) return [
4765
+ 3,
4766
+ 2
4767
+ ];
4768
+ return [
4769
+ 4,
4770
+ this.fetchAndParseVmap(this.config.vmapUrl)
4771
+ ];
4772
+ case 1:
4773
+ _state.sent();
4774
+ _state.label = 2;
4775
+ case 2:
4758
4776
  vastMode = this.config.vastMode || "default";
4759
4777
  if (this.config.debugAdTiming) {
4760
4778
  console.log("[StormcloudVideoPlayer] VAST mode:", vastMode);
@@ -4800,7 +4818,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4800
4818
  headers: headers
4801
4819
  })
4802
4820
  ];
4803
- case 1:
4821
+ case 3:
4804
4822
  response = _state.sent();
4805
4823
  if (!response.ok) {
4806
4824
  if (this.config.debugAdTiming) {
@@ -4814,7 +4832,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4814
4832
  4,
4815
4833
  response.json()
4816
4834
  ];
4817
- case 2:
4835
+ case 4:
4818
4836
  data = _state.sent();
4819
4837
  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;
4820
4838
  if (imaPayload) {
@@ -4842,6 +4860,171 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4842
4860
  }).call(this);
4843
4861
  }
4844
4862
  },
4863
+ {
4864
+ key: "fetchAndParseVmap",
4865
+ value: function fetchAndParseVmap(vmapUrl) {
4866
+ return _async_to_generator(function() {
4867
+ var response, vmapXml, error;
4868
+ return _ts_generator(this, function(_state) {
4869
+ switch(_state.label){
4870
+ case 0:
4871
+ if (!vmapUrl.trim()) {
4872
+ return [
4873
+ 2
4874
+ ];
4875
+ }
4876
+ _state.label = 1;
4877
+ case 1:
4878
+ _state.trys.push([
4879
+ 1,
4880
+ 4,
4881
+ ,
4882
+ 5
4883
+ ]);
4884
+ return [
4885
+ 4,
4886
+ fetch(vmapUrl)
4887
+ ];
4888
+ case 2:
4889
+ response = _state.sent();
4890
+ if (!response.ok) {
4891
+ throw new Error("Failed to fetch VMAP (".concat(response.status, ")"));
4892
+ }
4893
+ return [
4894
+ 4,
4895
+ response.text()
4896
+ ];
4897
+ case 3:
4898
+ vmapXml = _state.sent();
4899
+ this.vmapBreaks = this.parseVmapToBreaks(vmapXml);
4900
+ this.consumedVmapBreakIds.clear();
4901
+ if (this.config.debugAdTiming) {
4902
+ console.log("[StormcloudVideoPlayer] Loaded ".concat(this.vmapBreaks.length, " VMAP ad break(s) from:"), vmapUrl);
4903
+ }
4904
+ return [
4905
+ 3,
4906
+ 5
4907
+ ];
4908
+ case 4:
4909
+ error = _state.sent();
4910
+ this.vmapBreaks = [];
4911
+ this.consumedVmapBreakIds.clear();
4912
+ if (this.config.debugAdTiming) {
4913
+ console.warn("[StormcloudVideoPlayer] Failed to load VMAP:", error);
4914
+ }
4915
+ return [
4916
+ 3,
4917
+ 5
4918
+ ];
4919
+ case 5:
4920
+ return [
4921
+ 2
4922
+ ];
4923
+ }
4924
+ });
4925
+ }).call(this);
4926
+ }
4927
+ },
4928
+ {
4929
+ key: "parseVmapToBreaks",
4930
+ value: function parseVmapToBreaks(vmapXml) {
4931
+ var _this = this;
4932
+ if (typeof DOMParser === "undefined") {
4933
+ return [];
4934
+ }
4935
+ var doc = new DOMParser().parseFromString(vmapXml, "application/xml");
4936
+ if (doc.querySelector("parsererror")) {
4937
+ if (this.config.debugAdTiming) {
4938
+ console.warn("[StormcloudVideoPlayer] Invalid VMAP XML received");
4939
+ }
4940
+ return [];
4941
+ }
4942
+ var adBreakNodes = Array.from(doc.querySelectorAll("AdBreak, vmap\\:AdBreak"));
4943
+ var parsed = [];
4944
+ adBreakNodes.forEach(function(node, index) {
4945
+ var timeOffsetRaw = (node.getAttribute("timeOffset") || "").trim();
4946
+ var startTimeMs = _this.parseVmapTimeOffsetToMs(timeOffsetRaw);
4947
+ if (startTimeMs == null) {
4948
+ return;
4949
+ }
4950
+ var adTagNode = node.querySelector("AdTagURI, vmap\\:AdTagURI");
4951
+ var adTagUrl = ((adTagNode === null || adTagNode === void 0 ? void 0 : adTagNode.textContent) || "").trim();
4952
+ if (!adTagUrl) {
4953
+ return;
4954
+ }
4955
+ var breakId = node.getAttribute("breakId") || "vmap-break-".concat(index, "-").concat(timeOffsetRaw || "unknown");
4956
+ parsed.push({
4957
+ id: breakId,
4958
+ startTimeMs: startTimeMs,
4959
+ vastTagUrl: adTagUrl
4960
+ });
4961
+ });
4962
+ parsed.sort(function(a, b) {
4963
+ var aStart = a.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : a.startTimeMs;
4964
+ var bStart = b.startTimeMs < 0 ? Number.MAX_SAFE_INTEGER : b.startTimeMs;
4965
+ return aStart - bStart;
4966
+ });
4967
+ return parsed;
4968
+ }
4969
+ },
4970
+ {
4971
+ key: "parseVmapTimeOffsetToMs",
4972
+ value: function parseVmapTimeOffsetToMs(timeOffset) {
4973
+ if (!timeOffset) {
4974
+ return void 0;
4975
+ }
4976
+ var normalized = timeOffset.trim().toLowerCase();
4977
+ if (normalized === "start") {
4978
+ return 0;
4979
+ }
4980
+ if (normalized === "end") {
4981
+ return -1;
4982
+ }
4983
+ var hms = timeOffset.match(/^(\d{1,2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?$/);
4984
+ if (hms) {
4985
+ 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;
4986
+ var hours = Number(hh);
4987
+ var minutes = Number(mm);
4988
+ var seconds = Number(ss);
4989
+ var millis = Number(ms.padEnd(3, "0").slice(0, 3));
4990
+ return (hours * 3600 + minutes * 60 + seconds) * 1e3 + millis;
4991
+ }
4992
+ var percent = timeOffset.match(/^(\d+(?:\.\d+)?)%$/);
4993
+ if (percent) {
4994
+ var ratio = Number(percent[1]) / 100;
4995
+ var durationSec = this.video.duration;
4996
+ if (Number.isFinite(durationSec) && durationSec > 0) {
4997
+ return Math.floor(durationSec * 1e3 * ratio);
4998
+ }
4999
+ return void 0;
5000
+ }
5001
+ return void 0;
5002
+ }
5003
+ },
5004
+ {
5005
+ key: "getAdBreakKey",
5006
+ value: function getAdBreakKey(adBreak) {
5007
+ if (adBreak.id) {
5008
+ return adBreak.id;
5009
+ }
5010
+ return "".concat(adBreak.startTimeMs, "-").concat(adBreak.vastTagUrl || "");
5011
+ }
5012
+ },
5013
+ {
5014
+ key: "resolveBreakStartMs",
5015
+ value: function resolveBreakStartMs(adBreak) {
5016
+ if (adBreak.startTimeMs >= 0) {
5017
+ return adBreak.startTimeMs;
5018
+ }
5019
+ if (adBreak.startTimeMs === -1) {
5020
+ var durationSec = this.video.duration;
5021
+ if (Number.isFinite(durationSec) && durationSec > 0) {
5022
+ return Math.floor(durationSec * 1e3);
5023
+ }
5024
+ }
5025
+ return void 0;
5026
+ }
5027
+ },
4845
5028
  {
4846
5029
  key: "getCurrentAdIndex",
4847
5030
  value: function getCurrentAdIndex() {
@@ -4854,6 +5037,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4854
5037
  return this.totalAdsInBreak;
4855
5038
  }
4856
5039
  },
5040
+ {
5041
+ key: "getAdRemainingMs",
5042
+ value: function getAdRemainingMs() {
5043
+ return this.getRemainingAdMs();
5044
+ }
5045
+ },
4857
5046
  {
4858
5047
  key: "generateVastUrlsWithCorrelators",
4859
5048
  value: function generateVastUrlsWithCorrelators(baseUrl, count) {
@@ -4932,10 +5121,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4932
5121
  var scheduled = this.findCurrentOrNextBreak(this.video.currentTime * 1e3);
4933
5122
  var tags = this.selectVastTagsForBreak(scheduled);
4934
5123
  var baseVastUrl;
4935
- if (this.apiVastTagUrl) {
4936
- baseVastUrl = this.apiVastTagUrl;
4937
- } else if (tags && tags.length > 0 && tags[0]) {
5124
+ if (tags && tags.length > 0 && tags[0]) {
4938
5125
  baseVastUrl = tags[0];
5126
+ } else if (this.apiVastTagUrl) {
5127
+ baseVastUrl = this.apiVastTagUrl;
4939
5128
  } else {
4940
5129
  if (this.config.debugAdTiming) {
4941
5130
  console.warn("[StormcloudVideoPlayer] No VAST URL available for prefetch");
@@ -5385,11 +5574,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5385
5574
  switch(_state.label){
5386
5575
  case 0:
5387
5576
  scheduled = this.findCurrentOrNextBreak(this.video.currentTime * 1e3);
5577
+ if (scheduled) {
5578
+ this.consumedVmapBreakIds.add(this.getAdBreakKey(scheduled));
5579
+ }
5388
5580
  tags = this.selectVastTagsForBreak(scheduled);
5389
- if (this.apiVastTagUrl) {
5390
- baseVastUrl = this.apiVastTagUrl;
5391
- } else if (tags && tags.length > 0 && tags[0]) {
5581
+ if (tags && tags.length > 0 && tags[0]) {
5392
5582
  baseVastUrl = tags[0];
5583
+ } else if (this.apiVastTagUrl) {
5584
+ baseVastUrl = this.apiVastTagUrl;
5393
5585
  } else {
5394
5586
  this.clearPendingAdBreak();
5395
5587
  return [
@@ -5503,9 +5695,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5503
5695
  ];
5504
5696
  case 2:
5505
5697
  _state.sent();
5506
- if (this.expectedAdBreakDurationMs != null) {
5507
- this.currentAdBreakStartWallClockMs = Date.now();
5508
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
5698
+ if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
5699
+ this.scheduleAdStopCountdown(this.getRemainingAdMs());
5509
5700
  }
5510
5701
  adVolume = currentMuted ? 0 : currentVolume;
5511
5702
  this.ima.setAdVolume(adVolume);
@@ -5546,9 +5737,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5546
5737
  ];
5547
5738
  case 6:
5548
5739
  _state.sent();
5549
- if (this.expectedAdBreakDurationMs != null) {
5550
- this.currentAdBreakStartWallClockMs = Date.now();
5551
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
5740
+ if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
5741
+ this.scheduleAdStopCountdown(this.getRemainingAdMs());
5552
5742
  }
5553
5743
  adVolume1 = currentMuted ? 0 : currentVolume;
5554
5744
  this.ima.setAdVolume(adVolume1);
@@ -5602,9 +5792,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5602
5792
  ];
5603
5793
  case 10:
5604
5794
  _state.sent();
5605
- if (this.expectedAdBreakDurationMs != null) {
5606
- this.currentAdBreakStartWallClockMs = Date.now();
5607
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
5795
+ if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
5796
+ this.scheduleAdStopCountdown(this.getRemainingAdMs());
5608
5797
  }
5609
5798
  adVolume2 = currentMuted ? 0 : currentVolume;
5610
5799
  this.ima.setAdVolume(adVolume2);
@@ -5955,8 +6144,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5955
6144
  case 2:
5956
6145
  _state.sent();
5957
6146
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
5958
- this.currentAdBreakStartWallClockMs = Date.now();
5959
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
6147
+ this.scheduleAdStopCountdown(this.getRemainingAdMs());
5960
6148
  }
5961
6149
  currentMuted = this.video.muted;
5962
6150
  currentVolume = this.video.volume;
@@ -6268,15 +6456,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6268
6456
  {
6269
6457
  key: "findCurrentOrNextBreak",
6270
6458
  value: function findCurrentOrNextBreak(nowMs) {
6271
- var schedule = [];
6459
+ var schedule = this.vmapBreaks;
6272
6460
  var candidate;
6273
6461
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
6274
6462
  try {
6275
6463
  for(var _iterator = schedule[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
6276
6464
  var b = _step.value;
6277
- var _this_config_driftToleranceMs;
6465
+ var _this_config_driftToleranceMs, _this_resolveBreakStartMs;
6466
+ if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {
6467
+ continue;
6468
+ }
6469
+ var breakStartMs = this.resolveBreakStartMs(b);
6470
+ if (breakStartMs == null) {
6471
+ continue;
6472
+ }
6278
6473
  var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
6279
- if (b.startTimeMs <= nowMs + tol && (candidate == null || b.startTimeMs > (candidate.startTimeMs || 0))) {
6474
+ if (breakStartMs <= nowMs + tol && (candidate == null || breakStartMs > ((_this_resolveBreakStartMs = this.resolveBreakStartMs(candidate)) !== null && _this_resolveBreakStartMs !== void 0 ? _this_resolveBreakStartMs : 0))) {
6280
6475
  candidate = b;
6281
6476
  }
6282
6477
  }
@@ -6300,11 +6495,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6300
6495
  {
6301
6496
  key: "onTimeUpdate",
6302
6497
  value: function onTimeUpdate(currentTimeSec) {
6303
- if (this.ima.isAdPlaying()) return;
6498
+ var _this = this;
6499
+ if (this.ima.isAdPlaying() || this.inAdBreak) return;
6304
6500
  var nowMs = currentTimeSec * 1e3;
6305
6501
  var breakToPlay = this.findBreakForTime(nowMs);
6306
6502
  if (breakToPlay) {
6307
- this.handleMidAdJoin(breakToPlay, nowMs);
6503
+ void this.handleMidAdJoin(breakToPlay, nowMs).catch(function(error) {
6504
+ if (_this.config.debugAdTiming) {
6505
+ console.warn("[StormcloudVideoPlayer] Mid-roll VMAP join failed gracefully:", error);
6506
+ }
6507
+ });
6308
6508
  }
6309
6509
  }
6310
6510
  },
@@ -6312,40 +6512,76 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6312
6512
  key: "handleMidAdJoin",
6313
6513
  value: function handleMidAdJoin(adBreak, nowMs) {
6314
6514
  return _async_to_generator(function() {
6315
- var _adBreak_durationMs, durationMs, endMs, remainingMs, tags, first, rest;
6515
+ var _adBreak_durationMs, _this_config_driftToleranceMs, key, breakStartMs, durationMs, endMs, tol, inWindow, remainingMs, tags, first, rest, error;
6316
6516
  return _ts_generator(this, function(_state) {
6317
6517
  switch(_state.label){
6318
6518
  case 0:
6519
+ key = this.getAdBreakKey(adBreak);
6520
+ if (this.consumedVmapBreakIds.has(key)) {
6521
+ return [
6522
+ 2
6523
+ ];
6524
+ }
6525
+ breakStartMs = this.resolveBreakStartMs(adBreak);
6526
+ if (breakStartMs == null) {
6527
+ return [
6528
+ 2
6529
+ ];
6530
+ }
6319
6531
  durationMs = (_adBreak_durationMs = adBreak.durationMs) !== null && _adBreak_durationMs !== void 0 ? _adBreak_durationMs : 0;
6320
- endMs = adBreak.startTimeMs + durationMs;
6321
- if (!(durationMs > 0 && nowMs > adBreak.startTimeMs && nowMs < endMs)) return [
6532
+ endMs = breakStartMs + durationMs;
6533
+ tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
6534
+ inWindow = durationMs > 0 ? nowMs > breakStartMs && nowMs < endMs : nowMs + tol >= breakStartMs;
6535
+ if (!inWindow) return [
6322
6536
  3,
6323
- 2
6537
+ 4
6324
6538
  ];
6325
- remainingMs = endMs - nowMs;
6539
+ this.consumedVmapBreakIds.add(key);
6540
+ remainingMs = durationMs > 0 ? Math.max(0, endMs - nowMs) : 0;
6326
6541
  tags = this.selectVastTagsForBreak(adBreak) || (this.apiVastTagUrl ? [
6327
6542
  this.apiVastTagUrl
6328
6543
  ] : void 0);
6329
6544
  if (!(tags && tags.length > 0)) return [
6330
6545
  3,
6331
- 2
6546
+ 4
6332
6547
  ];
6333
6548
  first = tags[0];
6334
6549
  rest = tags.slice(1);
6335
6550
  this.adPodQueue = rest;
6336
6551
  this.ima.updateOriginalMutedState(this.video.muted, this.video.volume);
6552
+ _state.label = 1;
6553
+ case 1:
6554
+ _state.trys.push([
6555
+ 1,
6556
+ 3,
6557
+ ,
6558
+ 4
6559
+ ]);
6337
6560
  return [
6338
6561
  4,
6339
6562
  this.playSingleAd(first)
6340
6563
  ];
6341
- case 1:
6564
+ case 2:
6342
6565
  _state.sent();
6343
6566
  this.inAdBreak = true;
6344
6567
  this.expectedAdBreakDurationMs = remainingMs;
6345
6568
  this.currentAdBreakStartWallClockMs = Date.now();
6346
6569
  this.scheduleAdStopCountdown(remainingMs);
6347
- _state.label = 2;
6348
- case 2:
6570
+ return [
6571
+ 3,
6572
+ 4
6573
+ ];
6574
+ case 3:
6575
+ error = _state.sent();
6576
+ this.adPodQueue = [];
6577
+ if (this.config.debugAdTiming) {
6578
+ console.warn("[StormcloudVideoPlayer] Mid-roll VMAP ad request failed:", error);
6579
+ }
6580
+ return [
6581
+ 3,
6582
+ 4
6583
+ ];
6584
+ case 4:
6349
6585
  return [
6350
6586
  2
6351
6587
  ];
@@ -6661,8 +6897,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6661
6897
  case 5:
6662
6898
  _state.sent();
6663
6899
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
6664
- this.currentAdBreakStartWallClockMs = Date.now();
6665
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
6900
+ this.scheduleAdStopCountdown(this.getRemainingAdMs());
6666
6901
  }
6667
6902
  currentMuted = this.video.muted;
6668
6903
  currentVolume = this.video.volume;
@@ -6712,8 +6947,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6712
6947
  case 8:
6713
6948
  _state.sent();
6714
6949
  if (this.expectedAdBreakDurationMs != null && this.adStopTimerId == null) {
6715
- this.currentAdBreakStartWallClockMs = Date.now();
6716
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
6950
+ this.scheduleAdStopCountdown(this.getRemainingAdMs());
6717
6951
  }
6718
6952
  currentMuted1 = this.video.muted;
6719
6953
  currentVolume1 = this.video.volume;
@@ -7051,13 +7285,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7051
7285
  {
7052
7286
  key: "findBreakForTime",
7053
7287
  value: function findBreakForTime(nowMs) {
7054
- var schedule = [];
7288
+ var _this_config_driftToleranceMs;
7289
+ var schedule = this.vmapBreaks;
7290
+ var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
7055
7291
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
7056
7292
  try {
7057
7293
  for(var _iterator = schedule[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
7058
7294
  var b = _step.value;
7059
- var end = (b.startTimeMs || 0) + (b.durationMs || 0);
7060
- if (nowMs >= (b.startTimeMs || 0) && (b.durationMs ? nowMs < end : true)) {
7295
+ if (this.consumedVmapBreakIds.has(this.getAdBreakKey(b))) {
7296
+ continue;
7297
+ }
7298
+ var breakStartMs = this.resolveBreakStartMs(b);
7299
+ if (breakStartMs == null) {
7300
+ continue;
7301
+ }
7302
+ var end = breakStartMs + (b.durationMs || 0);
7303
+ if (nowMs >= breakStartMs && (b.durationMs ? nowMs < end : nowMs <= breakStartMs + tol)) {
7061
7304
  return b;
7062
7305
  }
7063
7306
  }
@@ -7289,13 +7532,15 @@ var CRITICAL_PROPS = [
7289
7532
  "src",
7290
7533
  "allowNativeHls",
7291
7534
  "licenseKey",
7535
+ "vmapUrl",
7292
7536
  "lowLatencyMode",
7293
7537
  "driftToleranceMs",
7294
7538
  "vastMode"
7295
7539
  ];
7296
7540
  var CONTROLS_HIDE_DELAY = 3e3;
7541
+ var DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;
7297
7542
  var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7298
- 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, [
7543
+ 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, [
7299
7544
  "src",
7300
7545
  "autoplay",
7301
7546
  "muted",
@@ -7322,6 +7567,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7322
7567
  "licenseKey",
7323
7568
  "vastMode",
7324
7569
  "vastTagUrl",
7570
+ "vmapUrl",
7325
7571
  "adPlayerType",
7326
7572
  "minSegmentsBeforePlay"
7327
7573
  ]);
@@ -7333,7 +7579,8 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7333
7579
  var _import_react_default_useState = _sliced_to_array(import_react.default.useState({
7334
7580
  showAds: false,
7335
7581
  currentIndex: 0,
7336
- totalAds: 0
7582
+ totalAds: 0,
7583
+ remainingSeconds: 0
7337
7584
  }), 2), adStatus = _import_react_default_useState[0], setAdStatus = _import_react_default_useState[1];
7338
7585
  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];
7339
7586
  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];
@@ -7352,6 +7599,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7352
7599
  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];
7353
7600
  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];
7354
7601
  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];
7602
+ 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];
7355
7603
  var getResponsiveScale = function getResponsiveScale() {
7356
7604
  if (viewportWidth < 480) return 0.7;
7357
7605
  if (viewportWidth < 768) return 0.8;
@@ -7461,6 +7709,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7461
7709
  src,
7462
7710
  allowNativeHls,
7463
7711
  licenseKey,
7712
+ vmapUrl,
7464
7713
  lowLatencyMode,
7465
7714
  driftToleranceMs,
7466
7715
  vastMode
@@ -7503,6 +7752,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7503
7752
  if (licenseKey !== void 0) cfg.licenseKey = licenseKey;
7504
7753
  if (vastMode !== void 0) cfg.vastMode = vastMode;
7505
7754
  if (vastTagUrl !== void 0) cfg.vastTagUrl = vastTagUrl;
7755
+ if (vmapUrl !== void 0) cfg.vmapUrl = vmapUrl;
7506
7756
  if (adPlayerType !== void 0) cfg.adPlayerType = adPlayerType;
7507
7757
  if (minSegmentsBeforePlay !== void 0) cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;
7508
7758
  var player = new StormcloudVideoPlayer(cfg);
@@ -7554,15 +7804,18 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7554
7804
  var showAds = showAdsFromMethod || showAdsFromAttribute;
7555
7805
  var currentIndex = playerRef.current.getCurrentAdIndex();
7556
7806
  var totalAds = playerRef.current.getTotalAdsInBreak();
7807
+ var remainingMs = playerRef.current.getAdRemainingMs();
7808
+ var remainingSeconds = showAds ? Math.max(0, Math.ceil(remainingMs / 1e3)) : 0;
7557
7809
  setAdStatus(function(prev) {
7558
- if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds) {
7810
+ if (prev.showAds !== showAds || prev.currentIndex !== currentIndex || prev.totalAds !== totalAds || prev.remainingSeconds !== remainingSeconds) {
7559
7811
  if (showAds && !prev.showAds) {
7560
7812
  setShowCenterPlay(false);
7561
7813
  }
7562
7814
  return {
7563
7815
  showAds: showAds,
7564
7816
  currentIndex: currentIndex,
7565
- totalAds: totalAds
7817
+ totalAds: totalAds,
7818
+ remainingSeconds: remainingSeconds
7566
7819
  };
7567
7820
  }
7568
7821
  return prev;
@@ -7620,8 +7873,11 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7620
7873
  (0, import_react.useEffect)(function() {
7621
7874
  if (!videoRef.current) return;
7622
7875
  var handleLoadedMetadata = function handleLoadedMetadata() {
7623
- if (videoRef.current) {
7624
- var video2 = videoRef.current;
7876
+ var video2 = videoRef.current;
7877
+ if (video2) {
7878
+ if (video2.videoWidth > 0 && video2.videoHeight > 0) {
7879
+ setPlayerAspectRatio(video2.videoWidth / video2.videoHeight);
7880
+ }
7625
7881
  void video2.offsetHeight;
7626
7882
  }
7627
7883
  if (debugAdTiming) {
@@ -7737,6 +7993,11 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7737
7993
  }, [
7738
7994
  debugAdTiming
7739
7995
  ]);
7996
+ (0, import_react.useEffect)(function() {
7997
+ setPlayerAspectRatio(DEFAULT_PLAYER_ASPECT_RATIO);
7998
+ }, [
7999
+ src
8000
+ ]);
7740
8001
  (0, import_react.useEffect)(function() {
7741
8002
  return function() {
7742
8003
  if (controlsTimerRef.current) {
@@ -7749,7 +8010,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7749
8010
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, {
7750
8011
  children: [
7751
8012
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", {
7752
- 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 "
8013
+ 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 "
7753
8014
  }),
7754
8015
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7755
8016
  ref: wrapperRef,
@@ -7767,6 +8028,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7767
8028
  width: isFullscreen ? "100vw" : "100%",
7768
8029
  height: isFullscreen ? "100vh" : "auto",
7769
8030
  minHeight: isFullscreen ? "100vh" : "auto",
8031
+ aspectRatio: isFullscreen ? void 0 : playerAspectRatio,
7770
8032
  maxWidth: isFullscreen ? "100vw" : "100%",
7771
8033
  maxHeight: isFullscreen ? "100vh" : "none",
7772
8034
  zIndex: isFullscreen ? 999999 : void 0,
@@ -7781,7 +8043,7 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7781
8043
  style: _object_spread({
7782
8044
  display: "block",
7783
8045
  width: "100%",
7784
- height: isFullscreen ? "100%" : "auto",
8046
+ height: "100%",
7785
8047
  maxWidth: "100%",
7786
8048
  maxHeight: isFullscreen ? "100%" : "none",
7787
8049
  objectFit: isFullscreen ? "cover" : "contain",
@@ -7795,18 +8057,44 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7795
8057
  }, restVideoAttrs), {
7796
8058
  children: children
7797
8059
  })),
7798
- (isLoading || isBuffering) && !hideLoadingIndicator && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaSpinner, {
8060
+ (isLoading || isBuffering) && !hideLoadingIndicator && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7799
8061
  className: "sc-loading-indicator",
7800
- size: 40,
7801
- color: "rgba(255, 255, 255, 0.85)",
7802
8062
  style: {
7803
8063
  position: "absolute",
7804
- top: "calc(50% - 20px)",
7805
- left: "calc(50% - 20px)",
8064
+ top: "50%",
8065
+ left: "50%",
8066
+ transform: "translate(-50%, -50%)",
7806
8067
  zIndex: 20,
7807
- animation: "sc-spin 0.9s linear infinite",
7808
- filter: "drop-shadow(0 2px 8px rgba(0, 0, 0, 0.6))"
7809
- }
8068
+ width: "".concat(Math.max(34, 38 * responsiveScale), "px"),
8069
+ height: "".concat(Math.max(34, 38 * responsiveScale), "px"),
8070
+ display: "flex",
8071
+ alignItems: "center",
8072
+ justifyContent: "center",
8073
+ animation: "sc-loading-glow 1.4s ease-in-out infinite",
8074
+ filter: "drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55))"
8075
+ },
8076
+ children: [
8077
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8078
+ style: {
8079
+ position: "absolute",
8080
+ inset: 0,
8081
+ borderRadius: "50%",
8082
+ border: "3px solid rgba(255, 255, 255, 0.25)",
8083
+ borderTopColor: "#ff0000",
8084
+ borderRightColor: "rgba(255, 255, 255, 0.85)",
8085
+ animation: "sc-spin 0.8s linear infinite"
8086
+ }
8087
+ }),
8088
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8089
+ style: {
8090
+ width: "7px",
8091
+ height: "7px",
8092
+ borderRadius: "50%",
8093
+ background: "#ff0000",
8094
+ boxShadow: "0 0 10px rgba(255, 0, 0, 0.65)"
8095
+ }
8096
+ })
8097
+ ]
7810
8098
  }),
7811
8099
  showLicenseWarning && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7812
8100
  style: {
@@ -7850,6 +8138,48 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7850
8138
  })
7851
8139
  ]
7852
8140
  }),
8141
+ adStatus.showAds && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8142
+ style: {
8143
+ position: "absolute",
8144
+ top: "".concat(12 * responsiveScale, "px"),
8145
+ left: "".concat(12 * responsiveScale, "px"),
8146
+ zIndex: 50,
8147
+ display: "flex",
8148
+ alignItems: "center",
8149
+ gap: "8px",
8150
+ pointerEvents: "none",
8151
+ animation: "sc-fade-in 0.3s ease"
8152
+ },
8153
+ children: [
8154
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8155
+ style: {
8156
+ background: "rgba(234, 179, 8, 0.95)",
8157
+ color: "#111",
8158
+ padding: "".concat(4 * responsiveScale, "px ").concat(12 * responsiveScale, "px"),
8159
+ borderRadius: "6px",
8160
+ fontSize: "".concat(11 * responsiveScale, "px"),
8161
+ fontWeight: 700,
8162
+ letterSpacing: "0.08em",
8163
+ textTransform: "uppercase",
8164
+ boxShadow: "0 2px 12px rgba(234, 179, 8, 0.35)"
8165
+ },
8166
+ children: "Ad"
8167
+ }),
8168
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8169
+ style: {
8170
+ background: "rgba(0, 0, 0, 0.58)",
8171
+ color: "rgba(255, 255, 255, 0.92)",
8172
+ padding: "".concat(4 * responsiveScale, "px ").concat(10 * responsiveScale, "px"),
8173
+ borderRadius: "6px",
8174
+ fontSize: "".concat(11 * responsiveScale, "px"),
8175
+ fontWeight: 600,
8176
+ border: "1px solid rgba(255, 255, 255, 0.1)",
8177
+ boxShadow: "0 2px 10px rgba(0, 0, 0, 0.25)"
8178
+ },
8179
+ children: "".concat(Math.max(1, adStatus.currentIndex), " of ").concat(Math.max(Math.max(1, adStatus.currentIndex), adStatus.totalAds))
8180
+ })
8181
+ ]
8182
+ }),
7853
8183
  showCenterPlay && !isLoading && !isBuffering && !showLicenseWarning && !adStatus.showAds && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
7854
8184
  onClick: handleCenterPlayClick,
7855
8185
  style: {
@@ -7989,7 +8319,8 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
7989
8319
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
7990
8320
  style: {
7991
8321
  display: "flex",
7992
- alignItems: "center"
8322
+ alignItems: "center",
8323
+ paddingRight: "".concat(6 * responsiveScale, "px")
7993
8324
  },
7994
8325
  onMouseEnter: function onMouseEnter() {
7995
8326
  return setShowVolumeSlider(true);
@@ -8018,13 +8349,13 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
8018
8349
  }),
8019
8350
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8020
8351
  style: {
8021
- width: showVolumeSlider ? "".concat(62 * responsiveScale, "px") : "0px",
8352
+ width: showVolumeSlider ? "".concat(68 * responsiveScale, "px") : "0px",
8022
8353
  overflow: "hidden",
8023
8354
  transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
8024
8355
  display: "flex",
8025
8356
  alignItems: "center",
8026
- paddingLeft: showVolumeSlider ? "2px" : "0",
8027
- paddingRight: showVolumeSlider ? "4px" : "0"
8357
+ paddingLeft: showVolumeSlider ? "".concat(3 * responsiveScale, "px") : "0",
8358
+ paddingRight: showVolumeSlider ? "".concat(8 * responsiveScale, "px") : "0"
8028
8359
  },
8029
8360
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8030
8361
  style: {
@@ -8271,7 +8602,8 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
8271
8602
  alignItems: "center",
8272
8603
  background: "rgba(0, 0, 0, 0.6)",
8273
8604
  borderRadius: "".concat(18 * responsiveScale, "px"),
8274
- padding: "2px"
8605
+ padding: "2px",
8606
+ paddingRight: "".concat(8 * responsiveScale, "px")
8275
8607
  },
8276
8608
  onMouseEnter: function onMouseEnter() {
8277
8609
  return setShowVolumeSlider(true);
@@ -8300,13 +8632,13 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
8300
8632
  }),
8301
8633
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8302
8634
  style: {
8303
- width: showVolumeSlider ? "".concat(62 * responsiveScale, "px") : "0px",
8635
+ width: showVolumeSlider ? "".concat(68 * responsiveScale, "px") : "0px",
8304
8636
  overflow: "hidden",
8305
8637
  transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
8306
8638
  display: "flex",
8307
8639
  alignItems: "center",
8308
- paddingLeft: showVolumeSlider ? "2px" : "0",
8309
- paddingRight: showVolumeSlider ? "6px" : "0"
8640
+ paddingLeft: showVolumeSlider ? "".concat(3 * responsiveScale, "px") : "0",
8641
+ paddingRight: showVolumeSlider ? "".concat(10 * responsiveScale, "px") : "0"
8310
8642
  },
8311
8643
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
8312
8644
  style: {
@@ -8542,6 +8874,7 @@ var defaultProps = {
8542
8874
  showCustomControls: false,
8543
8875
  hideLoadingIndicator: false,
8544
8876
  licenseKey: "",
8877
+ vmapUrl: "",
8545
8878
  adFailsafeTimeoutMs: 1e4,
8546
8879
  minSegmentsBeforePlay: 2,
8547
8880
  onStart: noop,
@@ -9485,6 +9818,7 @@ var SUPPORTED_PROPS = [
9485
9818
  "debugAdTiming",
9486
9819
  "showCustomControls",
9487
9820
  "licenseKey",
9821
+ "vmapUrl",
9488
9822
  "adFailsafeTimeoutMs",
9489
9823
  "minSegmentsBeforePlay",
9490
9824
  "onReady",