stormcloud-video-player 0.7.11 → 0.7.12

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
@@ -1582,7 +1582,6 @@ function createAdStormPlayer(contentVideo, options) {
1582
1582
  contentVideo.muted = originalMutedState;
1583
1583
  contentVideo.volume = originalVolume;
1584
1584
  currentAd = void 0;
1585
- tornDown = false;
1586
1585
  return [
1587
1586
  2,
1588
1587
  Promise.resolve()
@@ -1697,6 +1696,15 @@ function createAdStormPlayer(contentVideo, options) {
1697
1696
  if (!token) return [
1698
1697
  2
1699
1698
  ];
1699
+ if (currentAd) {
1700
+ preloadSlots.set(token, {
1701
+ ad: currentAd
1702
+ });
1703
+ currentAd = void 0;
1704
+ return [
1705
+ 2
1706
+ ];
1707
+ }
1700
1708
  requestContext = typeof arg1 === "string" ? arg2 : arg1;
1701
1709
  return [
1702
1710
  4,
@@ -2190,56 +2198,6 @@ function sendInitialTracking(licenseKey) {
2190
2198
  });
2191
2199
  })();
2192
2200
  }
2193
- function sendAdDetectTracking(licenseKey, adDetectInfo) {
2194
- return _async_to_generator(function() {
2195
- var clientInfo, browserId, trackingData, error;
2196
- return _ts_generator(this, function(_state) {
2197
- switch(_state.label){
2198
- case 0:
2199
- _state.trys.push([
2200
- 0,
2201
- 3,
2202
- ,
2203
- 4
2204
- ]);
2205
- clientInfo = getClientInfo();
2206
- return [
2207
- 4,
2208
- getBrowserID(clientInfo)
2209
- ];
2210
- case 1:
2211
- browserId = _state.sent();
2212
- trackingData = _object_spread({
2213
- browserId: browserId
2214
- }, clientInfo);
2215
- return [
2216
- 4,
2217
- sendTrackRequest(licenseKey, _object_spread_props(_object_spread({}, trackingData), {
2218
- licenseKey: licenseKey,
2219
- adDetectInfo: adDetectInfo
2220
- }))
2221
- ];
2222
- case 2:
2223
- _state.sent();
2224
- return [
2225
- 3,
2226
- 4
2227
- ];
2228
- case 3:
2229
- error = _state.sent();
2230
- console.error("[StormcloudVideoPlayer] Error sending ad detect tracking:", error);
2231
- return [
2232
- 3,
2233
- 4
2234
- ];
2235
- case 4:
2236
- return [
2237
- 2
2238
- ];
2239
- }
2240
- });
2241
- })();
2242
- }
2243
2201
  function sendAdLoadedTracking(licenseKey, adLoadedInfo) {
2244
2202
  return _async_to_generator(function() {
2245
2203
  var clientInfo, browserId, trackingData, error;
@@ -2949,7 +2907,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2949
2907
  this.continuousFetchLoopPromise = null;
2950
2908
  this.attached = false;
2951
2909
  this.inAdBreak = false;
2952
- this.ptsDriftEmaMs = 0;
2953
2910
  this.adPodQueue = [];
2954
2911
  this.lastHeartbeatTime = 0;
2955
2912
  this.currentAdIndex = 0;
@@ -2973,7 +2930,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2973
2930
  this.totalAdRequestsInBreak = 0;
2974
2931
  this.maxTotalAdRequestsPerBreak = 20;
2975
2932
  this.pendingAdBreak = null;
2976
- this.savedMutedStateBeforeScte = null;
2933
+ this.savedMutedStateBeforeAd = null;
2977
2934
  this.consecutiveFailures = 0;
2978
2935
  this.maxConsecutiveFailures = 5;
2979
2936
  this.lastAdRequestTime = 0;
@@ -2986,7 +2943,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2986
2943
  this.adRequestRetryBackoffMs = 1500;
2987
2944
  this.preloadedTokens = [];
2988
2945
  this.debugLogEntries = [];
2989
- this.scteMarkerHistory = [];
2990
2946
  this.adInsertionDebugHistory = [];
2991
2947
  initializePolyfills();
2992
2948
  var browserOverrides = getBrowserConfigOverrides();
@@ -3275,18 +3231,44 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3275
3231
  _this.pushAdInsertionDebug("ad_triggered", segmentName, {
3276
3232
  detail: "ad break started (60s)"
3277
3233
  });
3278
- var marker = {
3279
- type: "start",
3280
- durationSeconds: 60,
3281
- raw: {
3282
- apiInsertionPoint: _this.lastAdInsertionPoint
3283
- }
3284
- };
3285
- _this.onScte35Marker(marker);
3234
+ void _this.handleAdStart(60);
3286
3235
  }, offsetMs);
3287
3236
  }
3288
3237
  }
3289
3238
  });
