stormcloud-video-player 0.3.58 → 0.3.60

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.
@@ -1709,6 +1709,16 @@ function createHlsAdPlayer(contentVideo, options) {
1709
1709
  });
1710
1710
  return bestMatch.file;
1711
1711
  }
1712
+ function isHlsMediaFile(mediaFile) {
1713
+ var type = mediaFile.type.toLowerCase();
1714
+ var url = mediaFile.url.toLowerCase();
1715
+ return type === "application/x-mpegurl" || type === "application/vnd.apple.mpegurl" || type.includes("mpegurl") || url.includes(".m3u8");
1716
+ }
1717
+ function isProgressiveMediaFile(mediaFile) {
1718
+ var type = mediaFile.type.toLowerCase();
1719
+ var url = mediaFile.url.toLowerCase();
1720
+ return type.startsWith("video/") || url.endsWith(".mp4") || url.includes(".mp4?");
1721
+ }
1712
1722
  function parseVastXml(xmlString) {
1713
1723
  try {
1714
1724
  var _xmlDoc_querySelector, _xmlDoc_querySelector1, _xmlDoc_querySelector_textContent, _xmlDoc_querySelector2;
@@ -1740,30 +1750,32 @@ function createHlsAdPlayer(contentVideo, options) {
1740
1750
  var width = mf.getAttribute("width") || "";
1741
1751
  var height = mf.getAttribute("height") || "";
1742
1752
  console.log("[HlsAdPlayer] MediaFile ".concat(index, ': type="').concat(type, '", url="').concat(url, '", width="').concat(width, '", height="').concat(height, '"'));
1743
- if (type === "application/x-mpegURL" || type.includes("m3u8")) {
1744
- if (!url) {
1745
- console.warn("[HlsAdPlayer] MediaFile ".concat(index, " has HLS type but empty URL"));
1746
- return;
1747
- }
1748
- var bitrateAttr = mf.getAttribute("bitrate");
1749
- var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
1750
- mediaFiles.push({
1751
- url: url,
1752
- type: type,
1753
- width: parseInt(width || "1920", 10),
1754
- height: parseInt(height || "1080", 10),
1755
- bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
1756
- });
1757
- console.log("[HlsAdPlayer] Added HLS MediaFile: ".concat(url));
1753
+ var mediaFile = {
1754
+ url: url,
1755
+ type: type,
1756
+ width: parseInt(width || "1920", 10),
1757
+ height: parseInt(height || "1080", 10),
1758
+ bitrate: void 0
1759
+ };
1760
+ if (!url) {
1761
+ console.warn("[HlsAdPlayer] MediaFile ".concat(index, " has empty URL"));
1762
+ return;
1763
+ }
1764
+ var bitrateAttr = mf.getAttribute("bitrate");
1765
+ var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
1766
+ mediaFile.bitrate = bitrateValue && bitrateValue > 0 ? bitrateValue : void 0;
1767
+ if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
1768
+ mediaFiles.push(mediaFile);
1769
+ console.log("[HlsAdPlayer] Added ".concat(isHlsMediaFile(mediaFile) ? "HLS" : "progressive", " MediaFile: ").concat(url));
1758
1770
  } else {
1759
- console.log("[HlsAdPlayer] MediaFile ".concat(index, ' ignored (type="').concat(type, '" is not HLS)'));
1771
+ console.log("[HlsAdPlayer] MediaFile ".concat(index, ' ignored (type="').concat(type, '" is not supported)'));
1760
1772
  }
1761
1773
  });
1762
1774
  if (mediaFiles.length === 0) {
1763
1775
  if (isNoAdAvailable) {
1764
1776
  console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
1765
1777
  } else {
1766
- console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
1778
+ console.warn("[HlsAdPlayer] No supported media files found in VAST XML");
1767
1779
  }
1768
1780
  return null;
1769
1781
  }
@@ -2060,7 +2072,7 @@ function createHlsAdPlayer(contentVideo, options) {
2060
2072
  },
2061
2073
  play: function play() {
2062
2074
  return _async_to_generator(function() {
2063
- var contentVolume, adVolume, mediaFile;
2075
+ var contentVolume, adVolume, mediaFile, isHlsAd;
2064
2076
  return _ts_generator(this, function(_state) {
2065
2077
  if (!currentAd) {
2066
2078
  console.warn("[HlsAdPlayer] Cannot play: No ad loaded (no ads available)");
@@ -2112,8 +2124,9 @@ function createHlsAdPlayer(contentVideo, options) {
2112
2124
  if (!mediaFile) {
2113
2125
  throw new Error("No media file available for ad");
2114
2126
  }
2115
- console.log("[HlsAdPlayer] Loading ad from: ".concat(mediaFile.url));
2116
- if (import_hls.default.isSupported()) {
2127
+ isHlsAd = isHlsMediaFile(mediaFile);
2128
+ console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad from: ").concat(mediaFile.url));
2129
+ if (isHlsAd && import_hls.default.isSupported()) {
2117
2130
  if (adHls) {
2118
2131
  adHls.destroy();
2119
2132
  }
@@ -2136,14 +2149,25 @@ function createHlsAdPlayer(contentVideo, options) {
2136
2149
  handleAdError();
2137
2150
  }
2138
2151
  });
2139
- } else if (adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
2152
+ } else if (isHlsAd && adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
2140
2153
  adVideoElement.src = mediaFile.url;
2141
2154
  adVideoElement.play().catch(function(error) {
2142
2155
  console.error("[HlsAdPlayer] Error starting ad playback:", error);
2143
2156
  handleAdError();
2144
2157
  });
2158
+ } else if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {
2159
+ if (adHls) {
2160
+ adHls.destroy();
2161
+ adHls = void 0;
2162
+ }
2163
+ adVideoElement.src = mediaFile.url;
2164
+ adVideoElement.load();
2165
+ adVideoElement.play().catch(function(error) {
2166
+ console.error("[HlsAdPlayer] Error starting progressive ad playback:", error);
2167
+ handleAdError();
2168
+ });
2145
2169
  } else {
2146
- throw new Error("HLS not supported");
2170
+ throw new Error("Unsupported ad media file type: ".concat(mediaFile.type));
2147
2171
  }
2148
2172
  return [
2149
2173
  2,
@@ -3224,6 +3248,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3224
3248
  this.adRequestQueue = [];
3225
3249
  this.maxPlaceholderDurationMs = 5e3;
3226
3250
  this.isShowingPlaceholder = false;
3251
+ this.tsScte35Pids = /* @__PURE__ */ new Set();
3252
+ this.pmtPids = /* @__PURE__ */ new Set();
3253
+ this.processedTsScte35Sections = /* @__PURE__ */ new Set();
3254
+ this.pendingScte35Cues = /* @__PURE__ */ new Map();
3255
+ this.recentScte35CueKeys = /* @__PURE__ */ new Map();
3256
+ this.recentScte35CueLimit = 200;
3227
3257
  this.totalAdRequestsInBreak = 0;
3228
3258
  this.maxTotalAdRequestsPerBreak = 10;
3229
3259
  this.pendingAdBreak = null;
@@ -3493,7 +3523,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3493
3523
  if (_this.config.debugAdTiming) {
3494
3524
  console.log("[StormcloudVideoPlayer] \uD83C\uDFAF EARLY SCTE-35 DETECTION: Ad break marker found in fragment", i, "- starting pre-fetch (NOT playing yet)");
3495
3525
  }
3496
- _this.startAdPrefetch(marker, frag === null || frag === void 0 ? void 0 : frag.sn);
3526
+ _this.onScte35Cue(marker, _object_spread({}, _this.createScte35CueContext("manifest", "early", frag)));
3497
3527
  return;
3498
3528
  }
3499
3529
  }
@@ -3574,10 +3604,21 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3574
3604
  return _this.onId3Tag(tag);
3575
3605
  });
3576
3606
  });
3607
+ this.hls.on(import_hls2.default.Events.FRAG_LOADED, function(_evt, data) {
3608
+ var _data_frag;
3609
+ _this.processFragmentScte35Payload(data === null || data === void 0 ? void 0 : data.payload, typeof (data === null || data === void 0 ? void 0 : (_data_frag = data.frag) === null || _data_frag === void 0 ? void 0 : _data_frag.sn) === "number" ? data.frag.sn : void 0, _this.getFragmentStartSeconds(data === null || data === void 0 ? void 0 : data.frag));
3610
+ });
3611
+ this.hls.on(import_hls2.default.Events.FRAG_DECRYPTED, function(_evt, data) {
3612
+ var _data_frag;
3613
+ _this.processFragmentScte35Payload(data === null || data === void 0 ? void 0 : data.payload, typeof (data === null || data === void 0 ? void 0 : (_data_frag = data.frag) === null || _data_frag === void 0 ? void 0 : _data_frag.sn) === "number" ? data.frag.sn : void 0, _this.getFragmentStartSeconds(data === null || data === void 0 ? void 0 : data.frag));
3614
+ });
3577
3615
  this.hls.on(import_hls2.default.Events.FRAG_CHANGED, function(_evt, data) {
3578
3616
  var frag = data === null || data === void 0 ? void 0 : data.frag;
3579
3617
  var tagList = frag === null || frag === void 0 ? void 0 : frag.tagList;
3580
- if (!Array.isArray(tagList)) return;
3618
+ if (!Array.isArray(tagList)) {
3619
+ _this.activatePendingScte35CuesForFragment(frag);
3620
+ return;
3621
+ }
3581
3622
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3582
3623
  try {
3583
3624
  for(var _iterator = tagList[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
@@ -3613,7 +3654,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3613
3654
  value: value
3614
3655
  }
3615
3656
  });
3616
- _this.onScte35Marker(marker);
3657
+ _this.onScte35Cue(marker, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3617
3658
  } else if (tag.includes("EXT-X-CUE-OUT")) {
3618
3659
  var durationSeconds = _this.parseCueOutDuration(value);
3619
3660
  var marker1 = _object_spread_props(_object_spread({
@@ -3626,15 +3667,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3626
3667
  value: value
3627
3668
  }
3628
3669
  });
3629
- _this.onScte35Marker(marker1);
3670
+ _this.onScte35Cue(marker1, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3630
3671
  } else if (tag.includes("EXT-X-CUE-IN")) {
3631
- _this.onScte35Marker({
3672
+ _this.onScte35Cue({
3632
3673
  type: "end",
3633
3674
  raw: {
3634
3675
  tag: tag,
3635
3676
  value: value
3636
3677
  }
3637
- });
3678
+ }, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3638
3679
  } else if (tag.includes("EXT-X-DATERANGE")) {
3639
3680
  var _attrs_CLASS;
3640
3681
  var attrs = _this.parseAttributeList(value);
@@ -3654,17 +3695,17 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3654
3695
  attrs: attrs
3655
3696
  }
3656
3697
  });
3657
- _this.onScte35Marker(marker2);
3698
+ _this.onScte35Cue(marker2, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3658
3699
  }
3659
3700
  if (hasScteIn) {
3660
- _this.onScte35Marker({
3701
+ _this.onScte35Cue({
3661
3702
  type: "end",
3662
3703
  raw: {
3663
3704
  tag: tag,
3664
3705
  value: value,
3665
3706
  attrs: attrs
3666
3707
  }
3667
- });
3708
+ }, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3668
3709
  }
3669
3710
  }
3670
3711
  }
@@ -3682,6 +3723,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3682
3723
  }
3683
3724
  }
3684
3725
  }
