stormcloud-video-player 0.7.11 → 0.7.13

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
@@ -4365,6 +3807,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4365
3807
  if (this.config.debugAdTiming) {
4366
3808
  console.log("[PREFETCH] First VAST request returned no ad, aborting prefetch");
4367
3809
  }
3810
+ this.clearPendingAdBreak();
4368
3811
  return [
4369
3812
  2
4370
3813
  ];
@@ -4375,14 +3818,43 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4375
3818
  console.log("[PREFETCH] Ad duration=".concat(adDurationSec, "s, break=").concat(durSec, "s → ").concat(estimatedCount, " ad(s) needed"));
4376
3819
  }
4377
3820
  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);
3821
+ _state.label = 5;
3822
+ case 5:
3823
+ _state.trys.push([
3824
+ 5,
3825
+ 7,
3826
+ ,
3827
+ 8
3828
+ ]);
3829
+ return [
3830
+ 4,
3831
+ this.adLayer.preloadAd(firstBids, firstToken)
3832
+ ];
3833
+ case 6:
3834
+ _state.sent();
3835
+ if (!this.inAdBreak) {
3836
+ this.preloadedTokens.push(firstToken);
3837
+ if (this.config.debugAdTiming) {
3838
+ console.log("[PREFETCH] First ad preloaded and queued, token=".concat(firstToken));
3839
+ }
3840
+ }
3841
+ return [
3842
+ 3,
3843
+ 8
3844
+ ];
3845
+ case 7:
3846
+ unused1 = _state.sent();
4380
3847
  if (this.config.debugAdTiming) {
4381
- console.log("[PREFETCH] First ad preloading, token=".concat(firstToken));
3848
+ console.warn("[PREFETCH] First ad preload failed, token=".concat(firstToken));
4382
3849
  }
3850
+ return [
3851
+ 3,
3852
+ 8
3853
+ ];
3854
+ case 8:
4383
3855
  if (!(estimatedCount > 1)) return [
4384
3856
  3,
4385
- 6
3857
+ 19
4386
3858
  ];
4387
3859
  remaining = Array.from({
4388
3860
  length: estimatedCount - 1
@@ -4404,38 +3876,100 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4404
3876
  4,
4405
3877
  Promise.all(remaining)
4406
3878
  ];
4407
- case 5:
3879
+ case 9:
4408
3880
  results = _state.sent();
4409
3881
  _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3882
+ _state.label = 10;
3883
+ case 10:
3884
+ _state.trys.push([
3885
+ 10,
3886
+ 17,
3887
+ 18,
3888
+ 19
3889
+ ]);
3890
+ _iterator = results[Symbol.iterator]();
3891
+ _state.label = 11;
3892
+ case 11:
3893
+ if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
3894
+ 3,
3895
+ 16
3896
+ ];
3897
+ result = _step.value;
3898
+ if (this.inAdBreak) return [
3899
+ 3,
3900
+ 16
3901
+ ];
3902
+ if (!(result.ok && result.value.length > 0)) return [
3903
+ 3,
3904
+ 15
3905
+ ];
3906
+ token = "preload_".concat(Date.now(), "_").concat(Math.random().toString(36).slice(2, 7));
3907
+ _state.label = 12;
3908
+ case 12:
3909
+ _state.trys.push([
3910
+ 12,
3911
+ 14,
3912
+ ,
3913
+ 15
3914
+ ]);
3915
+ return [
3916
+ 4,
3917
+ this.adLayer.preloadAd(result.value, token)
3918
+ ];
3919
+ case 13:
3920
+ _state.sent();
3921
+ if (!this.inAdBreak) {
3922
+ this.preloadedTokens.push(token);
3923
+ if (this.config.debugAdTiming) {
3924
+ console.log("[PREFETCH] Additional ad preloaded and queued, token=".concat(token));
3925
+ }
3926
+ }
3927
+ return [
3928
+ 3,
3929
+ 15
3930
+ ];
3931
+ case 14:
3932
+ unused2 = _state.sent();
3933
+ if (this.config.debugAdTiming) {
3934
+ console.warn("[PREFETCH] Additional ad preload failed, token=".concat(token));
3935
+ }
3936
+ return [
3937
+ 3,
3938
+ 15
3939
+ ];
3940
+ case 15:
3941
+ _iteratorNormalCompletion = true;
3942
+ return [
3943
+ 3,
3944
+ 11
3945
+ ];
3946
+ case 16:
3947
+ return [
3948
+ 3,
3949
+ 19
3950
+ ];
3951
+ case 17:
3952
+ err = _state.sent();
3953
+ _didIteratorError = true;
3954
+ _iteratorError = err;
3955
+ return [
3956
+ 3,
3957
+ 19
3958
+ ];
3959
+ case 18:
4410
3960
  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