3239
+ this.hls.on(import_hls.default.Events.FRAG_PARSING_USERDATA, function(_evt, data) {
3240
+ var _ref;
3241
+ var samples = (_ref = data === null || data === void 0 ? void 0 : data.samples) !== null && _ref !== void 0 ? _ref : [];
3242
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3243
+ try {
3244
+ for(var _iterator = samples[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3245
+ var sample = _step.value;
3246
+ var _ref1, _ref2;
3247
+ var _data_frag, _data_frag1;
3248
+ var bytes = sample === null || sample === void 0 ? void 0 : sample.data;
3249
+ if (!bytes || bytes.length < 5) continue;
3250
+ var isSCTE35 = bytes[0] === 252;
3251
+ if (!isSCTE35) continue;
3252
+ var segName = (_ref1 = (_ref2 = data === null || data === void 0 ? void 0 : (_data_frag = data.frag) === null || _data_frag === void 0 ? void 0 : _data_frag.relurl) !== null && _ref2 !== void 0 ? _ref2 : data === null || data === void 0 ? void 0 : (_data_frag1 = data.frag) === null || _data_frag1 === void 0 ? void 0 : _data_frag1.url) !== null && _ref1 !== void 0 ? _ref1 : "";
3253
+ _this.pushAdInsertionDebug("scte35_inserted", segName, {
3254
+ detail: "len=".concat(bytes.length, "B")
3255
+ });
3256
+ }
3257
+ } catch (err) {
3258
+ _didIteratorError = true;
3259
+ _iteratorError = err;
3260
+ } finally{
3261
+ try {
3262
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
3263
+ _iterator.return();
3264
+ }
3265
+ } finally{
3266
+ if (_didIteratorError) {
3267
+ throw _iteratorError;
3268
+ }
3269
+ }
3270
+ }
3271
+ });
3290
3272
  this.hls.on(import_hls.default.Events.ERROR, function(_evt, data) {
3291
3273
  if (data === null || data === void 0 ? void 0 : data.fatal) {
3292
3274
  switch(data.type){
@@ -3361,8 +3343,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3361
3343
  _this.activeAdRequestToken = null;
3362
3344
  _this.showAds = true;
3363
3345
  if (_this.config.disableFiller) {
3364
- if (_this.savedMutedStateBeforeScte == null) {
3365
- _this.savedMutedStateBeforeScte = {
3346
+ if (_this.savedMutedStateBeforeAd == null) {
3347
+ _this.savedMutedStateBeforeAd = {
3366
3348
  muted: _this.video.muted,
3367
3349
  volume: _this.video.volume
3368
3350
  };
@@ -3390,10 +3372,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3390
3372
  });
3391
3373
  this.adLayer.on("content_resume", function() {
3392
3374
  var _ref, _ref1;
3393
- var _this_savedMutedStateBeforeScte, _this_savedMutedStateBeforeScte1;
3375
+ var _this_savedMutedStateBeforeAd, _this_savedMutedStateBeforeAd1;
3394
3376
  var remaining = _this.getRemainingAdMs();
3395
- var breakMuted = (_ref = (_this_savedMutedStateBeforeScte = _this.savedMutedStateBeforeScte) === null || _this_savedMutedStateBeforeScte === void 0 ? void 0 : _this_savedMutedStateBeforeScte.muted) !== null && _ref !== void 0 ? _ref : _this.adLayer.getOriginalMutedState();
3396
- var breakVolume = (_ref1 = (_this_savedMutedStateBeforeScte1 = _this.savedMutedStateBeforeScte) === null || _this_savedMutedStateBeforeScte1 === void 0 ? void 0 : _this_savedMutedStateBeforeScte1.volume) !== null && _ref1 !== void 0 ? _ref1 : _this.adLayer.getOriginalVolume();
3377
+ var breakMuted = (_ref = (_this_savedMutedStateBeforeAd = _this.savedMutedStateBeforeAd) === null || _this_savedMutedStateBeforeAd === void 0 ? void 0 : _this_savedMutedStateBeforeAd.muted) !== null && _ref !== void 0 ? _ref : _this.adLayer.getOriginalMutedState();
3378
+ var breakVolume = (_ref1 = (_this_savedMutedStateBeforeAd1 = _this.savedMutedStateBeforeAd) === null || _this_savedMutedStateBeforeAd1 === void 0 ? void 0 : _this_savedMutedStateBeforeAd1.volume) !== null && _ref1 !== void 0 ? _ref1 : _this.adLayer.getOriginalVolume();
3397
3379
  if (_this.config.debugAdTiming) {
3398
3380
  console.log("[StormcloudVideoPlayer] content_resume received, inAdBreak=%s, remaining=%s, preloadedTokens=%d, pendingNext=%s", _this.inAdBreak, remaining, _this.preloadedTokens.length, !!_this.pendingNextAdBids);
3399
3381
  }
@@ -3470,7 +3452,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3470
3452
  var remainingFinal = _this.getRemainingAdMs();
3471
3453
  if (_this.inAdBreak && remainingFinal > _this.MIN_AD_REMAINING_MS) {
3472
3454
  if (_this.config.debugAdTiming) {
3473
- console.log("[StormcloudVideoPlayer] content_resume: no more ads, showing filler for", remainingFinal, "ms");
3455
+ console.log("[StormcloudVideoPlayer] content_resume: ad ended/failed with time remaining, showing filler and continuing fetch for", remainingFinal, "ms");
3474
3456
  }
3475
3457
  if (!_this.config.disableFiller) {
3476
3458
  _this.showPlaceholderLayer();
@@ -3488,7 +3470,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3488
3470
  (_this_video_play = _this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
3489
3471
  }
3490
3472
  }
3491
- _this.stopContinuousFetching();
3473
+ _this.continuousFetchingActive = true;
3474
+ _this.startContinuousFetchLoop();
3492
3475
  return;
3493
3476
  }
3494
3477
  if (_this.config.debugAdTiming) {
@@ -3635,547 +3618,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3635
3618
  return !!(this.config.allowNativeHls && canNative);
3636
3619
  }
3637
3620
  },
3638
- {
3639
- key: "onId3Tag",
3640
- value: function onId3Tag(tag) {
3641
- if (typeof tag.ptsSeconds === "number") {
3642
- this.updatePtsDrift(tag.ptsSeconds);
3643
- }
3644
- var marker = this.parseScte35FromId3(tag);
3645
- if (marker) {
3646
- this.onScte35Marker(marker);
3647
- }
3648
- }
3649
- },
3650
- {
3651
- key: "parseScte35FromId3",
3652
- value: function parseScte35FromId3(tag) {
3653
- var text = this.decodeId3ValueToText(tag.value);
3654
- if (!text) return void 0;
3655
- var cueOutMatch = text.match(/EXT-X-CUE-OUT(?::([^\r\n]*))?/i) || text.match(/CUE-OUT(?::([^\r\n]*))?/i);
3656
- if (cueOutMatch) {
3657
- var _cueOutMatch_;
3658
- var arg = ((_cueOutMatch_ = cueOutMatch[1]) !== null && _cueOutMatch_ !== void 0 ? _cueOutMatch_ : "").trim();
3659
- var dur = this.parseCueOutDuration(arg);
3660
- var marker = _object_spread_props(_object_spread({
3661
- type: "start"
3662
- }, tag.ptsSeconds !== void 0 ? {
3663
- ptsSeconds: tag.ptsSeconds
3664
- } : {}, dur !== void 0 ? {
3665
- durationSeconds: dur
3666
- } : {}), {
3667
- raw: {
3668
- id3: text
3669
- }
3670
- });
3671
- return marker;
3672
- }
3673
- var cueOutContMatch = text.match(/EXT-X-CUE-OUT-CONT:([^\r\n]*)/i);
3674
- if (cueOutContMatch) {
3675
- var _cueOutContMatch_;
3676
- var arg1 = ((_cueOutContMatch_ = cueOutContMatch[1]) !== null && _cueOutContMatch_ !== void 0 ? _cueOutContMatch_ : "").trim();
3677
- var cont = this.parseCueOutCont(arg1);
3678
- var marker1 = _object_spread_props(_object_spread({
3679
- type: "progress"
3680
- }, tag.ptsSeconds !== void 0 ? {
3681
- ptsSeconds: tag.ptsSeconds
3682
- } : {}, (cont === null || cont === void 0 ? void 0 : cont.duration) !== void 0 ? {
3683
- durationSeconds: cont.duration
3684
- } : {}), {
3685
- raw: {
3686
- id3: text
3687
- }
3688
- });
3689
- return marker1;
3690
- }
3691
- var cueInMatch = text.match(/EXT-X-CUE-IN\b/i) || text.match(/CUE-IN\b/i);
3692
- if (cueInMatch) {
3693
- var marker2 = _object_spread_props(_object_spread({
3694
- type: "end"
3695
- }, tag.ptsSeconds !== void 0 ? {
3696
- ptsSeconds: tag.ptsSeconds
3697
- } : {}), {
3698
- raw: {
3699
- id3: text
3700
- }
3701
- });
3702
- return marker2;
3703
- }
3704
- var daterangeMatch = text.match(/EXT-X-DATERANGE:([^\r\n]*)/i);
3705
- if (daterangeMatch) {
3706
- var _daterangeMatch_, _attrs_CLASS;
3707
- var attrs = this.parseAttributeList((_daterangeMatch_ = daterangeMatch[1]) !== null && _daterangeMatch_ !== void 0 ? _daterangeMatch_ : "");
3708
- var hasScteOut = "SCTE35-OUT" in attrs || attrs["SCTE35-OUT"] !== void 0;
3709
- var hasScteIn = "SCTE35-IN" in attrs || attrs["SCTE35-IN"] !== void 0;
3710
- var klass = String((_attrs_CLASS = attrs["CLASS"]) !== null && _attrs_CLASS !== void 0 ? _attrs_CLASS : "");
3711
- var duration = this.toNumber(attrs["DURATION"]);
3712
- if (hasScteOut || /com\.apple\.hls\.cue/i.test(klass)) {
3713
- var marker3 = _object_spread_props(_object_spread({
3714
- type: "start"
3715
- }, tag.ptsSeconds !== void 0 ? {
3716
- ptsSeconds: tag.ptsSeconds
3717
- } : {}, duration !== void 0 ? {
3718
- durationSeconds: duration
3719
- } : {}), {
3720
- raw: {
3721
- id3: text,
3722
- attrs: attrs
3723
- }
3724
- });
3725
- return marker3;
3726
- }
3727
- if (hasScteIn) {
3728
- var marker4 = _object_spread_props(_object_spread({
3729
- type: "end"
3730
- }, tag.ptsSeconds !== void 0 ? {
3731
- ptsSeconds: tag.ptsSeconds
3732
- } : {}), {
3733
- raw: {
3734
- id3: text,
3735
- attrs: attrs
3736
- }
3737
- });
3738
- return marker4;
3739
- }
3740
- }
3741
- if (/SCTE35-OUT/i.test(text)) {
3742
- var marker5 = _object_spread_props(_object_spread({
3743
- type: "start"
3744
- }, tag.ptsSeconds !== void 0 ? {
3745
- ptsSeconds: tag.ptsSeconds
3746
- } : {}), {
3747
- raw: {
3748
- id3: text
3749
- }
3750
- });
3751
- return marker5;
3752
- }
3753
- if (/SCTE35-IN/i.test(text)) {
3754
- var marker6 = _object_spread_props(_object_spread({
3755
- type: "end"
3756
- }, tag.ptsSeconds !== void 0 ? {
3757
- ptsSeconds: tag.ptsSeconds
3758
- } : {}), {
3759
- raw: {
3760
- id3: text
3761
- }
3762
- });
3763
- return marker6;
3764
- }
3765
- if (_instanceof(tag.value, Uint8Array)) {
3766
- var bin = this.parseScte35Binary(tag.value);
3767
- if (bin) return bin;
3768
- }
3769
- return void 0;
3770
- }
3771
- },
3772
- {
3773
- key: "decodeId3ValueToText",
3774
- value: function decodeId3ValueToText(value) {
3775
- try {
3776
- if (typeof value === "string") return value;
3777
- var decoder = new TextDecoder("utf-8", {
3778
- fatal: false
3779
- });
3780
- var text = decoder.decode(value);
3781
- if (text && /[\x20-\x7E]/.test(text)) return text;
3782
- var out = "";
3783
- for(var i = 0; i < value.length; i++)out += String.fromCharCode(value[i]);
3784
- return out;
3785
- } catch (unused) {
3786
- return void 0;
3787
- }
3788
- }
3789
- },
3790
- {
3791
- key: "onScte35Marker",
3792
- value: function onScte35Marker(marker) {
3793
- var _this = this;
3794
- if (this.config.disableAds) return;
3795
- this.pushScteMarker(marker);
3796
- this.pushDebugLog("info", "scte35", "SCTE-35 marker detected", {
3797
- type: marker.type,
3798
- ptsSeconds: marker.ptsSeconds,
3799
- durationSeconds: marker.durationSeconds,
3800
- currentTime: this.video.currentTime
3801
- });
3802
- if (this.config.debugAdTiming) {
3803
- console.log("[StormcloudVideoPlayer] SCTE-35 marker detected:", {
3804
- type: marker.type,
3805
- ptsSeconds: marker.ptsSeconds,
3806
- durationSeconds: marker.durationSeconds,
3807
- currentTime: this.video.currentTime,
3808
- raw: marker.raw,
3809
- hasPendingAdBreak: !!this.pendingAdBreak
3810
- });
3811
- }
3812
- if (marker.type === "start") {
3813
- var _this_config_immediateManifestAds;
3814
- var _this_pendingAdBreak;
3815
- if (this.savedMutedStateBeforeScte == null) {
3816
- this.savedMutedStateBeforeScte = {
3817
- muted: this.video.muted,
3818
- volume: this.video.volume
3819
- };
3820
- this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);
3821
- }
3822
- if (!this.config.disableFiller && !this.video.muted && !this.adLayer.isAdPlaying()) {
3823
- this.video.muted = true;
3824
- this.video.volume = 0;
3825
- if (this.config.debugAdTiming) {
3826
- console.log("[StormcloudVideoPlayer] Muted video on SCTE start marker");
3827
- }
3828
- }
3829
- if (this.inAdBreak) {
3830
- if (marker.durationSeconds != null) {
3831
- var newDurationMs = marker.durationSeconds * 1e3;
3832
- if (this.expectedAdBreakDurationMs == null || newDurationMs > this.expectedAdBreakDurationMs) {
3833
- this.expectedAdBreakDurationMs = newDurationMs;
3834
- var elapsedMs = this.currentAdBreakStartWallClockMs != null ? Date.now() - this.currentAdBreakStartWallClockMs : 0;
3835
- var remainingMs = Math.max(0, newDurationMs - elapsedMs);
3836
- this.scheduleAdStopCountdown(remainingMs);
3837
- if (this.config.debugAdTiming) {
3838
- console.log("[StormcloudVideoPlayer] Updated ad break duration from subsequent marker: ".concat(newDurationMs, "ms, remaining: ").concat(remainingMs, "ms"));
3839
- }
3840
- }
3841
- }
3842
- return;
3843
- }
3844
- this.inAdBreak = true;
3845
- var durationMs = marker.durationSeconds != null ? marker.durationSeconds * 1e3 : ((_this_pendingAdBreak = this.pendingAdBreak) === null || _this_pendingAdBreak === void 0 ? void 0 : _this_pendingAdBreak.marker.durationSeconds) != null ? this.pendingAdBreak.marker.durationSeconds * 1e3 : void 0;
3846
- this.expectedAdBreakDurationMs = durationMs;
3847
- this.currentAdBreakStartWallClockMs = Date.now();
3848
- if (this.config.licenseKey) {
3849
- var _this_pendingAdBreak1;
3850
- var adDetectInfo = _object_spread({
3851
- source: "scte35",
3852
- timestamp: /* @__PURE__ */ new Date().toISOString()
3853
- }, marker.durationSeconds != null && {
3854
- durationSeconds: marker.durationSeconds
3855
- }, marker.ptsSeconds != null && {
3856
- ptsSeconds: marker.ptsSeconds
3857
- }, ((_this_pendingAdBreak1 = this.pendingAdBreak) === null || _this_pendingAdBreak1 === void 0 ? void 0 : _this_pendingAdBreak1.detectedAtFragmentSn) != null && {
3858
- detectedAtFragmentSn: this.pendingAdBreak.detectedAtFragmentSn
3859
- });
3860
- sendAdDetectTracking(this.config.licenseKey, adDetectInfo);
3861
- }
3862
- var isManifestMarker = this.isManifestBasedMarker(marker);
3863
- var forceImmediate = (_this_config_immediateManifestAds = this.config.immediateManifestAds) !== null && _this_config_immediateManifestAds !== void 0 ? _this_config_immediateManifestAds : true;
3864
- if (this.config.debugAdTiming) {
3865
- console.log("[StormcloudVideoPlayer] Ad start decision:", {
3866
- isManifestMarker: isManifestMarker,
3867
- forceImmediate: forceImmediate,
3868
- hasPts: typeof marker.ptsSeconds === "number"
3869
- });
3870
- }
3871
- if (isManifestMarker && forceImmediate) {
3872
- if (this.config.debugAdTiming) {
3873
- console.log("[StormcloudVideoPlayer] Starting ad immediately (manifest-based)");
3874
- }
3875
- this.clearAdStartTimer();
3876
- this.handleAdStart(marker);
3877
- } else if (typeof marker.ptsSeconds === "number") {
3878
- var _this_config_driftToleranceMs;
3879
- var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
3880
- var nowMs = this.video.currentTime * 1e3;
3881
- var estCurrentPtsMs = nowMs - this.ptsDriftEmaMs;
3882
- var deltaMs = Math.floor(marker.ptsSeconds * 1e3 - estCurrentPtsMs);
3883
- if (this.config.debugAdTiming) {
3884
- console.log("[StormcloudVideoPlayer] PTS-based timing calculation:", {
3885
- nowMs: nowMs,
3886
- estCurrentPtsMs: estCurrentPtsMs,
3887
- markerPtsMs: marker.ptsSeconds * 1e3,
3888
- deltaMs: deltaMs,
3889
- tolerance: tol
3890
- });
3891
- }
3892
- if (deltaMs > tol) {
3893
- if (this.config.debugAdTiming) {
3894
- console.log("[StormcloudVideoPlayer] Scheduling ad start in ".concat(deltaMs, "ms"));
3895
- }
3896
- this.scheduleAdStartIn(deltaMs);
3897
- } else {
3898
- if (this.config.debugAdTiming) {
3899
- console.log("[StormcloudVideoPlayer] Starting ad immediately (within tolerance)");
3900
- }
3901
- this.clearAdStartTimer();
3902
- this.handleAdStart(marker);
3903
- }
3904
- } else {
3905
- if (this.config.debugAdTiming) {
3906
- console.log("[StormcloudVideoPlayer] Starting ad immediately (fallback)");
3907
- }
3908
- this.clearAdStartTimer();
3909
- this.handleAdStart(marker);
3910
- }
3911
- if (this.expectedAdBreakDurationMs != null) {
3912
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
3913
- }
3914
- return;
3915
- }
3916
- if (marker.type === "progress" && this.inAdBreak) {
3917
- if (marker.durationSeconds != null) {
3918
- this.expectedAdBreakDurationMs = marker.durationSeconds * 1e3;
3919
- }
3920
- if (this.expectedAdBreakDurationMs != null && this.currentAdBreakStartWallClockMs != null) {
3921
- var elapsedMs1 = Date.now() - this.currentAdBreakStartWallClockMs;
3922
- var remainingMs1 = Math.max(0, this.expectedAdBreakDurationMs - elapsedMs1);
3923
- this.scheduleAdStopCountdown(remainingMs1);
3924
- }
3925
- if (!this.adLayer.isAdPlaying() && this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0) {
3926
- var bids = this.pendingNextAdBids;
3927
- this.pendingNextAdBids = null;
3928
- this.currentAdIndex++;
3929
- this.adLayer.playAd(bids).catch(function() {
3930
- return _this.handleAdFailure();
3931
- });
3932
- }
3933
- return;
3934
- }
3935
- if (marker.type === "end") {
3936
- var remaining = this.getRemainingAdMs();
3937
- var adPlaying = this.adLayer.isAdPlaying();
3938
- var hasQueuedAds = this.pendingNextAdBids != null && this.pendingNextAdBids.length > 0;
3939
- if (this.config.debugAdTiming) {
3940
- console.log("[StormcloudVideoPlayer] SCTE-35 end marker received:", {
3941
- inAdBreak: this.inAdBreak,
3942
- remaining: remaining,
3943
- adPlaying: adPlaying,
3944
- hasQueuedAds: hasQueuedAds,
3945
- activeAdRequest: this.activeAdRequestToken !== null
3946
- });
3947
- }
3948
- if (!this.inAdBreak) {
3949
- if (this.config.debugAdTiming) {
3950
- console.log("[StormcloudVideoPlayer] Ignoring SCTE-35 end marker - not in ad break");
3951
- }
3952
- return;
3953
- }
3954
- if (adPlaying || remaining > 500) {
3955
- if (this.config.debugAdTiming) {
3956
- console.log("[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active or time remaining");
3957
- }
3958
- return;
3959
- }
3960
- this.inAdBreak = false;
3961
- this.expectedAdBreakDurationMs = void 0;
3962
- this.currentAdBreakStartWallClockMs = void 0;
3963
- this.clearAdStartTimer();
3964
- this.clearAdStopTimer();
3965
- if (adPlaying) {
3966
- this.adLayer.stop().catch(function() {});
3967
- }
3968
- this.handleAdPodComplete();
3969
- return;
3970
- }
3971
- }
3972
- },
3973
- {
3974
- key: "parseCueOutDuration",
3975
- value: function parseCueOutDuration(value) {
3976
- var num = parseFloat(value.trim());
3977
- if (!Number.isNaN(num)) return num;
3978
- var match = value.match(/(?:^|[,\s])DURATION\s*=\s*([0-9.]+)/i) || value.match(/Duration\s*=\s*([0-9.]+)/i);
3979
- if (match && match[1] != null) {
3980
- var dStr = match[1];
3981
- var d = parseFloat(dStr);
3982
- return Number.isNaN(d) ? void 0 : d;
3983
- }
3984
- return void 0;
3985
- }
3986
- },
3987
- {
3988
- key: "parseCueOutCont",
3989
- value: function parseCueOutCont(value) {
3990
- var res = {};
3991
- var elapsedMatch = value.match(/Elapsed\s*=\s*([0-9.]+)/i);
3992
- var durationMatch = value.match(/Duration\s*=\s*([0-9.]+)/i);
3993
- if (elapsedMatch && elapsedMatch[1] != null) {
3994
- var e = parseFloat(elapsedMatch[1]);
3995
- if (!Number.isNaN(e)) res.elapsed = e;
3996
- }
3997
- if (durationMatch && durationMatch[1] != null) {
3998
- var d = parseFloat(durationMatch[1]);
3999
- if (!Number.isNaN(d)) res.duration = d;
4000
- }
4001
- if (!("elapsed" in res) || !("duration" in res)) {
4002
- var slashMatch = value.match(/([0-9.]+)\s*\/\s*([0-9.]+)/);
4003
- if (slashMatch && slashMatch[1] && slashMatch[2]) {
4004
- var elapsed = parseFloat(slashMatch[1]);
4005
- var duration = parseFloat(slashMatch[2]);
4006
- if (!Number.isNaN(elapsed) && !("elapsed" in res)) res.elapsed = elapsed;
4007
- if (!Number.isNaN(duration) && !("duration" in res)) res.duration = duration;
4008
- }
4009
- }
4010
- if ("elapsed" in res || "duration" in res) return res;
4011
- return void 0;
4012
- }
4013
- },
4014
- {
4015
- key: "parseAttributeList",
4016
- value: function parseAttributeList(value) {
4017
- var attrs = {};
4018
- var regex = /([A-Z0-9-]+)=(("[^"]*")|([^",]*))(?:,|$)/gi;
4019
- var match;
4020
- while((match = regex.exec(value)) !== null){
4021
- var _match_, _ref, _match_1;
4022
- var key = (_match_ = match[1]) !== null && _match_ !== void 0 ? _match_ : "";
4023
- var rawVal = (_ref = (_match_1 = match[3]) !== null && _match_1 !== void 0 ? _match_1 : match[4]) !== null && _ref !== void 0 ? _ref : "";
4024
- if (rawVal.startsWith('"') && rawVal.endsWith('"')) {
4025
- rawVal = rawVal.slice(1, -1);
4026
- }
4027
- if (key) {
4028
- attrs[key] = rawVal;
4029
- }
4030
- }
4031
- return attrs;
4032
- }
4033
- },
4034
- {
4035
- key: "toNumber",
4036
- value: function toNumber(val) {
4037
- if (val == null) return void 0;
4038
- var n = typeof val === "string" ? parseFloat(val) : Number(val);
4039
- return Number.isNaN(n) ? void 0 : n;
4040
- }
4041
- },
4042
- {
4043
- key: "isManifestBasedMarker",
4044
- value: function isManifestBasedMarker(marker) {
4045
- var raw = marker.raw;
4046
- if (!raw) return false;
4047
- if (raw.tag) {
4048
- var tag = String(raw.tag);
4049
- return tag.includes("EXT-X-CUE-OUT") || tag.includes("EXT-X-CUE-IN") || tag.includes("EXT-X-DATERANGE");
4050
- }
4051
- if (raw.id3) return false;
4052
- if (raw.splice_command_type) return false;
4053
- return false;
4054
- }
4055
- },
4056
- {
4057
- key: "parseScte35Binary",
4058
- value: function parseScte35Binary(data) {
4059
- var BitReader = /*#__PURE__*/ function() {
4060
- function BitReader(buf) {
4061
- _class_call_check(this, BitReader);
4062
- this.buf = buf;
4063
- this.bytePos = 0;
4064
- this.bitPos = 0;
4065
- }
4066
- _create_class(BitReader, [
4067
- {
4068
- key: "readBits",
4069
- value: function readBits(numBits) {
4070
- var result = 0;
4071
- while(numBits > 0){
4072
- if (this.bytePos >= this.buf.length) return result;
4073
- var remainingInByte = 8 - this.bitPos;
4074
- var toRead = Math.min(numBits, remainingInByte);
4075
- var currentByte = this.buf[this.bytePos];
4076
- var shift = remainingInByte - toRead;
4077
- var mask = (1 << toRead) - 1 & 255;
4078
- var bits = currentByte >> shift & mask;
4079
- result = result << toRead | bits;
4080
- this.bitPos += toRead;
4081
- if (this.bitPos >= 8) {
4082
- this.bitPos = 0;
4083
- this.bytePos += 1;
4084
- }
4085
- numBits -= toRead;
4086
- }
4087
- return result >>> 0;
4088
- }
4089
- },
4090
- {
4091
- key: "skipBits",
4092
- value: function skipBits(n) {
4093
- this.readBits(n);
4094
- }
4095
- }
4096
- ]);
4097
- return BitReader;
4098
- }();
4099
- var r = new BitReader(data);
4100
- var tableId = r.readBits(8);
4101
- if (tableId !== 252) return void 0;
4102
- r.readBits(1);
4103
- r.readBits(1);
4104
- r.readBits(2);
4105
- var sectionLength = r.readBits(12);
4106
- r.readBits(8);
4107
- r.readBits(1);
4108
- r.readBits(6);
4109
- var ptsAdjHigh = r.readBits(1);
4110
- var ptsAdjLow = r.readBits(32);
4111
- void ptsAdjHigh;
4112
- void ptsAdjLow;
4113
- r.readBits(8);
4114
- r.readBits(12);
4115
- var spliceCommandLength = r.readBits(12);
4116
- var spliceCommandType = r.readBits(8);
4117
- if (spliceCommandType !== 5) {
4118
- return void 0;
4119
- }
4120
- r.readBits(32);
4121
- var cancel = r.readBits(1) === 1;
4122
- r.readBits(7);
4123
- if (cancel) return void 0;
4124
- var outOfNetwork = r.readBits(1) === 1;
4125
- var programSpliceFlag = r.readBits(1) === 1;
4126
- var durationFlag = r.readBits(1) === 1;
4127
- var spliceImmediateFlag = r.readBits(1) === 1;
4128
- r.readBits(4);
4129
- if (programSpliceFlag && !spliceImmediateFlag) {
4130
- var timeSpecifiedFlag = r.readBits(1) === 1;
4131
- if (timeSpecifiedFlag) {
4132
- r.readBits(6);
4133
- r.readBits(33);
4134
- } else {
4135
- r.readBits(7);
4136
- }
4137
- } else if (!programSpliceFlag) {
4138
- var componentCount = r.readBits(8);
4139
- for(var i = 0; i < componentCount; i++){
4140
- r.readBits(8);
4141
- if (!spliceImmediateFlag) {
4142
- var timeSpecifiedFlag1 = r.readBits(1) === 1;
4143
- if (timeSpecifiedFlag1) {
4144
- r.readBits(6);
4145
- r.readBits(33);
4146
- } else {
4147
- r.readBits(7);
4148
- }
4149
- }
4150
- }
4151
- }
4152
- var durationSeconds = void 0;
4153
- if (durationFlag) {
4154
- r.readBits(6);
4155
- r.readBits(1);
4156
- var high = r.readBits(1);
4157
- var low = r.readBits(32);
4158
- var durationTicks = high * 4294967296 + low;
4159
- durationSeconds = durationTicks / 9e4;
4160
- }
4161
- r.readBits(16);
4162
- r.readBits(8);
4163
- r.readBits(8);
4164
- if (outOfNetwork) {
4165
- var marker = _object_spread_props(_object_spread({
4166
- type: "start"
4167
- }, durationSeconds !== void 0 ? {
4168
- durationSeconds: durationSeconds
4169
- } : {}), {
4170
- raw: {
4171
- splice_command_type: 5
4172
- }
4173
- });
4174
- return marker;
4175
- }
4176
- return void 0;
4177
- }
4178
- },
4179
3621
  {
4180
3622
  key: "initializeTracking",
4181
3623
  value: function initializeTracking() {
@@ -4297,35 +3739,35 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4297
3739
  },
4298
3740
  {
4299
3741
  key: "startAdPrefetch",
4300
- value: function startAdPrefetch(marker, fragmentSn) {
3742
+ value: function startAdPrefetch(durationSeconds, fragmentSn) {
4301
3743
  if (this.config.disableAds) return;
4302
3744
  if (this.pendingAdBreak || this.inAdBreak) {
4303
3745
  return;
4304
3746
  }
4305
- this.pendingAdBreak = _object_spread_props(_object_spread({
4306
- marker: marker
4307
- }, fragmentSn !== void 0 ? {
3747
+ this.pendingAdBreak = _object_spread_props(_object_spread({}, durationSeconds !== void 0 ? {
3748
+ durationSeconds: durationSeconds
3749
+ } : {}, fragmentSn !== void 0 ? {
4308
3750
  detectedAtFragmentSn: fragmentSn
4309
3751
  } : {}), {
4310
3752
  isFetching: false,
4311
3753
  fetchStartTime: Date.now()
4312
3754
  });
4313
- void this.runAdPrefetch(marker);
3755
+ void this.runAdPrefetch(durationSeconds);
4314
3756
  if (this.config.debugAdTiming) {
4315
- console.log("[PREFETCH] Ad break marker registered, multi-ad prefetch started");
3757
+ console.log("[PREFETCH] Ad break registered, multi-ad prefetch started");
4316
3758
  }
4317
3759
  }
4318
3760
  },
4319
3761
  {
4320
3762
  key: "runAdPrefetch",
4321
- value: function runAdPrefetch(marker) {
3763
+ value: function runAdPrefetch(durationSeconds) {
4322
3764
  return _async_to_generator(function() {
4323
- var _this, _marker_durationSeconds, _ref, _firstBids_, durSec, context, firstBids, unused, adDurationSec, estimatedCount, firstToken, remaining, results, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, result, token;
3765
+ var _this, _ref, _firstBids_, durSec, context, firstBids, unused, adDurationSec, estimatedCount, firstToken, unused1, remaining, results, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, result, token, unused2, err;
4324
3766
  return _ts_generator(this, function(_state) {
4325
3767
  switch(_state.label){
4326
3768
  case 0:
4327
3769
  _this = this;
4328
- durSec = (_marker_durationSeconds = marker.durationSeconds) !== null && _marker_durationSeconds !== void 0 ? _marker_durationSeconds : 60;
3770
+ durSec = durationSeconds !== null && durationSeconds !== void 0 ? durationSeconds : 60;
4329
3771
  context = {
4330
3772
  breakDurationSec: durSec,
4331
3773
  remainingBreakSec: durSec
@@ -4375,14 +3817,43 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4375
3817
  console.log("[PREFETCH] Ad duration=".concat(adDurationSec, "s, break=").concat(durSec, "s → ").concat(estimatedCount, " ad(s) needed"));
4376
3818
  }
4377
3819
  firstToken = "preload_".concat(Date.now(), "_").concat(Math.random().toString(36).slice(2, 7));
4378
- this.preloadedTokens.push(firstToken);
4379
- void this.adLayer.preloadAd(firstBids, firstToken);
3820
+ _state.label = 5;
3821
+ case 5:
3822
+ _state.trys.push([
3823
+ 5,
3824
+ 7,
3825
+ ,
3826
+ 8
3827
+ ]);
3828
+ return [
3829
+ 4,
3830
+ this.adLayer.preloadAd(firstBids, firstToken)
3831
+ ];
3832
+ case 6:
3833
+ _state.sent();
3834
+ if (!this.inAdBreak) {
3835
+ this.preloadedTokens.push(firstToken);
3836
+ if (this.config.debugAdTiming) {
3837
+ console.log("[PREFETCH] First ad preloaded and queued, token=".concat(firstToken));
3838
+ }
3839
+ }
3840
+ return [
3841
+ 3,
3842
+ 8
3843
+ ];
3844
+ case 7:
3845
+ unused1 = _state.sent();
4380
3846
  if (this.config.debugAdTiming) {
4381
- console.log("[PREFETCH] First ad preloading, token=".concat(firstToken));
3847
+ console.warn("[PREFETCH] First ad preload failed, token=".concat(firstToken));
4382
3848
  }
3849
+ return [
3850
+ 3,
3851
+ 8
3852
+ ];
3853
+ case 8:
4383
3854
  if (!(estimatedCount > 1)) return [
4384
3855
  3,
4385
- 6
3856
+ 19
4386
3857
  ];
4387
3858
  remaining = Array.from({
4388
3859
  length: estimatedCount - 1
@@ -4404,38 +3875,100 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4404
3875
  4,
4405
3876
  Promise.all(remaining)
4406
3877
  ];
4407
- case 5:
3878
+ case 9:
4408
3879
  results = _state.sent();
4409
3880
  _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3881
+ _state.label = 10;
3882
+ case 10:
3883
+ _state.trys.push([
3884
+ 10,
3885
+ 17,
3886
+ 18,
3887
+ 19
3888
+ ]);
3889
+ _iterator = results[Symbol.iterator]();
3890
+ _state.label = 11;
3891
+ case 11:
3892
+ if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
3893
+ 3,
3894
+ 16
3895
+ ];
3896
+ result = _step.value;
3897
+ if (this.inAdBreak) return [
3898
+ 3,
3899
+ 16
3900
+ ];
3901
+ if (!(result.ok && result.value.length > 0)) return [
3902
+ 3,
3903
+ 15
3904
+ ];
3905
+ token = "preload_".concat(Date.now(), "_").concat(Math.random().toString(36).slice(2, 7));
3906
+ _state.label = 12;
3907
+ case 12:
3908
+ _state.trys.push([
3909
+ 12,
3910
+ 14,
3911
+ ,
3912
+ 15
3913
+ ]);
3914
+ return [
3915
+ 4,
3916
+ this.adLayer.preloadAd(result.value, token)
3917
+ ];
3918
+ case 13:
3919
+ _state.sent();
3920
+ if (!this.inAdBreak) {
3921
+ this.preloadedTokens.push(token);
3922
+ if (this.config.debugAdTiming) {
3923
+ console.log("[PREFETCH] Additional ad preloaded and queued, token=".concat(token));
3924
+ }
3925
+ }
3926
+ return [
3927
+ 3,
3928
+ 15
3929
+ ];
3930
+ case 14:
3931
+ unused2 = _state.sent();
3932
+ if (this.config.debugAdTiming) {
3933
+ console.warn("[PREFETCH] Additional ad preload failed, token=".concat(token));
3934
+ }
3935
+ return [
3936
+ 3,
3937
+ 15
3938
+ ];
3939
+ case 15:
3940
+ _iteratorNormalCompletion = true;
3941
+ return [
3942
+ 3,
3943
+ 11
3944
+ ];
3945
+ case 16:
3946
+ return [
3947
+ 3,
3948
+ 19
3949
+ ];
3950
+ case 17:
3951
+ err = _state.sent();
3952
+ _didIteratorError = true;
3953
+ _iteratorError = err;
3954
+ return [
3955
+ 3,
3956
+ 19
3957
+ ];
3958
+ case 18:
4410
3959
  try {
4411
- for(_iterator = results[Symbol.iterator](); !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
4412
- result = _step.value;
4413
- if (this.inAdBreak) break;
4414
- if (result.ok && result.value.length > 0) {
4415
- token = "preload_".concat(Date.now(), "_").concat(Math.random().toString(36).slice(2, 7));
4416
- this.preloadedTokens.push(token);
4417
- void this.adLayer.preloadAd(result.value, token);
4418
- if (this.config.debugAdTiming) {
4419
- console.log("[PREFETCH] Additional ad preloading, token=".concat(token));
4420
- }
4421
- }
3960
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
3961
+ _iterator.return();
4422
3962
  }
4423
- } catch (err) {
4424
- _didIteratorError = true;
4425
- _iteratorError = err;
4426
3963
  } finally{
4427
- try {
4428
- if (!_iteratorNormalCompletion && _iterator.return != null) {
4429
- _iterator.return();
4430
- }
4431
- } finally{
4432
- if (_didIteratorError) {
4433
- throw _iteratorError;
4434
- }
3964
+ if (_didIteratorError) {
3965
+ throw _iteratorError;
4435
3966
  }
4436
3967
  }
4437
- _state.label = 6;
4438
- case 6:
3968
+ return [
3969
+ 7
3970
+ ];
3971
+ case 19:
4439
3972
  if (this.config.debugAdTiming) {
4440
3973
  console.log("[PREFETCH] Pre-fetch complete: ".concat(this.preloadedTokens.length, " ad(s) queued"));
4441
3974
  }
@@ -4600,15 +4133,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4600
4133
  if (this.config.debugAdTiming) {
4601
4134
  console.log('[StormcloudVideoPlayer] Ad insertion segment "'.concat(segmentName, '" found in manifest — starting pre-fetch'));
4602
4135
  }
4603
- var marker = {
4604
- type: "start",
4605
- durationSeconds: 60,
4606
- raw: {
4607
- apiInsertionPoint: this.lastAdInsertionPoint,
4608
- earlyDetection: true
4609
- }
4610
- };
4611
- this.startAdPrefetch(marker, frag === null || frag === void 0 ? void 0 : frag.sn);
4136
+ this.startAdPrefetch(60, frag === null || frag === void 0 ? void 0 : frag.sn);
4612
4137
  return;
4613
4138
  }
4614
4139
  }
@@ -4646,8 +4171,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4646
4171
  {
4647
4172
  key: "fragmentMatchesSegment",
4648
4173
  value: function fragmentMatchesSegment(frag, segmentName) {
4649
- var url = (frag === null || frag === void 0 ? void 0 : frag.url) || (frag === null || frag === void 0 ? void 0 : frag.relurl) || "";
4650
- return url.endsWith(segmentName) || url.includes("/" + segmentName);
4174
+ var _rawUrl_split_;
4175
+ var rawUrl = (frag === null || frag === void 0 ? void 0 : frag.url) || (frag === null || frag === void 0 ? void 0 : frag.relurl) || "";
4176
+ var url = (_rawUrl_split_ = rawUrl.split("?")[0]) !== null && _rawUrl_split_ !== void 0 ? _rawUrl_split_ : "";
4177
+ var name = segmentName.startsWith("/") ? segmentName : "/" + segmentName;
4178
+ return url.endsWith(name) || url.includes(name);
4651
4179
  }
4652
4180
  },
4653
4181
  {
@@ -4984,13 +4512,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4984
4512
  },
4985
4513
  {
4986
4514
  key: "handleAdStart",
4987
- value: function handleAdStart(_marker) {
4515
+ value: function handleAdStart(durationSeconds) {
4988
4516
  return _async_to_generator(function() {
4989
- var _this_savedMutedStateBeforeScte, adBreakDurationMs, mode, state, adBreakToken, adVolume, token, remaining, err;
4517
+ var _this_savedMutedStateBeforeAd, adBreakDurationMs, mode, state, adBreakToken, adVolume, token, remaining, err;
4990
4518
  return _ts_generator(this, function(_state) {
4991
4519
  switch(_state.label){
4992
4520
  case 0:
4993
- adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : void 0;
4521
+ adBreakDurationMs = durationSeconds != null ? durationSeconds * 1e3 : void 0;
4994
4522
  if (this.config.debugAdTiming) {
4995
4523
  mode = this.isLiveStream ? "LIVE" : "VOD";
4996
4524
  console.log("[CONTINUOUS-FETCH] \uD83D\uDCFA ".concat(mode, " MODE: Target duration=").concat(adBreakDurationMs, "ms"));
@@ -5001,13 +4529,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5001
4529
  this.pendingNextAdBids = null;
5002
4530
  this.isShowingPlaceholder = false;
5003
4531
  this.totalAdRequestsInBreak = 0;
5004
- if (this.savedMutedStateBeforeScte == null && !this.video.muted) {
5005
- this.savedMutedStateBeforeScte = {
4532
+ if (this.savedMutedStateBeforeAd == null && !this.video.muted) {
4533
+ this.savedMutedStateBeforeAd = {
5006
4534
  muted: false,
5007
4535
  volume: this.video.volume
5008
4536
  };
5009
4537
  }
5010
- state = (_this_savedMutedStateBeforeScte = this.savedMutedStateBeforeScte) !== null && _this_savedMutedStateBeforeScte !== void 0 ? _this_savedMutedStateBeforeScte : {
4538
+ state = (_this_savedMutedStateBeforeAd = this.savedMutedStateBeforeAd) !== null && _this_savedMutedStateBeforeAd !== void 0 ? _this_savedMutedStateBeforeAd : {
5011
4539
  muted: this.video.muted,
5012
4540
  volume: this.video.volume
5013
4541
  };
@@ -5034,6 +4562,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5034
4562
  if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {
5035
4563
  this.expectedAdBreakDurationMs = adBreakDurationMs;
5036
4564
  }
4565
+ if (this.expectedAdBreakDurationMs != null) {
4566
+ this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
4567
+ }
5037
4568
  this.clearPendingAdBreak();
5038
4569
  adBreakToken = Date.now();
5039
4570
  this.activeAdRequestToken = adBreakToken;
@@ -5532,49 +5063,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5532
5063
  this.handleAdPodComplete();
5533
5064
  }
5534
5065
  },
5535
- {
5536
- key: "scheduleAdStartIn",
5537
- value: function scheduleAdStartIn(delayMs) {
5538
- var _this = this;
5539
- this.clearAdStartTimer();
5540
- var ms = Math.max(0, Math.floor(delayMs));
5541
- if (ms === 0) {
5542
- this.handleAdStart({
5543
- type: "start"
5544
- }).catch(function() {});
5545
- return;
5546
- }
5547
- this.adStartTimerId = window.setTimeout(function() {
5548
- _this.handleAdStart({
5549
- type: "start"
5550
- }).catch(function() {});
5551
- }, ms);
5552
- }
5553
- },
5554
- {
5555
- key: "clearAdStartTimer",
5556
- value: function clearAdStartTimer() {
5557
- if (this.adStartTimerId != null) {
5558
- clearTimeout(this.adStartTimerId);
5559
- this.adStartTimerId = void 0;
5560
- }
5561
- }
5562
- },
5563
- {
5564
- key: "updatePtsDrift",
5565
- value: function updatePtsDrift(ptsSecondsSample) {
5566
- var sampleMs = (this.video.currentTime - ptsSecondsSample) * 1e3;
5567
- if (!Number.isFinite(sampleMs) || Math.abs(sampleMs) > 6e4) return;
5568
- var alpha = 0.1;
5569
- this.ptsDriftEmaMs = this.ptsDriftEmaMs * (1 - alpha) + sampleMs * alpha;
5570
- }
5571
- },
5572
5066
  {
5573
5067
  key: "handleAdPodComplete",
5574
5068
  value: function handleAdPodComplete() {
5575
5069
  var _this = this;
5576
5070
  var _ref, _ref1;
5577
- var _this_savedMutedStateBeforeScte, _this_savedMutedStateBeforeScte1;
5071
+ var _this_savedMutedStateBeforeAd, _this_savedMutedStateBeforeAd1;
5578
5072
  if (this.config.debugAdTiming) {
5579
5073
  console.log("[StormcloudVideoPlayer] \uD83C\uDFC1 Ad pod complete - cleaning up");
5580
5074
  }
@@ -5596,7 +5090,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5596
5090
  this.inAdBreak = false;
5597
5091
  this.expectedAdBreakDurationMs = void 0;
5598
5092
  this.currentAdBreakStartWallClockMs = void 0;
5599
- this.clearAdStartTimer();
5600
5093
  this.clearAdStopTimer();
5601
5094
  this.adPodQueue = [];
5602
5095
  this.showAds = false;
@@ -5604,8 +5097,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5604
5097
  this.totalAdsInBreak = 0;
5605
5098
  this.totalAdRequestsInBreak = 0;
5606
5099
  this.consecutiveFailures = 0;
5607
- var restoredMuted = (_ref = (_this_savedMutedStateBeforeScte = this.savedMutedStateBeforeScte) === null || _this_savedMutedStateBeforeScte === void 0 ? void 0 : _this_savedMutedStateBeforeScte.muted) !== null && _ref !== void 0 ? _ref : this.adLayer.getOriginalMutedState();
5608
- var restoredVolume = (_ref1 = (_this_savedMutedStateBeforeScte1 = this.savedMutedStateBeforeScte) === null || _this_savedMutedStateBeforeScte1 === void 0 ? void 0 : _this_savedMutedStateBeforeScte1.volume) !== null && _ref1 !== void 0 ? _ref1 : this.adLayer.getOriginalVolume();
5100
+ var restoredMuted = (_ref = (_this_savedMutedStateBeforeAd = this.savedMutedStateBeforeAd) === null || _this_savedMutedStateBeforeAd === void 0 ? void 0 : _this_savedMutedStateBeforeAd.muted) !== null && _ref !== void 0 ? _ref : this.adLayer.getOriginalMutedState();
5101
+ var restoredVolume = (_ref1 = (_this_savedMutedStateBeforeAd1 = this.savedMutedStateBeforeAd) === null || _this_savedMutedStateBeforeAd1 === void 0 ? void 0 : _this_savedMutedStateBeforeAd1.volume) !== null && _ref1 !== void 0 ? _ref1 : this.adLayer.getOriginalVolume();
5609
5102
  this.adLayer.updateOriginalMutedState(restoredMuted, restoredVolume);
5610
5103
  this.adLayer.stop().catch(function() {});
5611
5104
  if (this.video.muted !== restoredMuted) {
@@ -5714,7 +5207,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5714
5207
  }, delay);
5715
5208
  });
5716
5209
  }
5717
- this.savedMutedStateBeforeScte = null;
5210
+ this.savedMutedStateBeforeAd = null;
5718
5211
  }
5719
5212
  },
5720
5213
  {
@@ -5864,19 +5357,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5864
5357
  return Math.max(0, this.expectedAdBreakDurationMs - elapsed);
5865
5358
  }
5866
5359
  },
5867
- {
5868
- key: "pushScteMarker",
5869
- value: function pushScteMarker(marker) {
5870
- if (!this.config.debugAdTiming) return;
5871
- this.scteMarkerHistory.push({
5872
- timestampMs: Date.now(),
5873
- marker: marker
5874
- });
5875
- if (this.scteMarkerHistory.length > DEBUG_HISTORY_LIMIT) {
5876
- this.scteMarkerHistory = this.scteMarkerHistory.slice(-DEBUG_HISTORY_LIMIT);
5877
- }
5878
- }
5879
- },
5880
5360
  {
5881
5361
  key: "pushDebugLog",
5882
5362
  value: function pushDebugLog(level, category, message, details) {
@@ -5894,23 +5374,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5894
5374
  }
5895
5375
  }
5896
5376
  },
5897
- {
5898
- key: "getRecentScteMarkers",
5899
- value: function getRecentScteMarkers() {
5900
- return this.scteMarkerHistory.map(function(entry) {
5901
- return _object_spread({
5902
- timestampMs: entry.timestampMs,
5903
- type: entry.marker.type
5904
- }, entry.marker.ptsSeconds !== void 0 ? {
5905
- ptsSeconds: entry.marker.ptsSeconds
5906
- } : {}, entry.marker.durationSeconds !== void 0 ? {
5907
- durationSeconds: entry.marker.durationSeconds
5908
- } : {}, entry.marker.raw !== void 0 ? {
5909
- raw: entry.marker.raw
5910
- } : {});
5911
- });
5912
- }
5913
- },
5914
5377
  {
5915
5378
  key: "pushAdInsertionDebug",
5916
5379
  value: function pushAdInsertionDebug(event, segmentName, opts) {
@@ -6207,7 +5670,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6207
5670
  this.clearAdInsertionOffsetTimer();
6208
5671
  this.stopContinuousFetching();
6209
5672
  this.stopFillerBreakTimer();
6210
- this.clearAdStartTimer();
6211
5673
  this.clearAdStopTimer();
6212
5674
  this.clearAdFailsafeTimer();
6213
5675
  this.clearAdRequestWatchdog();
@@ -6235,7 +5697,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6235
5697
  (_this_adLayer = this.adLayer) === null || _this_adLayer === void 0 ? void 0 : _this_adLayer.destroy();
6236
5698
  this.consecutiveFailures = 0;
6237
5699
  this.debugLogEntries = [];
6238
- this.scteMarkerHistory = [];
6239
5700
  this.adInsertionDebugHistory = [];
6240
5701
  }
6241
5702
  }
@@ -7712,6 +7173,11 @@ var StormcloudVideoPlayerComponent = import_react2.default.memo(function(props)
7712
7173
  label: "API",
7713
7174
  color: "#60a5fa"
7714
7175
  };
7176
+ case "scte35_inserted":
7177
+ return {
7178
+ label: "SCTE-35",
7179
+ color: "#f43f5e"
7180
+ };
7715
7181
  case "segment_found":
7716
7182
  return {
7717
7183
  label: "FOUND",
@@ -7882,6 +7348,7 @@ var StormcloudVideoPlayerComponent = import_react2.default.memo(function(props)
7882
7348
  if (minSegmentsBeforePlay !== void 0) cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;
7883
7349
  if (disableAds !== void 0) cfg.disableAds = disableAds;
7884
7350
  cfg.disableFiller = disableFiller !== null && disableFiller !== void 0 ? disableFiller : true;
7351
+ if (swirlProjectId !== void 0) cfg.projectId = String(swirlProjectId);
7885
7352
  var player = new StormcloudVideoPlayer(cfg);
7886
7353
  playerRef.current = player;
7887
7354
  player.load().then(function() {
@@ -8755,9 +8222,13 @@ var StormcloudVideoPlayerComponent = import_react2.default.memo(function(props)
8755
8222
  overflowX: "hidden",
8756
8223
  height: "calc(100% - 46px)",
8757
8224
  display: "grid",
8758
- gap: "12px"
8225
+ gap: "12px",
8226
+ minWidth: 0
8759
8227
  },
8760
8228
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
8229
+ style: {
8230
+ minWidth: 0
8231
+ },
8761
8232
  children: [
8762
8233
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
8763
8234
  style: {
@@ -8773,7 +8244,8 @@ var StormcloudVideoPlayerComponent = import_react2.default.memo(function(props)
8773
8244
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
8774
8245
  style: {
8775
8246
  display: "grid",
8776
- gap: "6px"
8247
+ gap: "6px",
8248
+ minWidth: 0
8777
8249
  },
8778
8250
  children: debugMarkers.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
8779
8251
  style: {
@@ -8783,53 +8255,129 @@ var StormcloudVideoPlayerComponent = import_react2.default.memo(function(props)
8783
8255
  children: "No ad insertion events yet."
8784
8256
  }) : debugMarkers.map(function(entry, idx) {
8785
8257
  var evt = formatAdInsertionEvent(entry.event);
8258
+ var fileName = entry.segmentName ? entry.segmentName.split("/").pop() || entry.segmentName : "";
8786
8259
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
8787
8260
  style: {
8788
- display: "grid",
8789
- gridTemplateColumns: "56px 54px 1fr",
8790
- gap: "8px",
8791
- alignItems: "center",
8261
+ minWidth: 0,
8792
8262
  fontFamily: "'SF Mono', 'Cascadia Code', monospace",
8793
8263
  fontSize: "11px",
8794
8264
  background: "rgba(255,255,255,0.05)",
8795
8265
  border: "1px solid rgba(255,255,255,0.08)",
8796
8266
  borderRadius: "8px",
8797
- padding: "6px 8px"
8267
+ padding: "6px 8px",
8268
+ display: "flex",
8269
+ flexDirection: "column",
8270
+ gap: "4px"
8798
8271
  },
8799
8272
  children: [
8800
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {
8273
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
8801
8274
  style: {
8802
- color: "rgba(255,255,255,0.68)"
8275
+ display: "grid",
8276
+ gridTemplateColumns: "56px 54px minmax(0, 1fr) 20px",
8277
+ gap: "6px",
8278
+ alignItems: "center",
8279
+ minWidth: 0
8803
8280
  },
8804
- children: formatDebugClock(entry.timestampMs)
8281
+ children: [
8282
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {
8283
+ style: {
8284
+ color: "rgba(255,255,255,0.68)"
8285
+ },
8286
+ children: formatDebugClock(entry.timestampMs)
8287
+ }),
8288
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {
8289
+ style: {
8290
+ fontWeight: 700,
8291
+ color: evt.color,
8292
+ fontSize: "10px"
8293
+ },
8294
+ children: evt.label
8295
+ }),
8296
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {
8297
+ style: {
8298
+ color: "rgba(255,255,255,0.88)",
8299
+ overflow: "hidden",
8300
+ textOverflow: "ellipsis",
8301
+ whiteSpace: "nowrap",
8302
+ minWidth: 0
8303
+ },
8304
+ title: entry.segmentName,
8305
+ children: fileName
8306
+ }),
8307
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", {
8308
+ onClick: function onClick() {
8309
+ return navigator.clipboard.writeText(entry.segmentName);
8310
+ },
8311
+ title: entry.segmentName,
8312
+ style: {
8313
+ background: "none",
8314
+ border: "none",
8315
+ cursor: "pointer",
8316
+ padding: "2px",
8317
+ color: "rgba(255,255,255,0.45)",
8318
+ display: "flex",
8319
+ alignItems: "center",
8320
+ justifyContent: "center",
8321
+ borderRadius: "4px",
8322
+ flexShrink: 0
8323
+ },
8324
+ onMouseEnter: function onMouseEnter(e) {
8325
+ return e.currentTarget.style.color = "rgba(255,255,255,0.9)";
8326
+ },
8327
+ onMouseLeave: function onMouseLeave(e) {
8328
+ return e.currentTarget.style.color = "rgba(255,255,255,0.45)";
8329
+ },
8330
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_fa.FaCopy, {
8331
+ size: 10
8332
+ })
8333
+ })
8334
+ ]
8805
8335
  }),
8806
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {
8336
+ (entry.offsetSeconds != null || entry.detail || entry.updatedAt) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
8807
8337
  style: {
8808
- fontWeight: 700,
8809
- color: evt.color,
8338
+ display: "flex",
8339
+ flexWrap: "wrap",
8340
+ gap: "6px",
8341
+ paddingLeft: "0px",
8810
8342
  fontSize: "10px"
8811
8343
  },
8812
- children: evt.label
8813
- }),
8814
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {
8815
- style: {
8816
- color: "rgba(255,255,255,0.88)"
8817
- },
8818
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", {
8819
- style: {
8820
- display: "inline-block",
8821
- maxWidth: "100%",
8822
- verticalAlign: "bottom",
8823
- overflow: "hidden",
8824
- textOverflow: "ellipsis",
8825
- whiteSpace: "nowrap"
8826
- },
8827
- children: [
8828
- entry.segmentName,
8829
- entry.offsetSeconds != null ? " +".concat(entry.offsetSeconds, "s") : "",
8830
- entry.detail ? " (".concat(entry.detail, ")") : ""
8831
- ]
8832
- })
8344
+ children: [
8345
+ entry.offsetSeconds != null && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", {
8346
+ style: {
8347
+ color: "rgba(255,255,255,0.55)",
8348
+ background: "rgba(255,255,255,0.06)",
8349
+ borderRadius: "4px",
8350
+ padding: "1px 5px"
8351
+ },
8352
+ children: [
8353
+ "+",
8354
+ entry.offsetSeconds.toFixed(2),
8355
+ "s"
8356
+ ]
8357
+ }),
8358
+ entry.detail && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {
8359
+ style: {
8360
+ color: "rgba(255,255,255,0.55)",
8361
+ background: "rgba(255,255,255,0.06)",
8362
+ borderRadius: "4px",
8363
+ padding: "1px 5px",
8364
+ overflow: "hidden",
8365
+ textOverflow: "ellipsis",
8366
+ whiteSpace: "nowrap",
8367
+ maxWidth: "100%"
8368
+ },
8369
+ children: entry.detail
8370
+ }),
8371
+ entry.updatedAt && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {
8372
+ style: {
8373
+ color: "rgba(255,255,255,0.38)",
8374
+ background: "rgba(255,255,255,0.04)",
8375
+ borderRadius: "4px",
8376
+ padding: "1px 5px"
8377
+ },
8378
+ children: formatAiRelativeTime(entry.updatedAt)
8379
+ })
8380
+ ]
8833
8381
  })
8834
8382
  ]
8835
8383
  }, "".concat(entry.timestampMs, "-").concat(idx));