3726
+ _this.activatePendingScte35CuesForFragment(frag);
3685
3727
  });
3686
3728
  this.hls.on(import_hls2.default.Events.ERROR, function(_evt, data) {
3687
3729
  if (data === null || data === void 0 ? void 0 : data.fatal) {
@@ -3987,7 +4029,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3987
4029
  }
3988
4030
  var marker = this.parseScte35FromId3(tag);
3989
4031
  if (marker) {
3990
- this.onScte35Marker(marker);
4032
+ this.onScte35Cue(marker, {
4033
+ source: "id3",
4034
+ readiness: "playback"
4035
+ });
3991
4036
  }
3992
4037
  }
3993
4038
  },
@@ -4131,9 +4176,251 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4131
4176
  }
4132
4177
  }
4133
4178
  },
4179
+ {
4180
+ key: "createScte35CueContext",
4181
+ value: function createScte35CueContext(source, readiness, frag) {
4182
+ var context = {
4183
+ source: source,
4184
+ readiness: readiness
4185
+ };
4186
+ if (typeof (frag === null || frag === void 0 ? void 0 : frag.sn) === "number") {
4187
+ context.fragmentSn = frag.sn;
4188
+ }
4189
+ var fragmentStartSeconds = this.getFragmentStartSeconds(frag);
4190
+ if (fragmentStartSeconds !== void 0) {
4191
+ context.fragmentStartSeconds = fragmentStartSeconds;
4192
+ }
4193
+ return context;
4194
+ }
4195
+ },
4196
+ {
4197
+ key: "getFragmentStartSeconds",
4198
+ value: function getFragmentStartSeconds(frag) {
4199
+ var candidates = [
4200
+ frag === null || frag === void 0 ? void 0 : frag.start,
4201
+ frag === null || frag === void 0 ? void 0 : frag.startPTS
4202
+ ];
4203
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
4204
+ try {
4205
+ for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
4206
+ var candidate = _step.value;
4207
+ if (typeof candidate === "number" && Number.isFinite(candidate)) {
4208
+ return candidate;
4209
+ }
4210
+ }
4211
+ } catch (err) {
4212
+ _didIteratorError = true;
4213
+ _iteratorError = err;
4214
+ } finally{
4215
+ try {
4216
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
4217
+ _iterator.return();
4218
+ }
4219
+ } finally{
4220
+ if (_didIteratorError) {
4221
+ throw _iteratorError;
4222
+ }
4223
+ }
4224
+ }
4225
+ return void 0;
4226
+ }
4227
+ },
4228
+ {
4229
+ key: "onScte35Cue",
4230
+ value: function onScte35Cue(marker, context) {
4231
+ var cue = this.createScte35Cue(marker, context);
4232
+ var pendingKey = this.getPendingScte35CueKey(cue);
4233
+ if (context.readiness === "early") {
4234
+ this.pendingScte35Cues.set(pendingKey, cue);
4235
+ this.trimRecentScte35CueMaps();
4236
+ if (marker.type === "start") {
4237
+ this.startAdPrefetch(marker, context.fragmentSn, cue.key);
4238
+ }
4239
+ return;
4240
+ }
4241
+ if (marker.type === "end" && !this.shouldAcceptScte35EndCue(cue)) {
4242
+ if (this.config.debugAdTiming) {
4243
+ console.log("[StormcloudVideoPlayer] Ignoring SCTE-35 end cue", {
4244
+ key: cue.key,
4245
+ activeScte35BreakKey: this.activeScte35BreakKey,
4246
+ inAdBreak: this.inAdBreak,
4247
+ source: cue.source
4248
+ });
4249
+ }
4250
+ return;
4251
+ }
4252
+ if (marker.type === "start" && this.hasRecentlyHandledScte35Cue(cue)) {
4253
+ if (this.config.debugAdTiming) {
4254
+ console.log("[StormcloudVideoPlayer] Ignoring duplicate SCTE-35 start cue", {
4255
+ key: cue.key,
4256
+ source: cue.source
4257
+ });
4258
+ }
4259
+ return;
4260
+ }
4261
+ this.pendingScte35Cues.delete(pendingKey);
4262
+ this.markScte35CueHandled(cue);
4263
+ this.onScte35Marker(marker, cue.key);
4264
+ }
4265
+ },
4266
+ {
4267
+ key: "createScte35Cue",
4268
+ value: function createScte35Cue(marker, context) {
4269
+ var cue = {
4270
+ marker: marker,
4271
+ source: context.source,
4272
+ readiness: context.readiness,
4273
+ key: this.getScte35CueKey(marker, context)
4274
+ };
4275
+ if (context.fragmentSn !== void 0) {
4276
+ cue.fragmentSn = context.fragmentSn;
4277
+ }
4278
+ if (context.fragmentStartSeconds !== void 0) {
4279
+ cue.fragmentStartSeconds = context.fragmentStartSeconds;
4280
+ }
4281
+ return cue;
4282
+ }
4283
+ },
4284
+ {
4285
+ key: "getScte35CueKey",
4286
+ value: function getScte35CueKey(marker, context) {
4287
+ var _raw_attrs, _raw_attrs1, _raw_attrs2;
4288
+ var raw = this.getScte35MarkerRaw(marker);
4289
+ var spliceEventId = this.toIdentityString(raw === null || raw === void 0 ? void 0 : raw.splice_event_id);
4290
+ if (spliceEventId) {
4291
+ return "splice:".concat(spliceEventId);
4292
+ }
4293
+ var segmentationEventId = this.toIdentityString(raw === null || raw === void 0 ? void 0 : raw.segmentation_event_id);
4294
+ if (segmentationEventId) {
4295
+ return "segmentation:".concat(segmentationEventId);
4296
+ }
4297
+ var daterangeId = this.toIdentityString(raw === null || raw === void 0 ? void 0 : (_raw_attrs = raw.attrs) === null || _raw_attrs === void 0 ? void 0 : _raw_attrs.ID);
4298
+ if (daterangeId) {
4299
+ return "daterange:".concat(daterangeId);
4300
+ }
4301
+ var scteValue = this.toIdentityString(raw === null || raw === void 0 ? void 0 : (_raw_attrs1 = raw.attrs) === null || _raw_attrs1 === void 0 ? void 0 : _raw_attrs1["SCTE35-OUT"]) || this.toIdentityString(raw === null || raw === void 0 ? void 0 : (_raw_attrs2 = raw.attrs) === null || _raw_attrs2 === void 0 ? void 0 : _raw_attrs2["SCTE35-IN"]);
4302
+ if (scteValue) {
4303
+ return "daterange-scte:".concat(scteValue);
4304
+ }
4305
+ if (typeof marker.ptsSeconds === "number" && Number.isFinite(marker.ptsSeconds)) {
4306
+ return "pts:".concat(Math.round(marker.ptsSeconds * 2) / 2);
4307
+ }
4308
+ if (context.fragmentSn !== void 0) {
4309
+ return "fragment:".concat(context.fragmentSn);
4310
+ }
4311
+ return "".concat(context.source, ":wallclock:").concat(Math.floor(Date.now() / 1e3));
4312
+ }
4313
+ },
4314
+ {
4315
+ key: "getPendingScte35CueKey",
4316
+ value: function getPendingScte35CueKey(cue) {
4317
+ return "".concat(cue.marker.type, ":").concat(cue.key, ":").concat(cue.fragmentSn !== void 0 ? cue.fragmentSn : "unknown");
4318
+ }
4319
+ },
4320
+ {
4321
+ key: "getScte35MarkerRaw",
4322
+ value: function getScte35MarkerRaw(marker) {
4323
+ return _type_of(marker.raw) === "object" && marker.raw !== null ? marker.raw : {};
4324
+ }
4325
+ },
4326
+ {
4327
+ key: "toIdentityString",
4328
+ value: function toIdentityString(value) {
4329
+ if (typeof value === "number" && Number.isFinite(value)) {
4330
+ return String(value);
4331
+ }
4332
+ if (typeof value === "string" && value.trim().length > 0) {
4333
+ return value.trim();
4334
+ }
4335
+ return void 0;
4336
+ }
4337
+ },
4338
+ {
4339
+ key: "isStrongScte35CueKey",
4340
+ value: function isStrongScte35CueKey(key) {
4341
+ return !!(key && (key.startsWith("splice:") || key.startsWith("segmentation:") || key.startsWith("daterange:") || key.startsWith("daterange-scte:")));
4342
+ }
4343
+ },
4344
+ {
4345
+ key: "hasRecentlyHandledScte35Cue",
4346
+ value: function hasRecentlyHandledScte35Cue(cue) {
4347
+ if (this.activeScte35BreakKey === cue.key || this.scheduledScte35BreakKey === cue.key) {
4348
+ return true;
4349
+ }
4350
+ var recentKey = "".concat(cue.marker.type, ":").concat(cue.key);
4351
+ return this.recentScte35CueKeys.has(recentKey);
4352
+ }
4353
+ },
4354
+ {
4355
+ key: "markScte35CueHandled",
4356
+ value: function markScte35CueHandled(cue) {
4357
+ this.recentScte35CueKeys.set("".concat(cue.marker.type, ":").concat(cue.key), Date.now());
4358
+ this.trimRecentScte35CueMaps();
4359
+ }
4360
+ },
4361
+ {
4362
+ key: "trimRecentScte35CueMaps",
4363
+ value: function trimRecentScte35CueMaps() {
4364
+ while(this.recentScte35CueKeys.size > this.recentScte35CueLimit){
4365
+ var firstKey = this.recentScte35CueKeys.keys().next().value;
4366
+ if (!firstKey) {
4367
+ break;
4368
+ }
4369
+ this.recentScte35CueKeys.delete(firstKey);
4370
+ }
4371
+ while(this.pendingScte35Cues.size > this.recentScte35CueLimit){
4372
+ var firstKey1 = this.pendingScte35Cues.keys().next().value;
4373
+ if (!firstKey1) {
4374
+ break;
4375
+ }
4376
+ this.pendingScte35Cues.delete(firstKey1);
4377
+ }
4378
+ }
4379
+ },
4380
+ {
4381
+ key: "shouldAcceptScte35EndCue",
4382
+ value: function shouldAcceptScte35EndCue(cue) {
4383
+ if (!this.inAdBreak) {
4384
+ return false;
4385
+ }
4386
+ if (this.isStrongScte35CueKey(this.activeScte35BreakKey) && this.isStrongScte35CueKey(cue.key) && this.activeScte35BreakKey !== cue.key) {
4387
+ return false;
4388
+ }
4389
+ return true;
4390
+ }
4391
+ },
4392
+ {
4393
+ key: "activatePendingScte35CuesForFragment",
4394
+ value: function activatePendingScte35CuesForFragment(frag) {
4395
+ var _this = this;
4396
+ var fragmentSn = typeof (frag === null || frag === void 0 ? void 0 : frag.sn) === "number" ? frag.sn : void 0;
4397
+ if (fragmentSn === void 0) {
4398
+ return;
4399
+ }
4400
+ var matchingCues = Array.from(this.pendingScte35Cues.entries()).filter(function(param) {
4401
+ var _param = _sliced_to_array(param, 2), cue = _param[1];
4402
+ return cue.fragmentSn === fragmentSn;
4403
+ });
4404
+ matchingCues.forEach(function(param) {
4405
+ var _param = _sliced_to_array(param, 2), pendingKey = _param[0], cue = _param[1];
4406
+ var _cue_fragmentStartSeconds;
4407
+ _this.pendingScte35Cues.delete(pendingKey);
4408
+ var context = {
4409
+ source: cue.source,
4410
+ readiness: "playback"
4411
+ };
4412
+ context.fragmentSn = fragmentSn;
4413
+ var fragmentStartSeconds = (_cue_fragmentStartSeconds = cue.fragmentStartSeconds) !== null && _cue_fragmentStartSeconds !== void 0 ? _cue_fragmentStartSeconds : _this.getFragmentStartSeconds(frag);
4414
+ if (fragmentStartSeconds !== void 0) {
4415
+ context.fragmentStartSeconds = fragmentStartSeconds;
4416
+ }
4417
+ _this.onScte35Cue(cue.marker, context);
4418
+ });
4419
+ }
4420
+ },
4134
4421
  {
4135
4422
  key: "onScte35Marker",
4136
- value: function onScte35Marker(marker) {
4423
+ value: function onScte35Marker(marker, cueKey) {
4137
4424
  if (this.config.debugAdTiming) {
4138
4425
  console.log("[StormcloudVideoPlayer] SCTE-35 marker detected:", {
4139
4426
  type: marker.type,
@@ -4147,13 +4434,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4147
4434
  if (marker.type === "start") {
4148
4435
  var _this_config_immediateManifestAds;
4149
4436
  var _this_pendingAdBreak;
4150
- if (!this.video.muted) {
4151
- this.video.muted = true;
4152
- this.video.volume = 0;
4153
- if (this.config.debugAdTiming) {
4154
- console.log("[StormcloudVideoPlayer] Muted video on SCTE start marker");
4155
- }
4156
- }
4157
4437
  if (this.inAdBreak) {
4158
4438
  if (marker.durationSeconds != null) {
4159
4439
  var newDurationMs = marker.durationSeconds * 1e3;
@@ -4177,10 +4457,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4177
4457
  sendAdDetectTracking(this.config.licenseKey, detectPayload).catch(function() {});
4178
4458
  }
4179
4459
  var hasPrefetchedAds = this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0;
4180
- this.inAdBreak = true;
4181
4460
  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;
4182
- this.expectedAdBreakDurationMs = durationMs;
4183
- this.currentAdBreakStartWallClockMs = Date.now();
4184
4461
  var isManifestMarker = this.isManifestBasedMarker(marker);
4185
4462
  var forceImmediate = (_this_config_immediateManifestAds = this.config.immediateManifestAds) !== null && _this_config_immediateManifestAds !== void 0 ? _this_config_immediateManifestAds : true;
4186
4463
  if (this.config.debugAdTiming) {
@@ -4196,7 +4473,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4196
4473
  console.log("[StormcloudVideoPlayer] Starting ad immediately (manifest-based)".concat(hasPrefetchedAds ? " with prefetched ads" : ""));
4197
4474
  }
4198
4475
  this.clearAdStartTimer();
4199
- this.handleAdStart(marker);
4476
+ this.startScte35AdBreak(marker, cueKey, durationMs);
4200
4477
  } else if (typeof marker.ptsSeconds === "number") {
4201
4478
  var _this_config_driftToleranceMs;
4202
4479
  var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
@@ -4216,23 +4493,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4216
4493
  if (this.config.debugAdTiming) {
4217
4494
  console.log("[StormcloudVideoPlayer] Scheduling ad start in ".concat(deltaMs, "ms"));
4218
4495
  }
4219
- this.scheduleAdStartIn(deltaMs);
4496
+ this.expectedAdBreakDurationMs = durationMs;
4497
+ this.scheduledScte35BreakKey = cueKey;
4498
+ this.scheduleAdStartIn(deltaMs, marker, cueKey);
4220
4499
  } else {
4221
4500
  if (this.config.debugAdTiming) {
4222
4501
  console.log("[StormcloudVideoPlayer] Starting ad immediately (within tolerance)");
4223
4502
  }
4224
4503
  this.clearAdStartTimer();
4225
- this.handleAdStart(marker);
4504
+ this.startScte35AdBreak(marker, cueKey, durationMs);
4226
4505
  }
4227
4506
  } else {
4228
4507
  if (this.config.debugAdTiming) {
4229
4508
  console.log("[StormcloudVideoPlayer] Starting ad immediately (fallback)");
4230
4509
  }
4231
4510
  this.clearAdStartTimer();
4232
- this.handleAdStart(marker);
4233
- }
4234
- if (this.expectedAdBreakDurationMs != null) {
4235
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
4511
+ this.startScte35AdBreak(marker, cueKey, durationMs);
4236
4512
  }
4237
4513
  return;
4238
4514
  }
@@ -4288,6 +4564,27 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4288
4564
  }
4289
4565
  }
4290
4566
  },
4567
+ {
4568
+ key: "startScte35AdBreak",
4569
+ value: function startScte35AdBreak(marker, cueKey, durationMs) {
4570
+ if (!this.video.muted) {
4571
+ this.video.muted = true;
4572
+ this.video.volume = 0;
4573
+ if (this.config.debugAdTiming) {
4574
+ console.log("[StormcloudVideoPlayer] Muted video on SCTE start marker");
4575
+ }
4576
+ }
4577
+ this.inAdBreak = true;
4578
+ this.activeScte35BreakKey = cueKey !== null && cueKey !== void 0 ? cueKey : this.pendingScte35CueKey;
4579
+ this.scheduledScte35BreakKey = void 0;
4580
+ this.expectedAdBreakDurationMs = durationMs;
4581
+ this.currentAdBreakStartWallClockMs = Date.now();
4582
+ this.handleAdStart(marker);
4583
+ if (this.expectedAdBreakDurationMs != null) {
4584
+ this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
4585
+ }
4586
+ }
4587
+ },
4291
4588
  {
4292
4589
  key: "parseCueOutDuration",
4293
4590
  value: function parseCueOutDuration(value) {
@@ -4371,6 +4668,336 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4371
4668
  return false;
4372
4669
  }
4373
4670
  },
4671
+ {
4672
+ key: "normalizeFragmentPayload",
4673
+ value: function normalizeFragmentPayload(payload) {
4674
+ if (_instanceof(payload, Uint8Array)) {
4675
+ return payload;
4676
+ }
4677
+ if (_instanceof(payload, ArrayBuffer)) {
4678
+ return new Uint8Array(payload);
4679
+ }
4680
+ if (ArrayBuffer.isView(payload)) {
4681
+ var view = payload;
4682
+ return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
4683
+ }
4684
+ return void 0;
4685
+ }
4686
+ },
4687
+ {
4688
+ key: "processFragmentScte35Payload",
4689
+ value: function processFragmentScte35Payload(payloadData, fragmentSn, fragmentStartSeconds) {
4690
+ var _this = this;
4691
+ var payload = this.normalizeFragmentPayload(payloadData);
4692
+ if (!payload) {
4693
+ return;
4694
+ }
4695
+ var markers = this.parseScte35FromTsPackets(payload);
4696
+ markers.forEach(function(marker) {
4697
+ var context = {
4698
+ source: "ts",
4699
+ readiness: "early"
4700
+ };
4701
+ if (fragmentSn !== void 0) {
4702
+ context.fragmentSn = fragmentSn;
4703
+ }
4704
+ if (fragmentStartSeconds !== void 0) {
4705
+ context.fragmentStartSeconds = fragmentStartSeconds;
4706
+ }
4707
+ _this.onScte35Cue(marker, context);
4708
+ });
4709
+ }
4710
+ },
4711
+ {
4712
+ key: "parseScte35FromTsPackets",
4713
+ value: function parseScte35FromTsPackets(data) {
4714
+ var packetInfo = this.detectTsPacketFormat(data);
4715
+ if (!packetInfo) {
4716
+ return [];
4717
+ }
4718
+ var markers = [];
4719
+ var sectionAssemblers = /* @__PURE__ */ new Map();
4720
+ for(var packetStart = packetInfo.offset; packetStart + packetInfo.packetSize <= data.length; packetStart += packetInfo.packetSize){
4721
+ var tsStart = packetStart + packetInfo.tsPayloadOffset;
4722
+ if (data[tsStart] !== 71) {
4723
+ continue;
4724
+ }
4725
+ var secondByte = data[tsStart + 1];
4726
+ var thirdByte = data[tsStart + 2];
4727
+ var fourthByte = data[tsStart + 3];
4728
+ if (secondByte == null || thirdByte == null || fourthByte == null || (secondByte & 128) !== 0) {
4729
+ continue;
4730
+ }
4731
+ var payloadUnitStart = (secondByte & 64) !== 0;
4732
+ var pid = (secondByte & 31) << 8 | thirdByte;
4733
+ var adaptationFieldControl = fourthByte >> 4 & 3;
4734
+ var hasPayload = adaptationFieldControl === 1 || adaptationFieldControl === 3;
4735
+ if (!hasPayload) {
4736
+ continue;
4737
+ }
4738
+ var payloadStart = tsStart + 4;
4739
+ if (adaptationFieldControl === 3) {
4740
+ var adaptationLength = data[payloadStart];
4741
+ if (adaptationLength == null) {
4742
+ continue;
4743
+ }
4744
+ payloadStart += 1 + adaptationLength;
4745
+ }
4746
+ var payloadEnd = Math.min(tsStart + 188, data.length);
4747
+ if (payloadStart >= payloadEnd || payloadStart >= data.length) {
4748
+ continue;
4749
+ }
4750
+ var payload = data.subarray(payloadStart, payloadEnd);
4751
+ if (pid === 0) {
4752
+ this.parsePatSection(payload, payloadUnitStart);
4753
+ } else if (this.pmtPids.has(pid)) {
4754
+ this.parsePmtSection(payload, payloadUnitStart);
4755
+ } else if (this.tsScte35Pids.has(pid)) {
4756
+ this.collectScte35SectionsFromPayload(pid, payload, payloadUnitStart, sectionAssemblers, markers);
4757
+ }
4758
+ }
4759
+ return markers;
4760
+ }
4761
+ },
4762
+ {
4763
+ key: "detectTsPacketFormat",
4764
+ value: function detectTsPacketFormat(data) {
4765
+ var packetSizes = [
4766
+ 188,
4767
+ 192,
4768
+ 204
4769
+ ];
4770
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
4771
+ try {
4772
+ for(var _iterator = packetSizes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
4773
+ var packetSize = _step.value;
4774
+ var tsPayloadOffset = packetSize === 192 ? 4 : 0;
4775
+ for(var offset = 0; offset < packetSize; offset++){
4776
+ var matchedPackets = 0;
4777
+ for(var packetStart = offset; packetStart + tsPayloadOffset < data.length && matchedPackets < 5; packetStart += packetSize){
4778
+ if (data[packetStart + tsPayloadOffset] !== 71) {
4779
+ break;
4780
+ }
4781
+ matchedPackets++;
4782
+ }
4783
+ if (matchedPackets >= 2) {
4784
+ return {
4785
+ offset: offset,
4786
+ packetSize: packetSize,
4787
+ tsPayloadOffset: tsPayloadOffset
4788
+ };
4789
+ }
4790
+ }
4791
+ }
4792
+ } catch (err) {
4793
+ _didIteratorError = true;
4794
+ _iteratorError = err;
4795
+ } finally{
4796
+ try {
4797
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
4798
+ _iterator.return();
4799
+ }
4800
+ } finally{
4801
+ if (_didIteratorError) {
4802
+ throw _iteratorError;
4803
+ }
4804
+ }
4805
+ }
4806
+ return void 0;
4807
+ }
4808
+ },
4809
+ {
4810
+ key: "parsePatSection",
4811
+ value: function parsePatSection(payload, payloadUnitStart) {
4812
+ var sectionStart = this.getPsiSectionStart(payload, payloadUnitStart);
4813
+ if (sectionStart == null || sectionStart + 8 >= payload.length) {
4814
+ return;
4815
+ }
4816
+ if (payload[sectionStart] !== 0) {
4817
+ return;
4818
+ }
4819
+ var sectionLength = this.getPsiSectionLength(payload, sectionStart);
4820
+ var sectionEnd = Math.min(payload.length, sectionStart + 3 + sectionLength);
4821
+ for(var offset = sectionStart + 8; offset + 4 <= sectionEnd - 4; offset += 4){
4822
+ var _payload_offset, _payload_, _payload_1, _payload_2;
4823
+ var programNumber = ((_payload_offset = payload[offset]) !== null && _payload_offset !== void 0 ? _payload_offset : 0) << 8 | ((_payload_ = payload[offset + 1]) !== null && _payload_ !== void 0 ? _payload_ : 0);
4824
+ var pid = (((_payload_1 = payload[offset + 2]) !== null && _payload_1 !== void 0 ? _payload_1 : 0) & 31) << 8 | ((_payload_2 = payload[offset + 3]) !== null && _payload_2 !== void 0 ? _payload_2 : 0);
4825
+ if (programNumber !== 0) {
4826
+ this.pmtPids.add(pid);
4827
+ }
4828
+ }
4829
+ }
4830
+ },
4831
+ {
4832
+ key: "parsePmtSection",
4833
+ value: function parsePmtSection(payload, payloadUnitStart) {
4834
+ var _payload_, _payload_1;
4835
+ var sectionStart = this.getPsiSectionStart(payload, payloadUnitStart);
4836
+ if (sectionStart == null || sectionStart + 12 >= payload.length) {
4837
+ return;
4838
+ }
4839
+ if (payload[sectionStart] !== 2) {
4840
+ return;
4841
+ }
4842
+ var sectionLength = this.getPsiSectionLength(payload, sectionStart);
4843
+ var sectionEnd = Math.min(payload.length, sectionStart + 3 + sectionLength);
4844
+ var programInfoLength = (((_payload_ = payload[sectionStart + 10]) !== null && _payload_ !== void 0 ? _payload_ : 0) & 15) << 8 | ((_payload_1 = payload[sectionStart + 11]) !== null && _payload_1 !== void 0 ? _payload_1 : 0);
4845
+ var offset = sectionStart + 12 + programInfoLength;
4846
+ while(offset + 5 <= sectionEnd - 4){
4847
+ var _payload_offset, _payload_2, _payload_3, _payload_4, _payload_5;
4848
+ var streamType = (_payload_offset = payload[offset]) !== null && _payload_offset !== void 0 ? _payload_offset : 0;
4849
+ var elementaryPid = (((_payload_2 = payload[offset + 1]) !== null && _payload_2 !== void 0 ? _payload_2 : 0) & 31) << 8 | ((_payload_3 = payload[offset + 2]) !== null && _payload_3 !== void 0 ? _payload_3 : 0);
4850
+ var esInfoLength = (((_payload_4 = payload[offset + 3]) !== null && _payload_4 !== void 0 ? _payload_4 : 0) & 15) << 8 | ((_payload_5 = payload[offset + 4]) !== null && _payload_5 !== void 0 ? _payload_5 : 0);
4851
+ var descriptorStart = offset + 5;
4852
+ var descriptorEnd = Math.min(descriptorStart + esInfoLength, sectionEnd - 4);
4853
+ if (streamType === 134 || streamType === 6 && this.descriptorsIdentifyScte35(payload, descriptorStart, descriptorEnd)) {
4854
+ this.tsScte35Pids.add(elementaryPid);
4855
+ }
4856
+ offset = descriptorStart + esInfoLength;
4857
+ }
4858
+ }
4859
+ },
4860
+ {
4861
+ key: "descriptorsIdentifyScte35",
4862
+ value: function descriptorsIdentifyScte35(data, start, end) {
4863
+ var offset = start;
4864
+ while(offset + 2 <= end){
4865
+ var _data_offset, _data_, _data_descriptorStart, _data_1, _data_2, _data_3;
4866
+ var tag = (_data_offset = data[offset]) !== null && _data_offset !== void 0 ? _data_offset : 0;
4867
+ var length = (_data_ = data[offset + 1]) !== null && _data_ !== void 0 ? _data_ : 0;
4868
+ var descriptorStart = offset + 2;
4869
+ var descriptorEnd = descriptorStart + length;
4870
+ if (descriptorEnd > end) {
4871
+ return false;
4872
+ }
4873
+ var registration = length >= 4 ? String.fromCharCode((_data_descriptorStart = data[descriptorStart]) !== null && _data_descriptorStart !== void 0 ? _data_descriptorStart : 0, (_data_1 = data[descriptorStart + 1]) !== null && _data_1 !== void 0 ? _data_1 : 0, (_data_2 = data[descriptorStart + 2]) !== null && _data_2 !== void 0 ? _data_2 : 0, (_data_3 = data[descriptorStart + 3]) !== null && _data_3 !== void 0 ? _data_3 : 0) : "";
4874
+ if (tag === 138 || registration === "CUEI" || registration === "SCTE") {
4875
+ return true;
4876
+ }
4877
+ offset = descriptorEnd;
4878
+ }
4879
+ return false;
4880
+ }
4881
+ },
4882
+ {
4883
+ key: "collectScte35SectionsFromPayload",
4884
+ value: function collectScte35SectionsFromPayload(pid, payload, payloadUnitStart, assemblers, markers) {
4885
+ if (payload.length === 0) {
4886
+ return;
4887
+ }
4888
+ var offset = 0;
4889
+ if (payloadUnitStart) {
4890
+ var _payload_;
4891
+ var pointerField = (_payload_ = payload[0]) !== null && _payload_ !== void 0 ? _payload_ : 0;
4892
+ var previousAssembler = assemblers.get(pid);
4893
+ if (previousAssembler && pointerField > 0) {
4894
+ this.appendScte35Bytes(pid, payload.subarray(1, Math.min(1 + pointerField, payload.length)), assemblers, markers);
4895
+ }
4896
+ assemblers.delete(pid);
4897
+ offset = 1 + pointerField;
4898
+ } else {
4899
+ this.appendScte35Bytes(pid, payload, assemblers, markers);
4900
+ return;
4901
+ }
4902
+ while(offset + 3 <= payload.length){
4903
+ var tableId = payload[offset];
4904
+ if (tableId == null || tableId === 255) {
4905
+ return;
4906
+ }
4907
+ var sectionLength = this.getPsiSectionLength(payload, offset);
4908
+ var totalLength = 3 + sectionLength;
4909
+ if (sectionLength <= 0 || totalLength <= 3) {
4910
+ return;
4911
+ }
4912
+ if (offset + totalLength <= payload.length) {
4913
+ this.addScte35SectionMarker(payload.subarray(offset, offset + totalLength), markers);
4914
+ offset += totalLength;
4915
+ } else {
4916
+ assemblers.set(pid, {
4917
+ bytes: Array.from(payload.subarray(offset)),
4918
+ expectedLength: totalLength
4919
+ });
4920
+ return;
4921
+ }
4922
+ }
4923
+ }
4924
+ },
4925
+ {
4926
+ key: "appendScte35Bytes",
4927
+ value: function appendScte35Bytes(pid, bytes, assemblers, markers) {
4928
+ var assembler = assemblers.get(pid);
4929
+ if (!assembler) {
4930
+ return;
4931
+ }
4932
+ for(var i = 0; i < bytes.length && assembler.bytes.length < assembler.expectedLength; i++){
4933
+ var _bytes_i;
4934
+ assembler.bytes.push((_bytes_i = bytes[i]) !== null && _bytes_i !== void 0 ? _bytes_i : 0);
4935
+ }
4936
+ if (assembler.bytes.length >= assembler.expectedLength) {
4937
+ assemblers.delete(pid);
4938
+ this.addScte35SectionMarker(new Uint8Array(assembler.bytes), markers);
4939
+ }
4940
+ }
4941
+ },
4942
+ {
4943
+ key: "addScte35SectionMarker",
4944
+ value: function addScte35SectionMarker(section, markers) {
4945
+ if (section[0] !== 252 || this.hasProcessedTsScte35Section(section)) {
4946
+ return;
4947
+ }
4948
+ var marker = this.parseScte35Binary(section);
4949
+ if (!marker) {
4950
+ return;
4951
+ }
4952
+ marker.raw = _object_spread_props(_object_spread({}, _type_of(marker.raw) === "object" && marker.raw ? marker.raw : {}), {
4953
+ source: "ts-packet"
4954
+ });
4955
+ markers.push(marker);
4956
+ }
4957
+ },
4958
+ {
4959
+ key: "hasProcessedTsScte35Section",
4960
+ value: function hasProcessedTsScte35Section(section) {
4961
+ var checksum = 0;
4962
+ for(var i = 0; i < section.length; i++){
4963
+ var _section_i;
4964
+ checksum = checksum * 31 + ((_section_i = section[i]) !== null && _section_i !== void 0 ? _section_i : 0) >>> 0;
4965
+ }
4966
+ var key = "".concat(section.length, ":").concat(checksum);
4967
+ if (this.processedTsScte35Sections.has(key)) {
4968
+ return true;
4969
+ }
4970
+ this.processedTsScte35Sections.add(key);
4971
+ if (this.processedTsScte35Sections.size > 200) {
4972
+ var firstKey = this.processedTsScte35Sections.values().next().value;
4973
+ if (firstKey) {
4974
+ this.processedTsScte35Sections.delete(firstKey);
4975
+ }
4976
+ }
4977
+ return false;
4978
+ }
4979
+ },
4980
+ {
4981
+ key: "getPsiSectionStart",
4982
+ value: function getPsiSectionStart(payload, payloadUnitStart) {
4983
+ if (!payloadUnitStart) {
4984
+ return void 0;
4985
+ }
4986
+ var pointerField = payload[0];
4987
+ if (pointerField == null) {
4988
+ return void 0;
4989
+ }
4990
+ var sectionStart = 1 + pointerField;
4991
+ return sectionStart < payload.length ? sectionStart : void 0;
4992
+ }
4993
+ },
4994
+ {
4995
+ key: "getPsiSectionLength",
4996
+ value: function getPsiSectionLength(data, offset) {
4997
+ var _data_, _data_1;
4998
+ return (((_data_ = data[offset + 1]) !== null && _data_ !== void 0 ? _data_ : 0) & 15) << 8 | ((_data_1 = data[offset + 2]) !== null && _data_1 !== void 0 ? _data_1 : 0);
4999
+ }
5000
+ },
4374
5001
  {
4375
5002
  key: "parseScte35Binary",
4376
5003
  value: function parseScte35Binary(data) {
@@ -4410,10 +5037,28 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4410
5037
  value: function skipBits(n) {
4411
5038
  this.readBits(n);
4412
5039
  }
5040
+ },
5041
+ {
5042
+ key: "bytePosition",
5043
+ get: function get() {
5044
+ return this.bitPos === 0 ? this.bytePos : this.bytePos + 1;
5045
+ }
4413
5046
  }
4414
5047
  ]);