- }
3961
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
3962
+ _iterator.return();
4422
3963
  }
4423
- } catch (err) {
4424
- _didIteratorError = true;
4425
- _iteratorError = err;
4426
3964
  } finally{
4427
- try {
4428
- if (!_iteratorNormalCompletion && _iterator.return != null) {
4429
- _iterator.return();
4430
- }
4431
- } finally{
4432
- if (_didIteratorError) {
4433
- throw _iteratorError;
4434
- }
3965
+ if (_didIteratorError) {
3966
+ throw _iteratorError;
4435
3967
  }
4436
3968
  }
4437
- _state.label = 6;
4438
- case 6:
3969
+ return [
3970
+ 7
3971
+ ];
3972
+ case 19:
4439
3973
  if (this.config.debugAdTiming) {
4440
3974
  console.log("[PREFETCH] Pre-fetch complete: ".concat(this.preloadedTokens.length, " ad(s) queued"));
4441
3975
  }
@@ -4507,7 +4041,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4507
4041
  key: "fetchAdInsertionPoint",
4508
4042
  value: function fetchAdInsertionPoint() {
4509
4043
  return _async_to_generator(function() {
4510
- var _this_lastAdInsertionPoint, resp, data, isNew, unused;
4044
+ var _this_lastAdInsertionPoint, _this_lastAdInsertionPoint1, resp, data, prevSegment, isNew, segmentChanged, unused;
4511
4045
  return _ts_generator(this, function(_state) {
4512
4046
  switch(_state.label){
4513
4047
  case 0:
@@ -4537,7 +4071,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4537
4071
  ];
4538
4072
  case 3:
4539
4073
  data = _state.sent();
4540
- isNew = data.updated_at !== ((_this_lastAdInsertionPoint = this.lastAdInsertionPoint) === null || _this_lastAdInsertionPoint === void 0 ? void 0 : _this_lastAdInsertionPoint.updated_at);
4074
+ prevSegment = (_this_lastAdInsertionPoint = this.lastAdInsertionPoint) === null || _this_lastAdInsertionPoint === void 0 ? void 0 : _this_lastAdInsertionPoint.segment_ts_name;
4075
+ isNew = data.updated_at !== ((_this_lastAdInsertionPoint1 = this.lastAdInsertionPoint) === null || _this_lastAdInsertionPoint1 === void 0 ? void 0 : _this_lastAdInsertionPoint1.updated_at);
4076
+ segmentChanged = prevSegment !== data.segment_ts_name;
4541
4077
  this.lastAdInsertionPoint = data;
4542
4078
  if (isNew) {
4543
4079
  this.pushAdInsertionDebug("api_response", data.segment_ts_name, {
@@ -4545,6 +4081,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4545
4081
  updatedAt: data.updated_at,
4546
4082
  detail: "project=".concat(data.project_id)
4547
4083
  });
4084
+ if (segmentChanged && (this.pendingAdBreak || this.adInsertionOffsetTimerId != null)) {
4085
+ this.clearAdInsertionOffsetTimer();
4086
+ this.clearPendingAdBreak();
4087
+ this.cancelAndClearPreloadedTokens();
4088
+ if (this.config.debugAdTiming) {
4089
+ console.log("[StormcloudVideoPlayer] Insertion segment changed (".concat(prevSegment, " → ").concat(data.segment_ts_name, "), stale pending state cleared"));
4090
+ }
4091
+ }
4092
+ this.checkAdInsertionInManifest();
4548
4093
  }
4549
4094
  if (this.config.debugAdTiming) {
4550
4095
  console.log("[StormcloudVideoPlayer] Ad insertion point API response:", data);
@@ -4574,6 +4119,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4574
4119
  {
4575
4120
  key: "checkAdInsertionInManifest",
4576
4121
  value: function checkAdInsertionInManifest() {
4122
+ var _this = this;
4577
4123
  var _this_hls;
4578
4124
  if (!this.lastAdInsertionPoint) return;
4579
4125
  if (this.inAdBreak || this.pendingAdBreak) return;
@@ -4593,22 +4139,42 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4593
4139
  for(var _iterator1 = fragments[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
4594
4140
  var frag = _step1.value;
4595
4141
  if (this.fragmentMatchesSegment(frag, segmentName)) {
4596
- var _ref;
4142
+ var _frag_start, _frag_duration, _ref;
4143
+ var currentTime = this.video.currentTime;
4144
+ var fragStart = (_frag_start = frag.start) !== null && _frag_start !== void 0 ? _frag_start : 0;
4145
+ var fragDuration = (_frag_duration = frag.duration) !== null && _frag_duration !== void 0 ? _frag_duration : 0;
4146
+ var isCurrentlyPlaying = fragDuration > 0 && currentTime >= fragStart && currentTime < fragStart + fragDuration;
4597
4147
  this.pushAdInsertionDebug("segment_found", segmentName, {
4598
- detail: "sn=".concat((_ref = frag === null || frag === void 0 ? void 0 : frag.sn) !== null && _ref !== void 0 ? _ref : "?")
4148
+ detail: "sn=".concat((_ref = frag === null || frag === void 0 ? void 0 : frag.sn) !== null && _ref !== void 0 ? _ref : "?", " ").concat(isCurrentlyPlaying ? "(playing)" : "(future)")
4599
4149
  });
4600
4150
  if (this.config.debugAdTiming) {
4601
- console.log('[StormcloudVideoPlayer] Ad insertion segment "'.concat(segmentName, '" found in manifest — starting pre-fetch'));
4151
+ console.log('[StormcloudVideoPlayer] Ad insertion segment "'.concat(segmentName, '" found in manifest — ') + (isCurrentlyPlaying ? "currently playing, scheduling directly" : "starting pre-fetch"));
4152
+ }
4153
+ this.startAdPrefetch(60, frag === null || frag === void 0 ? void 0 : frag.sn);
4154
+ if (isCurrentlyPlaying && !this.inAdBreak) {
4155
+ var _this_lastAdInsertionPoint_offset_seconds, _ref1;
4156
+ this.processedAdInsertionUpdatedAt = this.lastAdInsertionPoint.updated_at;
4157
+ var rawOffsetMs = ((_this_lastAdInsertionPoint_offset_seconds = this.lastAdInsertionPoint.offset_seconds) !== null && _this_lastAdInsertionPoint_offset_seconds !== void 0 ? _this_lastAdInsertionPoint_offset_seconds : 0) * 1e3;
4158
+ var elapsedInFragMs = (currentTime - fragStart) * 1e3;
4159
+ var remainingOffsetMs = Math.max(0, rawOffsetMs - elapsedInFragMs);
4160
+ this.pushAdInsertionDebug("segment_playing", segmentName, {
4161
+ offsetSeconds: this.lastAdInsertionPoint.offset_seconds,
4162
+ detail: "sn=".concat((_ref1 = frag === null || frag === void 0 ? void 0 : frag.sn) !== null && _ref1 !== void 0 ? _ref1 : "?", " (caught in manifest check)")
4163
+ });
4164
+ this.pushAdInsertionDebug("ad_scheduled", segmentName, {
4165
+ offsetSeconds: this.lastAdInsertionPoint.offset_seconds,
4166
+ detail: "in ".concat(remainingOffsetMs, "ms (adjusted for elapsed ").concat(Math.round(elapsedInFragMs), "ms)")
4167
+ });
4168
+ this.clearAdInsertionOffsetTimer();
4169
+ this.adInsertionOffsetTimerId = window.setTimeout(function() {
4170
+ _this.adInsertionOffsetTimerId = void 0;
4171
+ if (_this.inAdBreak) return;
4172
+ _this.pushAdInsertionDebug("ad_triggered", segmentName, {
4173
+ detail: "ad break started (60s, via manifest-check path)"
4174
+ });
4175
+ void _this.handleAdStart(60);
4176
+ }, remainingOffsetMs);
4602
4177
  }
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);
4612
4178
  return;
4613
4179
  }
4614
4180
  }
@@ -4646,8 +4212,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4646
4212
  {
4647
4213
  key: "fragmentMatchesSegment",
4648
4214
  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);
4215
+ var _rawUrl_split_;
4216
+ var rawUrl = (frag === null || frag === void 0 ? void 0 : frag.url) || (frag === null || frag === void 0 ? void 0 : frag.relurl) || "";
4217
+ var url = (_rawUrl_split_ = rawUrl.split("?")[0]) !== null && _rawUrl_split_ !== void 0 ? _rawUrl_split_ : "";
4218
+ var name = segmentName.startsWith("/") ? segmentName : "/" + segmentName;
4219
+ return url.endsWith(name) || url.includes(name);
4651
4220
  }
4652
4221
  },
4653
4222
  {
@@ -4984,13 +4553,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4984
4553
  },
4985
4554
  {
4986
4555
  key: "handleAdStart",
4987
- value: function handleAdStart(_marker) {
4556
+ value: function handleAdStart(durationSeconds) {
4988
4557
  return _async_to_generator(function() {
4989
- var _this_savedMutedStateBeforeScte, adBreakDurationMs, mode, state, adBreakToken, adVolume, token, remaining, err;
4558
+ var _this_savedMutedStateBeforeAd, adBreakDurationMs, mode, state, adBreakToken, adVolume, token, remaining, err;
4990
4559
  return _ts_generator(this, function(_state) {
4991
4560
  switch(_state.label){
4992
4561
  case 0:
4993
- adBreakDurationMs = _marker.durationSeconds != null ? _marker.durationSeconds * 1e3 : void 0;
4562
+ adBreakDurationMs = durationSeconds != null ? durationSeconds * 1e3 : void 0;
4994
4563
  if (this.config.debugAdTiming) {
4995
4564
  mode = this.isLiveStream ? "LIVE" : "VOD";
4996
4565
  console.log("[CONTINUOUS-FETCH] \uD83D\uDCFA ".concat(mode, " MODE: Target duration=").concat(adBreakDurationMs, "ms"));
@@ -5001,13 +4570,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5001
4570
  this.pendingNextAdBids = null;
5002
4571
  this.isShowingPlaceholder = false;
5003
4572
  this.totalAdRequestsInBreak = 0;
5004
- if (this.savedMutedStateBeforeScte == null && !this.video.muted) {
5005
- this.savedMutedStateBeforeScte = {
4573
+ if (this.savedMutedStateBeforeAd == null && !this.video.muted) {
4574
+ this.savedMutedStateBeforeAd = {
5006
4575
  muted: false,
5007
4576
  volume: this.video.volume
5008
4577
  };
5009
4578
  }
5010
- state = (_this_savedMutedStateBeforeScte = this.savedMutedStateBeforeScte) !== null && _this_savedMutedStateBeforeScte !== void 0 ? _this_savedMutedStateBeforeScte : {
4579
+ state = (_this_savedMutedStateBeforeAd = this.savedMutedStateBeforeAd) !== null && _this_savedMutedStateBeforeAd !== void 0 ? _this_savedMutedStateBeforeAd : {
5011
4580
  muted: this.video.muted,
5012
4581
  volume: this.video.volume
5013
4582
  };
@@ -5034,6 +4603,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5034
4603
  if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {
5035
4604
  this.expectedAdBreakDurationMs = adBreakDurationMs;
5036
4605
  }
4606
+ if (this.expectedAdBreakDurationMs != null) {
4607
+ this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
4608
+ }
5037
4609
  this.clearPendingAdBreak();
5038
4610
  adBreakToken = Date.now();
5039
4611
  this.activeAdRequestToken = adBreakToken;
@@ -5532,49 +5104,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5532
5104
  this.handleAdPodComplete();
5533
5105
  }
5534
5106
  },
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
5107
  {
5573
5108
  key: "handleAdPodComplete",
5574
5109
  value: function handleAdPodComplete() {
5575
5110
  var _this = this;
5576
5111
  var _ref, _ref1;
5577
- var _this_savedMutedStateBeforeScte, _this_savedMutedStateBeforeScte1;
5112
+ var _this_savedMutedStateBeforeAd, _this_savedMutedStateBeforeAd1;
5578
5113
  if (this.config.debugAdTiming) {
5579
5114
  console.log("[StormcloudVideoPlayer] \uD83C\uDFC1 Ad pod complete - cleaning up");
5580
5115
  }
@@ -5596,7 +5131,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5596
5131
  this.inAdBreak = false;
5597
5132
  this.expectedAdBreakDurationMs = void 0;
5598
5133
  this.currentAdBreakStartWallClockMs = void 0;
5599
- this.clearAdStartTimer();
5600
5134
  this.clearAdStopTimer();
5601
5135
  this.adPodQueue = [];
5602
5136
  this.showAds = false;
@@ -5604,8 +5138,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5604
5138
  this.totalAdsInBreak = 0;
5605
5139
  this.totalAdRequestsInBreak = 0;
5606
5140
  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();
5141
+ 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();
5142
+ 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
5143
  this.adLayer.updateOriginalMutedState(restoredMuted, restoredVolume);
5610
5144
  this.adLayer.stop().catch(function() {});
5611
5145
  if (this.video.muted !== restoredMuted) {
@@ -5714,7 +5248,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5714
5248
  }, delay);
5715
5249
  });
5716
5250
  }
5717
- this.savedMutedStateBeforeScte = null;
5251
+ this.savedMutedStateBeforeAd = null;
5718
5252
  }
5719
5253
  },
5720
5254
  {
@@ -5864,19 +5398,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5864
5398
  return Math.max(0, this.expectedAdBreakDurationMs - elapsed);
5865
5399
  }
5866
5400
  },
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
5401
  {
5881
5402
  key: "pushDebugLog",
5882
5403
  value: function pushDebugLog(level, category, message, details) {
@@ -5894,23 +5415,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5894
5415
  }
5895
5416
  }
5896
5417
  },
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
5418
  {
5915
5419
  key: "pushAdInsertionDebug",
5916
5420
  value: function pushAdInsertionDebug(event, segmentName, opts) {
@@ -6207,7 +5711,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6207
5711
  this.clearAdInsertionOffsetTimer();
6208
5712
  this.stopContinuousFetching();
6209
5713
  this.stopFillerBreakTimer();
6210
- this.clearAdStartTimer();
6211
5714
  this.clearAdStopTimer();
6212
5715
  this.clearAdFailsafeTimer();
6213
5716
  this.clearAdRequestWatchdog();
@@ -6235,7 +5738,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6235
5738
  (_this_adLayer = this.adLayer) === null || _this_adLayer === void 0 ? void 0 : _this_adLayer.destroy();
6236
5739
  this.consecutiveFailures = 0;
6237
5740
  this.debugLogEntries = [];
6238
- this.scteMarkerHistory = [];
6239
5741
  this.adInsertionDebugHistory = [];
6240
5742
  }
6241
5743
  }
@@ -7712,6 +7214,11 @@ var StormcloudVideoPlayerComponent = import_react2.default.memo(function(props)
7712
7214
  label: "API",
7713
7215
  color: "#60a5fa"
7714
7216
  };
7217
+ case "scte35_inserted":
7218
+ return {
7219
+ label: "SCTE-35",
7220
+ color: "#f43f5e"
7221
+ };
7715
7222
  case "segment_found":
7716
7223
  return {
7717
7224
  label: "FOUND",
@@ -7882,6 +7389,7 @@ var StormcloudVideoPlayerComponent = import_react2.default.memo(function(props)
7882
7389
  if (minSegmentsBeforePlay !== void 0) cfg.minSegmentsBeforePlay = minSegmentsBeforePlay;
7883
7390
  if (disableAds !== void 0) cfg.disableAds = disableAds;
7884
7391
  cfg.disableFiller = disableFiller !== null && disableFiller !== void 0 ? disableFiller : true;
7392
+ if (swirlProjectId !== void 0) cfg.projectId = String(swirlProjectId);
7885
7393
  var player = new StormcloudVideoPlayer(cfg);
7886
7394
  playerRef.current = player;
7887
7395
  player.load().then(function() {
@@ -8755,9 +8263,13 @@ var StormcloudVideoPlayerComponent = import_react2.default.memo(function(props)
8755
8263
  overflowX: "hidden",
8756
8264
  height: "calc(100% - 46px)",
8757
8265
  display: "grid",
8758
- gap: "12px"
8266
+ gap: "12px",
8267
+ minWidth: 0
8759
8268
  },
8760
8269
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
8270
+ style: {
8271
+ minWidth: 0
8272
+ },
8761
8273
  children: [
8762
8274
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
8763
8275
  style: {
@@ -8773,7 +8285,8 @@ var StormcloudVideoPlayerComponent = import_react2.default.memo(function(props)
8773
8285
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
8774
8286
  style: {
8775
8287
  display: "grid",
8776
- gap: "6px"
8288
+ gap: "6px",
8289
+ minWidth: 0
8777
8290
  },
8778
8291
  children: debugMarkers.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", {
8779
8292
  style: {
@@ -8783,53 +8296,129 @@ var StormcloudVideoPlayerComponent = import_react2.default.memo(function(props)
8783
8296
  children: "No ad insertion events yet."
8784
8297
  }) : debugMarkers.map(function(entry, idx) {
8785
8298
  var evt = formatAdInsertionEvent(entry.event);
8299
+ var fileName = entry.segmentName ? entry.segmentName.split("/").pop() || entry.segmentName : "";
8786
8300
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
8787
8301
  style: {
8788
- display: "grid",
8789
- gridTemplateColumns: "56px 54px 1fr",
8790
- gap: "8px",
8791
- alignItems: "center",
8302
+ minWidth: 0,
8792
8303
  fontFamily: "'SF Mono', 'Cascadia Code', monospace",
8793
8304
  fontSize: "11px",
8794
8305
  background: "rgba(255,255,255,0.05)",
8795
8306
  border: "1px solid rgba(255,255,255,0.08)",
8796
8307
  borderRadius: "8px",
8797
- padding: "6px 8px"
8308
+ padding: "6px 8px",
8309
+ display: "flex",
8310
+ flexDirection: "column",
8311
+ gap: "4px"
8798
8312
  },
8799
8313
  children: [
8800
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {
8314
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
8801
8315
  style: {
8802
- color: "rgba(255,255,255,0.68)"
8316
+ display: "grid",
8317
+ gridTemplateColumns: "56px 54px minmax(0, 1fr) 20px",
8318
+ gap: "6px",
8319
+ alignItems: "center",
8320
+ minWidth: 0
8803
8321
  },
8804
- children: formatDebugClock(entry.timestampMs)
8322
+ children: [
8323
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {
8324
+ style: {
8325
+ color: "rgba(255,255,255,0.68)"
8326
+ },
8327
+ children: formatDebugClock(entry.timestampMs)
8328
+ }),
8329
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {
8330
+ style: {
8331
+ fontWeight: 700,
8332
+ color: evt.color,
8333
+ fontSize: "10px"
8334
+ },
8335
+ children: evt.label
8336
+ }),
8337
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {
8338
+ style: {
8339
+ color: "rgba(255,255,255,0.88)",
8340
+ overflow: "hidden",
8341
+ textOverflow: "ellipsis",
8342
+ whiteSpace: "nowrap",
8343
+ minWidth: 0
8344
+ },
8345
+ title: entry.segmentName,
8346
+ children: fileName
8347
+ }),
8348
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", {
8349
+ onClick: function onClick() {
8350
+ return navigator.clipboard.writeText(entry.segmentName);
8351
+ },
8352
+ title: entry.segmentName,
8353
+ style: {
8354
+ background: "none",
8355
+ border: "none",
8356
+ cursor: "pointer",
8357
+ padding: "2px",
8358
+ color: "rgba(255,255,255,0.45)",
8359
+ display: "flex",
8360
+ alignItems: "center",
8361
+ justifyContent: "center",
8362
+ borderRadius: "4px",
8363
+ flexShrink: 0
8364
+ },
8365
+ onMouseEnter: function onMouseEnter(e) {
8366
+ return e.currentTarget.style.color = "rgba(255,255,255,0.9)";
8367
+ },
8368
+ onMouseLeave: function onMouseLeave(e) {
8369
+ return e.currentTarget.style.color = "rgba(255,255,255,0.45)";
8370
+ },
8371
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_fa.FaCopy, {
8372
+ size: 10
8373
+ })
8374
+ })
8375
+ ]
8805
8376
  }),
8806
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {
8377
+ (entry.offsetSeconds != null || entry.detail || entry.updatedAt) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", {
8807
8378
  style: {
8808
- fontWeight: 700,
8809
- color: evt.color,
8379
+ display: "flex",
8380
+ flexWrap: "wrap",
8381
+ gap: "6px",
8382
+ paddingLeft: "0px",
8810
8383
  fontSize: "10px"
8811
8384
  },
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
- })
8385
+ children: [
8386
+ entry.offsetSeconds != null && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", {
8387
+ style: {
8388
+ color: "rgba(255,255,255,0.55)",
8389
+ background: "rgba(255,255,255,0.06)",
8390
+ borderRadius: "4px",
8391
+ padding: "1px 5px"
8392
+ },
8393
+ children: [
8394
+ "+",
8395
+ entry.offsetSeconds.toFixed(2),
8396
+ "s"
8397
+ ]
8398
+ }),
8399
+ entry.detail && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {
8400
+ style: {
8401
+ color: "rgba(255,255,255,0.55)",
8402
+ background: "rgba(255,255,255,0.06)",
8403
+ borderRadius: "4px",
8404
+ padding: "1px 5px",
8405
+ overflow: "hidden",
8406
+ textOverflow: "ellipsis",
8407
+ whiteSpace: "nowrap",
8408
+ maxWidth: "100%"
8409
+ },
8410
+ children: entry.detail
8411
+ }),
8412
+ entry.updatedAt && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", {
8413
+ style: {
8414
+ color: "rgba(255,255,255,0.38)",
8415
+ background: "rgba(255,255,255,0.04)",
8416
+ borderRadius: "4px",
8417
+ padding: "1px 5px"
8418
+ },
8419
+ children: formatAiRelativeTime(entry.updatedAt)
8420
+ })
8421
+ ]
8833
8422
  })
8834
8423
  ]
8835
8424
  }, "".concat(entry.timestampMs, "-").concat(idx));