4415
5048
  return BitReader;
4416
5049
  }();
5050
+ var readSpliceTime = function readSpliceTime(r2, ptsAdjustmentTicks2) {
5051
+ var timeSpecifiedFlag = r2.readBits(1) === 1;
5052
+ if (!timeSpecifiedFlag) {
5053
+ r2.readBits(7);
5054
+ return void 0;
5055
+ }
5056
+ r2.readBits(6);
5057
+ var high = r2.readBits(1);
5058
+ var low = r2.readBits(32);
5059
+ var ptsTicks = (high * 4294967296 + low + ptsAdjustmentTicks2) % 8589934592;
5060
+ return ptsTicks / 9e4;
5061
+ };
4417
5062
  var r = new BitReader(data);
4418
5063
  var tableId = r.readBits(8);
4419
5064
  if (tableId !== 252) return void 0;
@@ -4421,77 +5066,206 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4421
5066
  r.readBits(1);
4422
5067
  r.readBits(2);
4423
5068
  var sectionLength = r.readBits(12);
5069
+ if (sectionLength <= 0 || data.length < 3 + sectionLength) {
5070
+ return void 0;
5071
+ }
4424
5072
  r.readBits(8);
4425
5073
  r.readBits(1);
4426
5074
  r.readBits(6);
4427
5075
  var ptsAdjHigh = r.readBits(1);
4428
5076
  var ptsAdjLow = r.readBits(32);
4429
- void ptsAdjHigh;
4430
- void ptsAdjLow;
5077
+ var ptsAdjustmentTicks = ptsAdjHigh * 4294967296 + ptsAdjLow;
4431
5078
  r.readBits(8);
4432
5079
  r.readBits(12);
4433
5080
  var spliceCommandLength = r.readBits(12);
4434
5081
  var spliceCommandType = r.readBits(8);
4435
- if (spliceCommandType !== 5) {
5082
+ var markerType;
5083
+ var durationSeconds = void 0;
5084
+ var ptsSeconds = void 0;
5085
+ var spliceEventId = void 0;
5086
+ var commandBodyStart = r.bytePosition;
5087
+ if (spliceCommandType === 5) {
5088
+ spliceEventId = r.readBits(32);
5089
+ var cancel = r.readBits(1) === 1;
5090
+ r.readBits(7);
5091
+ if (cancel) return void 0;
5092
+ var outOfNetwork = r.readBits(1) === 1;
5093
+ var programSpliceFlag = r.readBits(1) === 1;
5094
+ var durationFlag = r.readBits(1) === 1;
5095
+ var spliceImmediateFlag = r.readBits(1) === 1;
5096
+ r.readBits(4);
5097
+ markerType = outOfNetwork ? "start" : "end";
5098
+ if (programSpliceFlag && !spliceImmediateFlag) {
5099
+ ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);
5100
+ } else if (!programSpliceFlag) {
5101
+ var componentCount = r.readBits(8);
5102
+ for(var i = 0; i < componentCount; i++){
5103
+ r.readBits(8);
5104
+ if (!spliceImmediateFlag) {
5105
+ var componentPtsSeconds = readSpliceTime(r, ptsAdjustmentTicks);
5106
+ if (ptsSeconds === void 0) {
5107
+ ptsSeconds = componentPtsSeconds;
5108
+ }
5109
+ }
5110
+ }
5111
+ }
5112
+ if (durationFlag) {
5113
+ r.readBits(6);
5114
+ r.readBits(1);
5115
+ var high = r.readBits(1);
5116
+ var low = r.readBits(32);
5117
+ var durationTicks = high * 4294967296 + low;
5118
+ durationSeconds = durationTicks / 9e4;
5119
+ }
5120
+ r.readBits(16);
5121
+ r.readBits(8);
5122
+ r.readBits(8);
5123
+ } else if (spliceCommandType === 6) {
5124
+ ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);
5125
+ } else {
4436
5126
  return void 0;
4437
5127
  }
4438
- r.readBits(32);
4439
- var cancel = r.readBits(1) === 1;
4440
- r.readBits(7);
4441
- if (cancel) return void 0;
4442
- var outOfNetwork = r.readBits(1) === 1;
4443
- var programSpliceFlag = r.readBits(1) === 1;
4444
- var durationFlag = r.readBits(1) === 1;
4445
- var spliceImmediateFlag = r.readBits(1) === 1;
4446
- r.readBits(4);
4447
- if (programSpliceFlag && !spliceImmediateFlag) {
4448
- var timeSpecifiedFlag = r.readBits(1) === 1;
4449
- if (timeSpecifiedFlag) {
4450
- r.readBits(6);
4451
- r.readBits(33);
4452
- } else {
4453
- r.readBits(7);
4454
- }
4455
- } else if (!programSpliceFlag) {
4456
- var componentCount = r.readBits(8);
4457
- for(var i = 0; i < componentCount; i++){
4458
- r.readBits(8);
4459
- if (!spliceImmediateFlag) {
4460
- var timeSpecifiedFlag1 = r.readBits(1) === 1;
4461
- if (timeSpecifiedFlag1) {
4462
- r.readBits(6);
4463
- r.readBits(33);
4464
- } else {
4465
- r.readBits(7);
4466
- }
5128
+ var expectedDescriptorOffset = spliceCommandLength === 4095 ? r.bytePosition : commandBodyStart + spliceCommandLength;
5129
+ var descriptorMarker = this.parseScte35SegmentationDescriptors(data, expectedDescriptorOffset);
5130
+ if (descriptorMarker) {
5131
+ markerType = descriptorMarker.type;
5132
+ if (durationSeconds === void 0) {
5133
+ durationSeconds = descriptorMarker.durationSeconds;
5134
+ }
5135
+ }
5136
+ if (!markerType) {
5137
+ return void 0;
5138
+ }
5139
+ var marker = _object_spread_props(_object_spread({
5140
+ type: markerType
5141
+ }, ptsSeconds !== void 0 ? {
5142
+ ptsSeconds: ptsSeconds
5143
+ } : {}, durationSeconds !== void 0 ? {
5144
+ durationSeconds: durationSeconds
5145
+ } : {}), {
5146
+ raw: _object_spread({
5147
+ splice_command_type: spliceCommandType
5148
+ }, spliceEventId !== void 0 ? {
5149
+ splice_event_id: spliceEventId
5150
+ } : {}, (descriptorMarker === null || descriptorMarker === void 0 ? void 0 : descriptorMarker.segmentationEventId) !== void 0 ? {
5151
+ segmentation_event_id: descriptorMarker.segmentationEventId
5152
+ } : {})
5153
+ });
5154
+ return marker;
5155
+ }
5156
+ },
5157
+ {
5158
+ key: "parseScte35SegmentationDescriptors",
5159
+ value: function parseScte35SegmentationDescriptors(data, offset) {
5160
+ var _data_offset, _data_;
5161
+ if (offset + 2 > data.length) {
5162
+ return void 0;
5163
+ }
5164
+ var descriptorLoopLength = ((_data_offset = data[offset]) !== null && _data_offset !== void 0 ? _data_offset : 0) << 8 | ((_data_ = data[offset + 1]) !== null && _data_ !== void 0 ? _data_ : 0);
5165
+ var descriptorOffset = offset + 2;
5166
+ var descriptorEnd = Math.min(data.length, descriptorOffset + descriptorLoopLength);
5167
+ while(descriptorOffset + 2 <= descriptorEnd){
5168
+ var _data_descriptorOffset, _data_1;
5169
+ var descriptorTag = (_data_descriptorOffset = data[descriptorOffset]) !== null && _data_descriptorOffset !== void 0 ? _data_descriptorOffset : 0;
5170
+ var descriptorLength = (_data_1 = data[descriptorOffset + 1]) !== null && _data_1 !== void 0 ? _data_1 : 0;
5171
+ var descriptorDataStart = descriptorOffset + 2;
5172
+ var descriptorDataEnd = descriptorDataStart + descriptorLength;
5173
+ if (descriptorDataEnd > descriptorEnd) {
5174
+ return void 0;
5175
+ }
5176
+ if (descriptorTag === 2) {
5177
+ var descriptorMarker = this.parseScte35SegmentationDescriptor(data.subarray(descriptorDataStart, descriptorDataEnd));
5178
+ if (descriptorMarker) {
5179
+ return descriptorMarker;
4467
5180
  }
4468
5181
  }
5182
+ descriptorOffset = descriptorDataEnd;
5183
+ }
5184
+ return void 0;
5185
+ }
5186
+ },
5187
+ {
5188
+ key: "parseScte35SegmentationDescriptor",
5189
+ value: function parseScte35SegmentationDescriptor(descriptor) {
5190
+ var _descriptor_, _descriptor_1, _descriptor_2, _descriptor_3, _descriptor_4, _descriptor_5, _descriptor_6, _descriptor_7, _descriptor_8, _descriptor_9, _descriptor_offset, _descriptor_offset1;
5191
+ if (descriptor.length < 11) {
5192
+ return void 0;
5193
+ }
5194
+ var identifier = String.fromCharCode((_descriptor_ = descriptor[0]) !== null && _descriptor_ !== void 0 ? _descriptor_ : 0, (_descriptor_1 = descriptor[1]) !== null && _descriptor_1 !== void 0 ? _descriptor_1 : 0, (_descriptor_2 = descriptor[2]) !== null && _descriptor_2 !== void 0 ? _descriptor_2 : 0, (_descriptor_3 = descriptor[3]) !== null && _descriptor_3 !== void 0 ? _descriptor_3 : 0);
5195
+ if (identifier !== "CUEI") {
5196
+ return void 0;
5197
+ }
5198
+ var segmentationEventId = ((_descriptor_4 = descriptor[4]) !== null && _descriptor_4 !== void 0 ? _descriptor_4 : 0) * 16777216 + (((_descriptor_5 = descriptor[5]) !== null && _descriptor_5 !== void 0 ? _descriptor_5 : 0) << 16) + (((_descriptor_6 = descriptor[6]) !== null && _descriptor_6 !== void 0 ? _descriptor_6 : 0) << 8) + ((_descriptor_7 = descriptor[7]) !== null && _descriptor_7 !== void 0 ? _descriptor_7 : 0);
5199
+ var cancelIndicator = (((_descriptor_8 = descriptor[8]) !== null && _descriptor_8 !== void 0 ? _descriptor_8 : 0) & 128) !== 0;
5200
+ if (cancelIndicator) {
5201
+ return void 0;
5202
+ }
5203
+ var flags = (_descriptor_9 = descriptor[9]) !== null && _descriptor_9 !== void 0 ? _descriptor_9 : 0;
5204
+ var programSegmentationFlag = (flags & 128) !== 0;
5205
+ var segmentationDurationFlag = (flags & 64) !== 0;
5206
+ var offset = 10;
5207
+ if (!programSegmentationFlag) {
5208
+ var _descriptor_offset2;
5209
+ var componentCount = (_descriptor_offset2 = descriptor[offset]) !== null && _descriptor_offset2 !== void 0 ? _descriptor_offset2 : 0;
5210
+ offset += 1 + componentCount * 6;
5211
+ if (offset > descriptor.length) {
5212
+ return void 0;
5213
+ }
4469
5214
  }
4470
5215
  var durationSeconds = void 0;
4471
- if (durationFlag) {
4472
- r.readBits(6);
4473
- r.readBits(1);
4474
- var high = r.readBits(1);
4475
- var low = r.readBits(32);
4476
- var durationTicks = high * 4294967296 + low;
5216
+ if (segmentationDurationFlag) {
5217
+ var _descriptor_offset3, _descriptor_10, _descriptor_11, _descriptor_12, _descriptor_13;
5218
+ if (offset + 5 > descriptor.length) {
5219
+ return void 0;
5220
+ }
5221
+ var durationTicks = ((_descriptor_offset3 = descriptor[offset]) !== null && _descriptor_offset3 !== void 0 ? _descriptor_offset3 : 0) * 4294967296 + ((_descriptor_10 = descriptor[offset + 1]) !== null && _descriptor_10 !== void 0 ? _descriptor_10 : 0) * 16777216 + (((_descriptor_11 = descriptor[offset + 2]) !== null && _descriptor_11 !== void 0 ? _descriptor_11 : 0) << 16) + (((_descriptor_12 = descriptor[offset + 3]) !== null && _descriptor_12 !== void 0 ? _descriptor_12 : 0) << 8) + ((_descriptor_13 = descriptor[offset + 4]) !== null && _descriptor_13 !== void 0 ? _descriptor_13 : 0);
4477
5222
  durationSeconds = durationTicks / 9e4;
5223
+ offset += 5;
4478
5224
  }
4479
- r.readBits(16);
4480
- r.readBits(8);
4481
- r.readBits(8);
4482
- if (outOfNetwork) {
4483
- var marker = _object_spread_props(_object_spread({
4484
- type: "start"
4485
- }, durationSeconds !== void 0 ? {
4486
- durationSeconds: durationSeconds
4487
- } : {}), {
4488
- raw: {
4489
- splice_command_type: 5
4490
- }
4491
- });
4492
- return marker;
5225
+ if (offset + 2 > descriptor.length) {
5226
+ return void 0;
5227
+ }
5228
+ offset += 1;
5229
+ var segmentationUpidLength = (_descriptor_offset = descriptor[offset]) !== null && _descriptor_offset !== void 0 ? _descriptor_offset : 0;
5230
+ offset += 1 + segmentationUpidLength;
5231
+ if (offset >= descriptor.length) {
5232
+ return void 0;
5233
+ }
5234
+ var segmentationTypeId = (_descriptor_offset1 = descriptor[offset]) !== null && _descriptor_offset1 !== void 0 ? _descriptor_offset1 : 0;
5235
+ var markerType = this.markerTypeFromSegmentationTypeId(segmentationTypeId);
5236
+ if (!markerType) {
5237
+ return void 0;
5238
+ }
5239
+ return _object_spread_props(_object_spread({
5240
+ type: markerType
5241
+ }, durationSeconds !== void 0 ? {
5242
+ durationSeconds: durationSeconds
5243
+ } : {}), {
5244
+ segmentationEventId: segmentationEventId
5245
+ });
5246
+ }
5247
+ },
5248
+ {
5249
+ key: "markerTypeFromSegmentationTypeId",
5250
+ value: function markerTypeFromSegmentationTypeId(segmentationTypeId) {
5251
+ switch(segmentationTypeId){
5252
+ case 16:
5253
+ case 34:
5254
+ case 48:
5255
+ case 50:
5256
+ case 52:
5257
+ case 54:
5258
+ return "start";
5259
+ case 17:
5260
+ case 35:
5261
+ case 49:
5262
+ case 51:
5263
+ case 53:
5264
+ case 55:
5265
+ return "end";
5266
+ default:
5267
+ return void 0;
4493
5268
  }
4494
- return void 0;
4495
5269
  }
4496
5270
  },
4497
5271
  {
@@ -4888,7 +5662,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4888
5662
  },
4889
5663
  {
4890
5664
  key: "startAdPrefetch",
4891
- value: function startAdPrefetch(marker, fragmentSn) {
5665
+ value: function startAdPrefetch(marker, fragmentSn, cueKey) {
4892
5666
  if (this.pendingAdBreak || this.inAdBreak) {
4893
5667
  return;
4894
5668
  }
@@ -4916,6 +5690,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4916
5690
  isFetching: false,
4917
5691
  fetchStartTime: Date.now()
4918
5692
  });
5693
+ this.pendingScte35CueKey = cueKey;
4919
5694
  this.adDetectSentForCurrentBreak = true;
4920
5695
  var detectPayload = {};
4921
5696
  if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;
@@ -4937,6 +5712,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4937
5712
  this.prefetchTimerId = void 0;
4938
5713
  }
4939
5714
  this.pendingAdBreak = null;
5715
+ this.pendingScte35CueKey = void 0;
4940
5716
  }
4941
5717
  },
4942
5718
  {
@@ -6420,18 +7196,17 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6420
7196
  key: "scheduleAdStartIn",
6421
7197
  value: function scheduleAdStartIn(delayMs) {
6422
7198
  var _this = this;
7199
+ var marker = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {
7200
+ type: "start"
7201
+ }, cueKey = arguments.length > 2 ? arguments[2] : void 0;
6423
7202
  this.clearAdStartTimer();
6424
7203
  var ms = Math.max(0, Math.floor(delayMs));
6425
7204
  if (ms === 0) {
6426
- this.handleAdStart({
6427
- type: "start"
6428
- }).catch(function() {});
7205
+ this.startScte35AdBreak(marker, cueKey, marker.durationSeconds != null ? marker.durationSeconds * 1e3 : void 0);
6429
7206
  return;
6430
7207
  }
6431
7208
  this.adStartTimerId = window.setTimeout(function() {
6432
- _this.handleAdStart({
6433
- type: "start"
6434
- }).catch(function() {});
7209
+ _this.startScte35AdBreak(marker, cueKey, marker.durationSeconds != null ? marker.durationSeconds * 1e3 : _this.expectedAdBreakDurationMs);
6435
7210
  }, ms);
6436
7211
  }
6437
7212
  },
@@ -6862,6 +7637,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6862
7637
  this.adRequestQueue = [];
6863
7638
  this.inAdBreak = false;
6864
7639
  this.adDetectSentForCurrentBreak = false;
7640
+ this.activeScte35BreakKey = void 0;
7641
+ this.scheduledScte35BreakKey = void 0;
6865
7642
  this.expectedAdBreakDurationMs = void 0;
6866
7643
  this.currentAdBreakStartWallClockMs = void 0;
6867
7644
  this.clearAdStartTimer();