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.
@@ -1761,6 +1761,16 @@ function createHlsAdPlayer(contentVideo, options) {
1761
1761
  });
1762
1762
  return bestMatch.file;
1763
1763
  }
1764
+ function isHlsMediaFile(mediaFile) {
1765
+ var type = mediaFile.type.toLowerCase();
1766
+ var url = mediaFile.url.toLowerCase();
1767
+ return type === "application/x-mpegurl" || type === "application/vnd.apple.mpegurl" || type.includes("mpegurl") || url.includes(".m3u8");
1768
+ }
1769
+ function isProgressiveMediaFile(mediaFile) {
1770
+ var type = mediaFile.type.toLowerCase();
1771
+ var url = mediaFile.url.toLowerCase();
1772
+ return type.startsWith("video/") || url.endsWith(".mp4") || url.includes(".mp4?");
1773
+ }
1764
1774
  function parseVastXml(xmlString) {
1765
1775
  try {
1766
1776
  var _xmlDoc_querySelector, _xmlDoc_querySelector1, _xmlDoc_querySelector_textContent, _xmlDoc_querySelector2;
@@ -1792,30 +1802,32 @@ function createHlsAdPlayer(contentVideo, options) {
1792
1802
  var width = mf.getAttribute("width") || "";
1793
1803
  var height = mf.getAttribute("height") || "";
1794
1804
  console.log("[HlsAdPlayer] MediaFile ".concat(index, ': type="').concat(type, '", url="').concat(url, '", width="').concat(width, '", height="').concat(height, '"'));
1795
- if (type === "application/x-mpegURL" || type.includes("m3u8")) {
1796
- if (!url) {
1797
- console.warn("[HlsAdPlayer] MediaFile ".concat(index, " has HLS type but empty URL"));
1798
- return;
1799
- }
1800
- var bitrateAttr = mf.getAttribute("bitrate");
1801
- var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
1802
- mediaFiles.push({
1803
- url: url,
1804
- type: type,
1805
- width: parseInt(width || "1920", 10),
1806
- height: parseInt(height || "1080", 10),
1807
- bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
1808
- });
1809
- console.log("[HlsAdPlayer] Added HLS MediaFile: ".concat(url));
1805
+ var mediaFile = {
1806
+ url: url,
1807
+ type: type,
1808
+ width: parseInt(width || "1920", 10),
1809
+ height: parseInt(height || "1080", 10),
1810
+ bitrate: void 0
1811
+ };
1812
+ if (!url) {
1813
+ console.warn("[HlsAdPlayer] MediaFile ".concat(index, " has empty URL"));
1814
+ return;
1815
+ }
1816
+ var bitrateAttr = mf.getAttribute("bitrate");
1817
+ var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
1818
+ mediaFile.bitrate = bitrateValue && bitrateValue > 0 ? bitrateValue : void 0;
1819
+ if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
1820
+ mediaFiles.push(mediaFile);
1821
+ console.log("[HlsAdPlayer] Added ".concat(isHlsMediaFile(mediaFile) ? "HLS" : "progressive", " MediaFile: ").concat(url));
1810
1822
  } else {
1811
- console.log("[HlsAdPlayer] MediaFile ".concat(index, ' ignored (type="').concat(type, '" is not HLS)'));
1823
+ console.log("[HlsAdPlayer] MediaFile ".concat(index, ' ignored (type="').concat(type, '" is not supported)'));
1812
1824
  }
1813
1825
  });
1814
1826
  if (mediaFiles.length === 0) {
1815
1827
  if (isNoAdAvailable) {
1816
1828
  console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
1817
1829
  } else {
1818
- console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
1830
+ console.warn("[HlsAdPlayer] No supported media files found in VAST XML");
1819
1831
  }
1820
1832
  return null;
1821
1833
  }
@@ -2112,7 +2124,7 @@ function createHlsAdPlayer(contentVideo, options) {
2112
2124
  },
2113
2125
  play: function play() {
2114
2126
  return _async_to_generator(function() {
2115
- var contentVolume, adVolume, mediaFile;
2127
+ var contentVolume, adVolume, mediaFile, isHlsAd;
2116
2128
  return _ts_generator(this, function(_state) {
2117
2129
  if (!currentAd) {
2118
2130
  console.warn("[HlsAdPlayer] Cannot play: No ad loaded (no ads available)");
@@ -2164,8 +2176,9 @@ function createHlsAdPlayer(contentVideo, options) {
2164
2176
  if (!mediaFile) {
2165
2177
  throw new Error("No media file available for ad");
2166
2178
  }
2167
- console.log("[HlsAdPlayer] Loading ad from: ".concat(mediaFile.url));
2168
- if (import_hls.default.isSupported()) {
2179
+ isHlsAd = isHlsMediaFile(mediaFile);
2180
+ console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad from: ").concat(mediaFile.url));
2181
+ if (isHlsAd && import_hls.default.isSupported()) {
2169
2182
  if (adHls) {
2170
2183
  adHls.destroy();
2171
2184
  }
@@ -2188,14 +2201,25 @@ function createHlsAdPlayer(contentVideo, options) {
2188
2201
  handleAdError();
2189
2202
  }
2190
2203
  });
2191
- } else if (adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
2204
+ } else if (isHlsAd && adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
2192
2205
  adVideoElement.src = mediaFile.url;
2193
2206
  adVideoElement.play().catch(function(error) {
2194
2207
  console.error("[HlsAdPlayer] Error starting ad playback:", error);
2195
2208
  handleAdError();
2196
2209
  });
2210
+ } else if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {
2211
+ if (adHls) {
2212
+ adHls.destroy();
2213
+ adHls = void 0;
2214
+ }
2215
+ adVideoElement.src = mediaFile.url;
2216
+ adVideoElement.load();
2217
+ adVideoElement.play().catch(function(error) {
2218
+ console.error("[HlsAdPlayer] Error starting progressive ad playback:", error);
2219
+ handleAdError();
2220
+ });
2197
2221
  } else {
2198
- throw new Error("HLS not supported");
2222
+ throw new Error("Unsupported ad media file type: ".concat(mediaFile.type));
2199
2223
  }
2200
2224
  return [
2201
2225
  2,
@@ -3276,6 +3300,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3276
3300
  this.adRequestQueue = [];
3277
3301
  this.maxPlaceholderDurationMs = 5e3;
3278
3302
  this.isShowingPlaceholder = false;
3303
+ this.tsScte35Pids = /* @__PURE__ */ new Set();
3304
+ this.pmtPids = /* @__PURE__ */ new Set();
3305
+ this.processedTsScte35Sections = /* @__PURE__ */ new Set();
3306
+ this.pendingScte35Cues = /* @__PURE__ */ new Map();
3307
+ this.recentScte35CueKeys = /* @__PURE__ */ new Map();
3308
+ this.recentScte35CueLimit = 200;
3279
3309
  this.totalAdRequestsInBreak = 0;
3280
3310
  this.maxTotalAdRequestsPerBreak = 10;
3281
3311
  this.pendingAdBreak = null;
@@ -3545,7 +3575,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3545
3575
  if (_this.config.debugAdTiming) {
3546
3576
  console.log("[StormcloudVideoPlayer] \uD83C\uDFAF EARLY SCTE-35 DETECTION: Ad break marker found in fragment", i, "- starting pre-fetch (NOT playing yet)");
3547
3577
  }
3548
- _this.startAdPrefetch(marker, frag === null || frag === void 0 ? void 0 : frag.sn);
3578
+ _this.onScte35Cue(marker, _object_spread({}, _this.createScte35CueContext("manifest", "early", frag)));
3549
3579
  return;
3550
3580
  }
3551
3581
  }
@@ -3626,10 +3656,21 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3626
3656
  return _this.onId3Tag(tag);
3627
3657
  });
3628
3658
  });
3659
+ this.hls.on(import_hls2.default.Events.FRAG_LOADED, function(_evt, data) {
3660
+ var _data_frag;
3661
+ _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));
3662
+ });
3663
+ this.hls.on(import_hls2.default.Events.FRAG_DECRYPTED, function(_evt, data) {
3664
+ var _data_frag;
3665
+ _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));
3666
+ });
3629
3667
  this.hls.on(import_hls2.default.Events.FRAG_CHANGED, function(_evt, data) {
3630
3668
  var frag = data === null || data === void 0 ? void 0 : data.frag;
3631
3669
  var tagList = frag === null || frag === void 0 ? void 0 : frag.tagList;
3632
- if (!Array.isArray(tagList)) return;
3670
+ if (!Array.isArray(tagList)) {
3671
+ _this.activatePendingScte35CuesForFragment(frag);
3672
+ return;
3673
+ }
3633
3674
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3634
3675
  try {
3635
3676
  for(var _iterator = tagList[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
@@ -3665,7 +3706,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3665
3706
  value: value
3666
3707
  }
3667
3708
  });
3668
- _this.onScte35Marker(marker);
3709
+ _this.onScte35Cue(marker, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3669
3710
  } else if (tag.includes("EXT-X-CUE-OUT")) {
3670
3711
  var durationSeconds = _this.parseCueOutDuration(value);
3671
3712
  var marker1 = _object_spread_props(_object_spread({
@@ -3678,15 +3719,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3678
3719
  value: value
3679
3720
  }
3680
3721
  });
3681
- _this.onScte35Marker(marker1);
3722
+ _this.onScte35Cue(marker1, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3682
3723
  } else if (tag.includes("EXT-X-CUE-IN")) {
3683
- _this.onScte35Marker({
3724
+ _this.onScte35Cue({
3684
3725
  type: "end",
3685
3726
  raw: {
3686
3727
  tag: tag,
3687
3728
  value: value
3688
3729
  }
3689
- });
3730
+ }, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3690
3731
  } else if (tag.includes("EXT-X-DATERANGE")) {
3691
3732
  var _attrs_CLASS;
3692
3733
  var attrs = _this.parseAttributeList(value);
@@ -3706,17 +3747,17 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3706
3747
  attrs: attrs
3707
3748
  }
3708
3749
  });
3709
- _this.onScte35Marker(marker2);
3750
+ _this.onScte35Cue(marker2, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3710
3751
  }
3711
3752
  if (hasScteIn) {
3712
- _this.onScte35Marker({
3753
+ _this.onScte35Cue({
3713
3754
  type: "end",
3714
3755
  raw: {
3715
3756
  tag: tag,
3716
3757
  value: value,
3717
3758
  attrs: attrs
3718
3759
  }
3719
- });
3760
+ }, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3720
3761
  }
3721
3762
  }
3722
3763
  }
@@ -3734,6 +3775,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3734
3775
  }
3735
3776
  }
3736
3777
  }
3778
+ _this.activatePendingScte35CuesForFragment(frag);
3737
3779
  });
3738
3780
  this.hls.on(import_hls2.default.Events.ERROR, function(_evt, data) {
3739
3781
  if (data === null || data === void 0 ? void 0 : data.fatal) {
@@ -4039,7 +4081,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4039
4081
  }
4040
4082
  var marker = this.parseScte35FromId3(tag);
4041
4083
  if (marker) {
4042
- this.onScte35Marker(marker);
4084
+ this.onScte35Cue(marker, {
4085
+ source: "id3",
4086
+ readiness: "playback"
4087
+ });
4043
4088
  }
4044
4089
  }
4045
4090
  },
@@ -4183,9 +4228,251 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4183
4228
  }
4184
4229
  }
4185
4230
  },
4231
+ {
4232
+ key: "createScte35CueContext",
4233
+ value: function createScte35CueContext(source, readiness, frag) {
4234
+ var context = {
4235
+ source: source,
4236
+ readiness: readiness
4237
+ };
4238
+ if (typeof (frag === null || frag === void 0 ? void 0 : frag.sn) === "number") {
4239
+ context.fragmentSn = frag.sn;
4240
+ }
4241
+ var fragmentStartSeconds = this.getFragmentStartSeconds(frag);
4242
+ if (fragmentStartSeconds !== void 0) {
4243
+ context.fragmentStartSeconds = fragmentStartSeconds;
4244
+ }
4245
+ return context;
4246
+ }
4247
+ },
4248
+ {
4249
+ key: "getFragmentStartSeconds",
4250
+ value: function getFragmentStartSeconds(frag) {
4251
+ var candidates = [
4252
+ frag === null || frag === void 0 ? void 0 : frag.start,
4253
+ frag === null || frag === void 0 ? void 0 : frag.startPTS
4254
+ ];
4255
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
4256
+ try {
4257
+ for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
4258
+ var candidate = _step.value;
4259
+ if (typeof candidate === "number" && Number.isFinite(candidate)) {
4260
+ return candidate;
4261
+ }
4262
+ }
4263
+ } catch (err) {
4264
+ _didIteratorError = true;
4265
+ _iteratorError = err;
4266
+ } finally{
4267
+ try {
4268
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
4269
+ _iterator.return();
4270
+ }
4271
+ } finally{
4272
+ if (_didIteratorError) {
4273
+ throw _iteratorError;
4274
+ }
4275
+ }
4276
+ }
4277
+ return void 0;
4278
+ }
4279
+ },
4280
+ {
4281
+ key: "onScte35Cue",
4282
+ value: function onScte35Cue(marker, context) {
4283
+ var cue = this.createScte35Cue(marker, context);
4284
+ var pendingKey = this.getPendingScte35CueKey(cue);
4285
+ if (context.readiness === "early") {
4286
+ this.pendingScte35Cues.set(pendingKey, cue);
4287
+ this.trimRecentScte35CueMaps();
4288
+ if (marker.type === "start") {
4289
+ this.startAdPrefetch(marker, context.fragmentSn, cue.key);
4290
+ }
4291
+ return;
4292
+ }
4293
+ if (marker.type === "end" && !this.shouldAcceptScte35EndCue(cue)) {
4294
+ if (this.config.debugAdTiming) {
4295
+ console.log("[StormcloudVideoPlayer] Ignoring SCTE-35 end cue", {
4296
+ key: cue.key,
4297
+ activeScte35BreakKey: this.activeScte35BreakKey,
4298
+ inAdBreak: this.inAdBreak,
4299
+ source: cue.source
4300
+ });
4301
+ }
4302
+ return;
4303
+ }
4304
+ if (marker.type === "start" && this.hasRecentlyHandledScte35Cue(cue)) {
4305
+ if (this.config.debugAdTiming) {
4306
+ console.log("[StormcloudVideoPlayer] Ignoring duplicate SCTE-35 start cue", {
4307
+ key: cue.key,
4308
+ source: cue.source
4309
+ });
4310
+ }
4311
+ return;
4312
+ }
4313
+ this.pendingScte35Cues.delete(pendingKey);
4314
+ this.markScte35CueHandled(cue);
4315
+ this.onScte35Marker(marker, cue.key);
4316
+ }
4317
+ },
4318
+ {
4319
+ key: "createScte35Cue",
4320
+ value: function createScte35Cue(marker, context) {
4321
+ var cue = {
4322
+ marker: marker,
4323
+ source: context.source,
4324
+ readiness: context.readiness,
4325
+ key: this.getScte35CueKey(marker, context)
4326
+ };
4327
+ if (context.fragmentSn !== void 0) {
4328
+ cue.fragmentSn = context.fragmentSn;
4329
+ }
4330
+ if (context.fragmentStartSeconds !== void 0) {
4331
+ cue.fragmentStartSeconds = context.fragmentStartSeconds;
4332
+ }
4333
+ return cue;
4334
+ }
4335
+ },
4336
+ {
4337
+ key: "getScte35CueKey",
4338
+ value: function getScte35CueKey(marker, context) {
4339
+ var _raw_attrs, _raw_attrs1, _raw_attrs2;
4340
+ var raw = this.getScte35MarkerRaw(marker);
4341
+ var spliceEventId = this.toIdentityString(raw === null || raw === void 0 ? void 0 : raw.splice_event_id);
4342
+ if (spliceEventId) {
4343
+ return "splice:".concat(spliceEventId);
4344
+ }
4345
+ var segmentationEventId = this.toIdentityString(raw === null || raw === void 0 ? void 0 : raw.segmentation_event_id);
4346
+ if (segmentationEventId) {
4347
+ return "segmentation:".concat(segmentationEventId);
4348
+ }
4349
+ 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);
4350
+ if (daterangeId) {
4351
+ return "daterange:".concat(daterangeId);
4352
+ }
4353
+ 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"]);
4354
+ if (scteValue) {
4355
+ return "daterange-scte:".concat(scteValue);
4356
+ }
4357
+ if (typeof marker.ptsSeconds === "number" && Number.isFinite(marker.ptsSeconds)) {
4358
+ return "pts:".concat(Math.round(marker.ptsSeconds * 2) / 2);
4359
+ }
4360
+ if (context.fragmentSn !== void 0) {
4361
+ return "fragment:".concat(context.fragmentSn);
4362
+ }
4363
+ return "".concat(context.source, ":wallclock:").concat(Math.floor(Date.now() / 1e3));
4364
+ }
4365
+ },
4366
+ {
4367
+ key: "getPendingScte35CueKey",
4368
+ value: function getPendingScte35CueKey(cue) {
4369
+ return "".concat(cue.marker.type, ":").concat(cue.key, ":").concat(cue.fragmentSn !== void 0 ? cue.fragmentSn : "unknown");
4370
+ }
4371
+ },
4372
+ {
4373
+ key: "getScte35MarkerRaw",
4374
+ value: function getScte35MarkerRaw(marker) {
4375
+ return _type_of(marker.raw) === "object" && marker.raw !== null ? marker.raw : {};
4376
+ }
4377
+ },
4378
+ {
4379
+ key: "toIdentityString",
4380
+ value: function toIdentityString(value) {
4381
+ if (typeof value === "number" && Number.isFinite(value)) {
4382
+ return String(value);
4383
+ }
4384
+ if (typeof value === "string" && value.trim().length > 0) {
4385
+ return value.trim();
4386
+ }
4387
+ return void 0;
4388
+ }
4389
+ },
4390
+ {
4391
+ key: "isStrongScte35CueKey",
4392
+ value: function isStrongScte35CueKey(key) {
4393
+ return !!(key && (key.startsWith("splice:") || key.startsWith("segmentation:") || key.startsWith("daterange:") || key.startsWith("daterange-scte:")));
4394
+ }
4395
+ },
4396
+ {
4397
+ key: "hasRecentlyHandledScte35Cue",
4398
+ value: function hasRecentlyHandledScte35Cue(cue) {
4399
+ if (this.activeScte35BreakKey === cue.key || this.scheduledScte35BreakKey === cue.key) {
4400
+ return true;
4401
+ }
4402
+ var recentKey = "".concat(cue.marker.type, ":").concat(cue.key);
4403
+ return this.recentScte35CueKeys.has(recentKey);
4404
+ }
4405
+ },
4406
+ {
4407
+ key: "markScte35CueHandled",
4408
+ value: function markScte35CueHandled(cue) {
4409
+ this.recentScte35CueKeys.set("".concat(cue.marker.type, ":").concat(cue.key), Date.now());
4410
+ this.trimRecentScte35CueMaps();
4411
+ }
4412
+ },
4413
+ {
4414
+ key: "trimRecentScte35CueMaps",
4415
+ value: function trimRecentScte35CueMaps() {
4416
+ while(this.recentScte35CueKeys.size > this.recentScte35CueLimit){
4417
+ var firstKey = this.recentScte35CueKeys.keys().next().value;
4418
+ if (!firstKey) {
4419
+ break;
4420
+ }
4421
+ this.recentScte35CueKeys.delete(firstKey);
4422
+ }
4423
+ while(this.pendingScte35Cues.size > this.recentScte35CueLimit){
4424
+ var firstKey1 = this.pendingScte35Cues.keys().next().value;
4425
+ if (!firstKey1) {
4426
+ break;
4427
+ }
4428
+ this.pendingScte35Cues.delete(firstKey1);
4429
+ }
4430
+ }
4431
+ },
4432
+ {
4433
+ key: "shouldAcceptScte35EndCue",
4434
+ value: function shouldAcceptScte35EndCue(cue) {
4435
+ if (!this.inAdBreak) {
4436
+ return false;
4437
+ }
4438
+ if (this.isStrongScte35CueKey(this.activeScte35BreakKey) && this.isStrongScte35CueKey(cue.key) && this.activeScte35BreakKey !== cue.key) {
4439
+ return false;
4440
+ }
4441
+ return true;
4442
+ }
4443
+ },
4444
+ {
4445
+ key: "activatePendingScte35CuesForFragment",
4446
+ value: function activatePendingScte35CuesForFragment(frag) {
4447
+ var _this = this;
4448
+ var fragmentSn = typeof (frag === null || frag === void 0 ? void 0 : frag.sn) === "number" ? frag.sn : void 0;
4449
+ if (fragmentSn === void 0) {
4450
+ return;
4451
+ }
4452
+ var matchingCues = Array.from(this.pendingScte35Cues.entries()).filter(function(param) {
4453
+ var _param = _sliced_to_array(param, 2), cue = _param[1];
4454
+ return cue.fragmentSn === fragmentSn;
4455
+ });
4456
+ matchingCues.forEach(function(param) {
4457
+ var _param = _sliced_to_array(param, 2), pendingKey = _param[0], cue = _param[1];
4458
+ var _cue_fragmentStartSeconds;
4459
+ _this.pendingScte35Cues.delete(pendingKey);
4460
+ var context = {
4461
+ source: cue.source,
4462
+ readiness: "playback"
4463
+ };
4464
+ context.fragmentSn = fragmentSn;
4465
+ var fragmentStartSeconds = (_cue_fragmentStartSeconds = cue.fragmentStartSeconds) !== null && _cue_fragmentStartSeconds !== void 0 ? _cue_fragmentStartSeconds : _this.getFragmentStartSeconds(frag);
4466
+ if (fragmentStartSeconds !== void 0) {
4467
+ context.fragmentStartSeconds = fragmentStartSeconds;
4468
+ }
4469
+ _this.onScte35Cue(cue.marker, context);
4470
+ });
4471
+ }
4472
+ },
4186
4473
  {
4187
4474
  key: "onScte35Marker",
4188
- value: function onScte35Marker(marker) {
4475
+ value: function onScte35Marker(marker, cueKey) {
4189
4476
  if (this.config.debugAdTiming) {
4190
4477
  console.log("[StormcloudVideoPlayer] SCTE-35 marker detected:", {
4191
4478
  type: marker.type,
@@ -4199,13 +4486,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4199
4486
  if (marker.type === "start") {
4200
4487
  var _this_config_immediateManifestAds;
4201
4488
  var _this_pendingAdBreak;
4202
- if (!this.video.muted) {
4203
- this.video.muted = true;
4204
- this.video.volume = 0;
4205
- if (this.config.debugAdTiming) {
4206
- console.log("[StormcloudVideoPlayer] Muted video on SCTE start marker");
4207
- }
4208
- }
4209
4489
  if (this.inAdBreak) {
4210
4490
  if (marker.durationSeconds != null) {
4211
4491
  var newDurationMs = marker.durationSeconds * 1e3;
@@ -4229,10 +4509,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4229
4509
  sendAdDetectTracking(this.config.licenseKey, detectPayload).catch(function() {});
4230
4510
  }
4231
4511
  var hasPrefetchedAds = this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0;
4232
- this.inAdBreak = true;
4233
4512
  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;
4234
- this.expectedAdBreakDurationMs = durationMs;
4235
- this.currentAdBreakStartWallClockMs = Date.now();
4236
4513
  var isManifestMarker = this.isManifestBasedMarker(marker);
4237
4514
  var forceImmediate = (_this_config_immediateManifestAds = this.config.immediateManifestAds) !== null && _this_config_immediateManifestAds !== void 0 ? _this_config_immediateManifestAds : true;
4238
4515
  if (this.config.debugAdTiming) {
@@ -4248,7 +4525,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4248
4525
  console.log("[StormcloudVideoPlayer] Starting ad immediately (manifest-based)".concat(hasPrefetchedAds ? " with prefetched ads" : ""));
4249
4526
  }
4250
4527
  this.clearAdStartTimer();
4251
- this.handleAdStart(marker);
4528
+ this.startScte35AdBreak(marker, cueKey, durationMs);
4252
4529
  } else if (typeof marker.ptsSeconds === "number") {
4253
4530
  var _this_config_driftToleranceMs;
4254
4531
  var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
@@ -4268,23 +4545,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4268
4545
  if (this.config.debugAdTiming) {
4269
4546
  console.log("[StormcloudVideoPlayer] Scheduling ad start in ".concat(deltaMs, "ms"));
4270
4547
  }
4271
- this.scheduleAdStartIn(deltaMs);
4548
+ this.expectedAdBreakDurationMs = durationMs;
4549
+ this.scheduledScte35BreakKey = cueKey;
4550
+ this.scheduleAdStartIn(deltaMs, marker, cueKey);
4272
4551
  } else {
4273
4552
  if (this.config.debugAdTiming) {
4274
4553
  console.log("[StormcloudVideoPlayer] Starting ad immediately (within tolerance)");
4275
4554
  }
4276
4555
  this.clearAdStartTimer();
4277
- this.handleAdStart(marker);
4556
+ this.startScte35AdBreak(marker, cueKey, durationMs);
4278
4557
  }
4279
4558
  } else {
4280
4559
  if (this.config.debugAdTiming) {
4281
4560
  console.log("[StormcloudVideoPlayer] Starting ad immediately (fallback)");
4282
4561
  }
4283
4562
  this.clearAdStartTimer();
4284
- this.handleAdStart(marker);
4285
- }
4286
- if (this.expectedAdBreakDurationMs != null) {
4287
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
4563
+ this.startScte35AdBreak(marker, cueKey, durationMs);
4288
4564
  }
4289
4565
  return;
4290
4566
  }
@@ -4340,6 +4616,27 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4340
4616
  }
4341
4617
  }
4342
4618
  },
4619
+ {
4620
+ key: "startScte35AdBreak",
4621
+ value: function startScte35AdBreak(marker, cueKey, durationMs) {
4622
+ if (!this.video.muted) {
4623
+ this.video.muted = true;
4624
+ this.video.volume = 0;
4625
+ if (this.config.debugAdTiming) {
4626
+ console.log("[StormcloudVideoPlayer] Muted video on SCTE start marker");
4627
+ }
4628
+ }
4629
+ this.inAdBreak = true;
4630
+ this.activeScte35BreakKey = cueKey !== null && cueKey !== void 0 ? cueKey : this.pendingScte35CueKey;
4631
+ this.scheduledScte35BreakKey = void 0;
4632
+ this.expectedAdBreakDurationMs = durationMs;
4633
+ this.currentAdBreakStartWallClockMs = Date.now();
4634
+ this.handleAdStart(marker);
4635
+ if (this.expectedAdBreakDurationMs != null) {
4636
+ this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
4637
+ }
4638
+ }
4639
+ },
4343
4640
  {
4344
4641
  key: "parseCueOutDuration",
4345
4642
  value: function parseCueOutDuration(value) {
@@ -4423,6 +4720,336 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4423
4720
  return false;
4424
4721
  }
4425
4722
  },
4723
+ {
4724
+ key: "normalizeFragmentPayload",
4725
+ value: function normalizeFragmentPayload(payload) {
4726
+ if (_instanceof(payload, Uint8Array)) {
4727
+ return payload;
4728
+ }
4729
+ if (_instanceof(payload, ArrayBuffer)) {
4730
+ return new Uint8Array(payload);
4731
+ }
4732
+ if (ArrayBuffer.isView(payload)) {
4733
+ var view = payload;
4734
+ return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
4735
+ }
4736
+ return void 0;
4737
+ }
4738
+ },
4739
+ {
4740
+ key: "processFragmentScte35Payload",
4741
+ value: function processFragmentScte35Payload(payloadData, fragmentSn, fragmentStartSeconds) {
4742
+ var _this = this;
4743
+ var payload = this.normalizeFragmentPayload(payloadData);
4744
+ if (!payload) {
4745
+ return;
4746
+ }
4747
+ var markers = this.parseScte35FromTsPackets(payload);
4748
+ markers.forEach(function(marker) {
4749
+ var context = {
4750
+ source: "ts",
4751
+ readiness: "early"
4752
+ };
4753
+ if (fragmentSn !== void 0) {
4754
+ context.fragmentSn = fragmentSn;
4755
+ }
4756
+ if (fragmentStartSeconds !== void 0) {
4757
+ context.fragmentStartSeconds = fragmentStartSeconds;
4758
+ }
4759
+ _this.onScte35Cue(marker, context);
4760
+ });
4761
+ }
4762
+ },
4763
+ {
4764
+ key: "parseScte35FromTsPackets",
4765
+ value: function parseScte35FromTsPackets(data) {
4766
+ var packetInfo = this.detectTsPacketFormat(data);
4767
+ if (!packetInfo) {
4768
+ return [];
4769
+ }
4770
+ var markers = [];
4771
+ var sectionAssemblers = /* @__PURE__ */ new Map();
4772
+ for(var packetStart = packetInfo.offset; packetStart + packetInfo.packetSize <= data.length; packetStart += packetInfo.packetSize){
4773
+ var tsStart = packetStart + packetInfo.tsPayloadOffset;
4774
+ if (data[tsStart] !== 71) {
4775
+ continue;
4776
+ }
4777
+ var secondByte = data[tsStart + 1];
4778
+ var thirdByte = data[tsStart + 2];
4779
+ var fourthByte = data[tsStart + 3];
4780
+ if (secondByte == null || thirdByte == null || fourthByte == null || (secondByte & 128) !== 0) {
4781
+ continue;
4782
+ }
4783
+ var payloadUnitStart = (secondByte & 64) !== 0;
4784
+ var pid = (secondByte & 31) << 8 | thirdByte;
4785
+ var adaptationFieldControl = fourthByte >> 4 & 3;
4786
+ var hasPayload = adaptationFieldControl === 1 || adaptationFieldControl === 3;
4787
+ if (!hasPayload) {
4788
+ continue;
4789
+ }
4790
+ var payloadStart = tsStart + 4;
4791
+ if (adaptationFieldControl === 3) {
4792
+ var adaptationLength = data[payloadStart];
4793
+ if (adaptationLength == null) {
4794
+ continue;
4795
+ }
4796
+ payloadStart += 1 + adaptationLength;
4797
+ }
4798
+ var payloadEnd = Math.min(tsStart + 188, data.length);
4799
+ if (payloadStart >= payloadEnd || payloadStart >= data.length) {
4800
+ continue;
4801
+ }
4802
+ var payload = data.subarray(payloadStart, payloadEnd);
4803
+ if (pid === 0) {
4804
+ this.parsePatSection(payload, payloadUnitStart);
4805
+ } else if (this.pmtPids.has(pid)) {
4806
+ this.parsePmtSection(payload, payloadUnitStart);
4807
+ } else if (this.tsScte35Pids.has(pid)) {
4808
+ this.collectScte35SectionsFromPayload(pid, payload, payloadUnitStart, sectionAssemblers, markers);
4809
+ }
4810
+ }
4811
+ return markers;
4812
+ }
4813
+ },
4814
+ {
4815
+ key: "detectTsPacketFormat",
4816
+ value: function detectTsPacketFormat(data) {
4817
+ var packetSizes = [
4818
+ 188,
4819
+ 192,
4820
+ 204
4821
+ ];
4822
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
4823
+ try {
4824
+ for(var _iterator = packetSizes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
4825
+ var packetSize = _step.value;
4826
+ var tsPayloadOffset = packetSize === 192 ? 4 : 0;
4827
+ for(var offset = 0; offset < packetSize; offset++){
4828
+ var matchedPackets = 0;
4829
+ for(var packetStart = offset; packetStart + tsPayloadOffset < data.length && matchedPackets < 5; packetStart += packetSize){
4830
+ if (data[packetStart + tsPayloadOffset] !== 71) {
4831
+ break;
4832
+ }
4833
+ matchedPackets++;
4834
+ }
4835
+ if (matchedPackets >= 2) {
4836
+ return {
4837
+ offset: offset,
4838
+ packetSize: packetSize,
4839
+ tsPayloadOffset: tsPayloadOffset
4840
+ };
4841
+ }
4842
+ }
4843
+ }
4844
+ } catch (err) {
4845
+ _didIteratorError = true;
4846
+ _iteratorError = err;
4847
+ } finally{
4848
+ try {
4849
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
4850
+ _iterator.return();
4851
+ }
4852
+ } finally{
4853
+ if (_didIteratorError) {
4854
+ throw _iteratorError;
4855
+ }
4856
+ }
4857
+ }
4858
+ return void 0;
4859
+ }
4860
+ },
4861
+ {
4862
+ key: "parsePatSection",
4863
+ value: function parsePatSection(payload, payloadUnitStart) {
4864
+ var sectionStart = this.getPsiSectionStart(payload, payloadUnitStart);
4865
+ if (sectionStart == null || sectionStart + 8 >= payload.length) {
4866
+ return;
4867
+ }
4868
+ if (payload[sectionStart] !== 0) {
4869
+ return;
4870
+ }
4871
+ var sectionLength = this.getPsiSectionLength(payload, sectionStart);
4872
+ var sectionEnd = Math.min(payload.length, sectionStart + 3 + sectionLength);
4873
+ for(var offset = sectionStart + 8; offset + 4 <= sectionEnd - 4; offset += 4){
4874
+ var _payload_offset, _payload_, _payload_1, _payload_2;
4875
+ 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);
4876
+ 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);
4877
+ if (programNumber !== 0) {
4878
+ this.pmtPids.add(pid);
4879
+ }
4880
+ }
4881
+ }
4882
+ },
4883
+ {
4884
+ key: "parsePmtSection",
4885
+ value: function parsePmtSection(payload, payloadUnitStart) {
4886
+ var _payload_, _payload_1;
4887
+ var sectionStart = this.getPsiSectionStart(payload, payloadUnitStart);
4888
+ if (sectionStart == null || sectionStart + 12 >= payload.length) {
4889
+ return;
4890
+ }
4891
+ if (payload[sectionStart] !== 2) {
4892
+ return;
4893
+ }
4894
+ var sectionLength = this.getPsiSectionLength(payload, sectionStart);
4895
+ var sectionEnd = Math.min(payload.length, sectionStart + 3 + sectionLength);
4896
+ 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);
4897
+ var offset = sectionStart + 12 + programInfoLength;
4898
+ while(offset + 5 <= sectionEnd - 4){
4899
+ var _payload_offset, _payload_2, _payload_3, _payload_4, _payload_5;
4900
+ var streamType = (_payload_offset = payload[offset]) !== null && _payload_offset !== void 0 ? _payload_offset : 0;
4901
+ 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);
4902
+ 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);
4903
+ var descriptorStart = offset + 5;
4904
+ var descriptorEnd = Math.min(descriptorStart + esInfoLength, sectionEnd - 4);
4905
+ if (streamType === 134 || streamType === 6 && this.descriptorsIdentifyScte35(payload, descriptorStart, descriptorEnd)) {
4906
+ this.tsScte35Pids.add(elementaryPid);
4907
+ }
4908
+ offset = descriptorStart + esInfoLength;
4909
+ }
4910
+ }
4911
+ },
4912
+ {
4913
+ key: "descriptorsIdentifyScte35",
4914
+ value: function descriptorsIdentifyScte35(data, start, end) {
4915
+ var offset = start;
4916
+ while(offset + 2 <= end){
4917
+ var _data_offset, _data_, _data_descriptorStart, _data_1, _data_2, _data_3;
4918
+ var tag = (_data_offset = data[offset]) !== null && _data_offset !== void 0 ? _data_offset : 0;
4919
+ var length = (_data_ = data[offset + 1]) !== null && _data_ !== void 0 ? _data_ : 0;
4920
+ var descriptorStart = offset + 2;
4921
+ var descriptorEnd = descriptorStart + length;
4922
+ if (descriptorEnd > end) {
4923
+ return false;
4924
+ }
4925
+ 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) : "";
4926
+ if (tag === 138 || registration === "CUEI" || registration === "SCTE") {
4927
+ return true;
4928
+ }
4929
+ offset = descriptorEnd;
4930
+ }
4931
+ return false;
4932
+ }
4933
+ },
4934
+ {
4935
+ key: "collectScte35SectionsFromPayload",
4936
+ value: function collectScte35SectionsFromPayload(pid, payload, payloadUnitStart, assemblers, markers) {
4937
+ if (payload.length === 0) {
4938
+ return;
4939
+ }
4940
+ var offset = 0;
4941
+ if (payloadUnitStart) {
4942
+ var _payload_;
4943
+ var pointerField = (_payload_ = payload[0]) !== null && _payload_ !== void 0 ? _payload_ : 0;
4944
+ var previousAssembler = assemblers.get(pid);
4945
+ if (previousAssembler && pointerField > 0) {
4946
+ this.appendScte35Bytes(pid, payload.subarray(1, Math.min(1 + pointerField, payload.length)), assemblers, markers);
4947
+ }
4948
+ assemblers.delete(pid);
4949
+ offset = 1 + pointerField;
4950
+ } else {
4951
+ this.appendScte35Bytes(pid, payload, assemblers, markers);
4952
+ return;
4953
+ }
4954
+ while(offset + 3 <= payload.length){
4955
+ var tableId = payload[offset];
4956
+ if (tableId == null || tableId === 255) {
4957
+ return;
4958
+ }
4959
+ var sectionLength = this.getPsiSectionLength(payload, offset);
4960
+ var totalLength = 3 + sectionLength;
4961
+ if (sectionLength <= 0 || totalLength <= 3) {
4962
+ return;
4963
+ }
4964
+ if (offset + totalLength <= payload.length) {
4965
+ this.addScte35SectionMarker(payload.subarray(offset, offset + totalLength), markers);
4966
+ offset += totalLength;
4967
+ } else {
4968
+ assemblers.set(pid, {
4969
+ bytes: Array.from(payload.subarray(offset)),
4970
+ expectedLength: totalLength
4971
+ });
4972
+ return;
4973
+ }
4974
+ }
4975
+ }
4976
+ },
4977
+ {
4978
+ key: "appendScte35Bytes",
4979
+ value: function appendScte35Bytes(pid, bytes, assemblers, markers) {
4980
+ var assembler = assemblers.get(pid);
4981
+ if (!assembler) {
4982
+ return;
4983
+ }
4984
+ for(var i = 0; i < bytes.length && assembler.bytes.length < assembler.expectedLength; i++){
4985
+ var _bytes_i;
4986
+ assembler.bytes.push((_bytes_i = bytes[i]) !== null && _bytes_i !== void 0 ? _bytes_i : 0);
4987
+ }
4988
+ if (assembler.bytes.length >= assembler.expectedLength) {
4989
+ assemblers.delete(pid);
4990
+ this.addScte35SectionMarker(new Uint8Array(assembler.bytes), markers);
4991
+ }
4992
+ }
4993
+ },
4994
+ {
4995
+ key: "addScte35SectionMarker",
4996
+ value: function addScte35SectionMarker(section, markers) {
4997
+ if (section[0] !== 252 || this.hasProcessedTsScte35Section(section)) {
4998
+ return;
4999
+ }
5000
+ var marker = this.parseScte35Binary(section);
5001
+ if (!marker) {
5002
+ return;
5003
+ }
5004
+ marker.raw = _object_spread_props(_object_spread({}, _type_of(marker.raw) === "object" && marker.raw ? marker.raw : {}), {
5005
+ source: "ts-packet"
5006
+ });
5007
+ markers.push(marker);
5008
+ }
5009
+ },
5010
+ {
5011
+ key: "hasProcessedTsScte35Section",
5012
+ value: function hasProcessedTsScte35Section(section) {
5013
+ var checksum = 0;
5014
+ for(var i = 0; i < section.length; i++){
5015
+ var _section_i;
5016
+ checksum = checksum * 31 + ((_section_i = section[i]) !== null && _section_i !== void 0 ? _section_i : 0) >>> 0;
5017
+ }
5018
+ var key = "".concat(section.length, ":").concat(checksum);
5019
+ if (this.processedTsScte35Sections.has(key)) {
5020
+ return true;
5021
+ }
5022
+ this.processedTsScte35Sections.add(key);
5023
+ if (this.processedTsScte35Sections.size > 200) {
5024
+ var firstKey = this.processedTsScte35Sections.values().next().value;
5025
+ if (firstKey) {
5026
+ this.processedTsScte35Sections.delete(firstKey);
5027
+ }
5028
+ }
5029
+ return false;
5030
+ }
5031
+ },
5032
+ {
5033
+ key: "getPsiSectionStart",
5034
+ value: function getPsiSectionStart(payload, payloadUnitStart) {
5035
+ if (!payloadUnitStart) {
5036
+ return void 0;
5037
+ }
5038
+ var pointerField = payload[0];
5039
+ if (pointerField == null) {
5040
+ return void 0;
5041
+ }
5042
+ var sectionStart = 1 + pointerField;
5043
+ return sectionStart < payload.length ? sectionStart : void 0;
5044
+ }
5045
+ },
5046
+ {
5047
+ key: "getPsiSectionLength",
5048
+ value: function getPsiSectionLength(data, offset) {
5049
+ var _data_, _data_1;
5050
+ 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);
5051
+ }
5052
+ },
4426
5053
  {
4427
5054
  key: "parseScte35Binary",
4428
5055
  value: function parseScte35Binary(data) {
@@ -4462,10 +5089,28 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4462
5089
  value: function skipBits(n) {
4463
5090
  this.readBits(n);
4464
5091
  }
5092
+ },
5093
+ {
5094
+ key: "bytePosition",
5095
+ get: function get() {
5096
+ return this.bitPos === 0 ? this.bytePos : this.bytePos + 1;
5097
+ }
4465
5098
  }
4466
5099
  ]);
4467
5100
  return BitReader;
4468
5101
  }();
5102
+ var readSpliceTime = function readSpliceTime(r2, ptsAdjustmentTicks2) {
5103
+ var timeSpecifiedFlag = r2.readBits(1) === 1;
5104
+ if (!timeSpecifiedFlag) {
5105
+ r2.readBits(7);
5106
+ return void 0;
5107
+ }
5108
+ r2.readBits(6);
5109
+ var high = r2.readBits(1);
5110
+ var low = r2.readBits(32);
5111
+ var ptsTicks = (high * 4294967296 + low + ptsAdjustmentTicks2) % 8589934592;
5112
+ return ptsTicks / 9e4;
5113
+ };
4469
5114
  var r = new BitReader(data);
4470
5115
  var tableId = r.readBits(8);
4471
5116
  if (tableId !== 252) return void 0;
@@ -4473,77 +5118,206 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4473
5118
  r.readBits(1);
4474
5119
  r.readBits(2);
4475
5120
  var sectionLength = r.readBits(12);
5121
+ if (sectionLength <= 0 || data.length < 3 + sectionLength) {
5122
+ return void 0;
5123
+ }
4476
5124
  r.readBits(8);
4477
5125
  r.readBits(1);
4478
5126
  r.readBits(6);
4479
5127
  var ptsAdjHigh = r.readBits(1);
4480
5128
  var ptsAdjLow = r.readBits(32);
4481
- void ptsAdjHigh;
4482
- void ptsAdjLow;
5129
+ var ptsAdjustmentTicks = ptsAdjHigh * 4294967296 + ptsAdjLow;
4483
5130
  r.readBits(8);
4484
5131
  r.readBits(12);
4485
5132
  var spliceCommandLength = r.readBits(12);
4486
5133
  var spliceCommandType = r.readBits(8);
4487
- if (spliceCommandType !== 5) {
5134
+ var markerType;
5135
+ var durationSeconds = void 0;
5136
+ var ptsSeconds = void 0;
5137
+ var spliceEventId = void 0;
5138
+ var commandBodyStart = r.bytePosition;
5139
+ if (spliceCommandType === 5) {
5140
+ spliceEventId = r.readBits(32);
5141
+ var cancel = r.readBits(1) === 1;
5142
+ r.readBits(7);
5143
+ if (cancel) return void 0;
5144
+ var outOfNetwork = r.readBits(1) === 1;
5145
+ var programSpliceFlag = r.readBits(1) === 1;
5146
+ var durationFlag = r.readBits(1) === 1;
5147
+ var spliceImmediateFlag = r.readBits(1) === 1;
5148
+ r.readBits(4);
5149
+ markerType = outOfNetwork ? "start" : "end";
5150
+ if (programSpliceFlag && !spliceImmediateFlag) {
5151
+ ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);
5152
+ } else if (!programSpliceFlag) {
5153
+ var componentCount = r.readBits(8);
5154
+ for(var i = 0; i < componentCount; i++){
5155
+ r.readBits(8);
5156
+ if (!spliceImmediateFlag) {
5157
+ var componentPtsSeconds = readSpliceTime(r, ptsAdjustmentTicks);
5158
+ if (ptsSeconds === void 0) {
5159
+ ptsSeconds = componentPtsSeconds;
5160
+ }
5161
+ }
5162
+ }
5163
+ }
5164
+ if (durationFlag) {
5165
+ r.readBits(6);
5166
+ r.readBits(1);
5167
+ var high = r.readBits(1);
5168
+ var low = r.readBits(32);
5169
+ var durationTicks = high * 4294967296 + low;
5170
+ durationSeconds = durationTicks / 9e4;
5171
+ }
5172
+ r.readBits(16);
5173
+ r.readBits(8);
5174
+ r.readBits(8);
5175
+ } else if (spliceCommandType === 6) {
5176
+ ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);
5177
+ } else {
4488
5178
  return void 0;
4489
5179
  }
4490
- r.readBits(32);
4491
- var cancel = r.readBits(1) === 1;
4492
- r.readBits(7);
4493
- if (cancel) return void 0;
4494
- var outOfNetwork = r.readBits(1) === 1;
4495
- var programSpliceFlag = r.readBits(1) === 1;
4496
- var durationFlag = r.readBits(1) === 1;
4497
- var spliceImmediateFlag = r.readBits(1) === 1;
4498
- r.readBits(4);
4499
- if (programSpliceFlag && !spliceImmediateFlag) {
4500
- var timeSpecifiedFlag = r.readBits(1) === 1;
4501
- if (timeSpecifiedFlag) {
4502
- r.readBits(6);
4503
- r.readBits(33);
4504
- } else {
4505
- r.readBits(7);
4506
- }
4507
- } else if (!programSpliceFlag) {
4508
- var componentCount = r.readBits(8);
4509
- for(var i = 0; i < componentCount; i++){
4510
- r.readBits(8);
4511
- if (!spliceImmediateFlag) {
4512
- var timeSpecifiedFlag1 = r.readBits(1) === 1;
4513
- if (timeSpecifiedFlag1) {
4514
- r.readBits(6);
4515
- r.readBits(33);
4516
- } else {
4517
- r.readBits(7);
4518
- }
5180
+ var expectedDescriptorOffset = spliceCommandLength === 4095 ? r.bytePosition : commandBodyStart + spliceCommandLength;
5181
+ var descriptorMarker = this.parseScte35SegmentationDescriptors(data, expectedDescriptorOffset);
5182
+ if (descriptorMarker) {
5183
+ markerType = descriptorMarker.type;
5184
+ if (durationSeconds === void 0) {
5185
+ durationSeconds = descriptorMarker.durationSeconds;
5186
+ }
5187
+ }
5188
+ if (!markerType) {
5189
+ return void 0;
5190
+ }
5191
+ var marker = _object_spread_props(_object_spread({
5192
+ type: markerType
5193
+ }, ptsSeconds !== void 0 ? {
5194
+ ptsSeconds: ptsSeconds
5195
+ } : {}, durationSeconds !== void 0 ? {
5196
+ durationSeconds: durationSeconds
5197
+ } : {}), {
5198
+ raw: _object_spread({
5199
+ splice_command_type: spliceCommandType
5200
+ }, spliceEventId !== void 0 ? {
5201
+ splice_event_id: spliceEventId
5202
+ } : {}, (descriptorMarker === null || descriptorMarker === void 0 ? void 0 : descriptorMarker.segmentationEventId) !== void 0 ? {
5203
+ segmentation_event_id: descriptorMarker.segmentationEventId
5204
+ } : {})
5205
+ });
5206
+ return marker;
5207
+ }
5208
+ },
5209
+ {
5210
+ key: "parseScte35SegmentationDescriptors",
5211
+ value: function parseScte35SegmentationDescriptors(data, offset) {
5212
+ var _data_offset, _data_;
5213
+ if (offset + 2 > data.length) {
5214
+ return void 0;
5215
+ }
5216
+ 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);
5217
+ var descriptorOffset = offset + 2;
5218
+ var descriptorEnd = Math.min(data.length, descriptorOffset + descriptorLoopLength);
5219
+ while(descriptorOffset + 2 <= descriptorEnd){
5220
+ var _data_descriptorOffset, _data_1;
5221
+ var descriptorTag = (_data_descriptorOffset = data[descriptorOffset]) !== null && _data_descriptorOffset !== void 0 ? _data_descriptorOffset : 0;
5222
+ var descriptorLength = (_data_1 = data[descriptorOffset + 1]) !== null && _data_1 !== void 0 ? _data_1 : 0;
5223
+ var descriptorDataStart = descriptorOffset + 2;
5224
+ var descriptorDataEnd = descriptorDataStart + descriptorLength;
5225
+ if (descriptorDataEnd > descriptorEnd) {
5226
+ return void 0;
5227
+ }
5228
+ if (descriptorTag === 2) {
5229
+ var descriptorMarker = this.parseScte35SegmentationDescriptor(data.subarray(descriptorDataStart, descriptorDataEnd));
5230
+ if (descriptorMarker) {
5231
+ return descriptorMarker;
4519
5232
  }
4520
5233
  }
5234
+ descriptorOffset = descriptorDataEnd;
5235
+ }
5236
+ return void 0;
5237
+ }
5238
+ },
5239
+ {
5240
+ key: "parseScte35SegmentationDescriptor",
5241
+ value: function parseScte35SegmentationDescriptor(descriptor) {
5242
+ var _descriptor_, _descriptor_1, _descriptor_2, _descriptor_3, _descriptor_4, _descriptor_5, _descriptor_6, _descriptor_7, _descriptor_8, _descriptor_9, _descriptor_offset, _descriptor_offset1;
5243
+ if (descriptor.length < 11) {
5244
+ return void 0;
5245
+ }
5246
+ 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);
5247
+ if (identifier !== "CUEI") {
5248
+ return void 0;
5249
+ }
5250
+ 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);
5251
+ var cancelIndicator = (((_descriptor_8 = descriptor[8]) !== null && _descriptor_8 !== void 0 ? _descriptor_8 : 0) & 128) !== 0;
5252
+ if (cancelIndicator) {
5253
+ return void 0;
5254
+ }
5255
+ var flags = (_descriptor_9 = descriptor[9]) !== null && _descriptor_9 !== void 0 ? _descriptor_9 : 0;
5256
+ var programSegmentationFlag = (flags & 128) !== 0;
5257
+ var segmentationDurationFlag = (flags & 64) !== 0;
5258
+ var offset = 10;
5259
+ if (!programSegmentationFlag) {
5260
+ var _descriptor_offset2;
5261
+ var componentCount = (_descriptor_offset2 = descriptor[offset]) !== null && _descriptor_offset2 !== void 0 ? _descriptor_offset2 : 0;
5262
+ offset += 1 + componentCount * 6;
5263
+ if (offset > descriptor.length) {
5264
+ return void 0;
5265
+ }
4521
5266
  }
4522
5267
  var durationSeconds = void 0;
4523
- if (durationFlag) {
4524
- r.readBits(6);
4525
- r.readBits(1);
4526
- var high = r.readBits(1);
4527
- var low = r.readBits(32);
4528
- var durationTicks = high * 4294967296 + low;
5268
+ if (segmentationDurationFlag) {
5269
+ var _descriptor_offset3, _descriptor_10, _descriptor_11, _descriptor_12, _descriptor_13;
5270
+ if (offset + 5 > descriptor.length) {
5271
+ return void 0;
5272
+ }
5273
+ 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);
4529
5274
  durationSeconds = durationTicks / 9e4;
5275
+ offset += 5;
4530
5276
  }
4531
- r.readBits(16);
4532
- r.readBits(8);
4533
- r.readBits(8);
4534
- if (outOfNetwork) {
4535
- var marker = _object_spread_props(_object_spread({
4536
- type: "start"
4537
- }, durationSeconds !== void 0 ? {
4538
- durationSeconds: durationSeconds
4539
- } : {}), {
4540
- raw: {
4541
- splice_command_type: 5
4542
- }
4543
- });
4544
- return marker;
5277
+ if (offset + 2 > descriptor.length) {
5278
+ return void 0;
5279
+ }
5280
+ offset += 1;
5281
+ var segmentationUpidLength = (_descriptor_offset = descriptor[offset]) !== null && _descriptor_offset !== void 0 ? _descriptor_offset : 0;
5282
+ offset += 1 + segmentationUpidLength;
5283
+ if (offset >= descriptor.length) {
5284
+ return void 0;
5285
+ }
5286
+ var segmentationTypeId = (_descriptor_offset1 = descriptor[offset]) !== null && _descriptor_offset1 !== void 0 ? _descriptor_offset1 : 0;
5287
+ var markerType = this.markerTypeFromSegmentationTypeId(segmentationTypeId);
5288
+ if (!markerType) {
5289
+ return void 0;
5290
+ }
5291
+ return _object_spread_props(_object_spread({
5292
+ type: markerType
5293
+ }, durationSeconds !== void 0 ? {
5294
+ durationSeconds: durationSeconds
5295
+ } : {}), {
5296
+ segmentationEventId: segmentationEventId
5297
+ });
5298
+ }
5299
+ },
5300
+ {
5301
+ key: "markerTypeFromSegmentationTypeId",
5302
+ value: function markerTypeFromSegmentationTypeId(segmentationTypeId) {
5303
+ switch(segmentationTypeId){
5304
+ case 16:
5305
+ case 34:
5306
+ case 48:
5307
+ case 50:
5308
+ case 52:
5309
+ case 54:
5310
+ return "start";
5311
+ case 17:
5312
+ case 35:
5313
+ case 49:
5314
+ case 51:
5315
+ case 53:
5316
+ case 55:
5317
+ return "end";
5318
+ default:
5319
+ return void 0;
4545
5320
  }
4546
- return void 0;
4547
5321
  }
4548
5322
  },
4549
5323
  {
@@ -4940,7 +5714,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4940
5714
  },
4941
5715
  {
4942
5716
  key: "startAdPrefetch",
4943
- value: function startAdPrefetch(marker, fragmentSn) {
5717
+ value: function startAdPrefetch(marker, fragmentSn, cueKey) {
4944
5718
  if (this.pendingAdBreak || this.inAdBreak) {
4945
5719
  return;
4946
5720
  }
@@ -4968,6 +5742,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4968
5742
  isFetching: false,
4969
5743
  fetchStartTime: Date.now()
4970
5744
  });
5745
+ this.pendingScte35CueKey = cueKey;
4971
5746
  this.adDetectSentForCurrentBreak = true;
4972
5747
  var detectPayload = {};
4973
5748
  if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;
@@ -4989,6 +5764,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4989
5764
  this.prefetchTimerId = void 0;
4990
5765
  }
4991
5766
  this.pendingAdBreak = null;
5767
+ this.pendingScte35CueKey = void 0;
4992
5768
  }
4993
5769
  },
4994
5770
  {
@@ -6472,18 +7248,17 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6472
7248
  key: "scheduleAdStartIn",
6473
7249
  value: function scheduleAdStartIn(delayMs) {
6474
7250
  var _this = this;
7251
+ var marker = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {
7252
+ type: "start"
7253
+ }, cueKey = arguments.length > 2 ? arguments[2] : void 0;
6475
7254
  this.clearAdStartTimer();
6476
7255
  var ms = Math.max(0, Math.floor(delayMs));
6477
7256
  if (ms === 0) {
6478
- this.handleAdStart({
6479
- type: "start"
6480
- }).catch(function() {});
7257
+ this.startScte35AdBreak(marker, cueKey, marker.durationSeconds != null ? marker.durationSeconds * 1e3 : void 0);
6481
7258
  return;
6482
7259
  }
6483
7260
  this.adStartTimerId = window.setTimeout(function() {
6484
- _this.handleAdStart({
6485
- type: "start"
6486
- }).catch(function() {});
7261
+ _this.startScte35AdBreak(marker, cueKey, marker.durationSeconds != null ? marker.durationSeconds * 1e3 : _this.expectedAdBreakDurationMs);
6487
7262
  }, ms);
6488
7263
  }
6489
7264
  },
@@ -6914,6 +7689,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6914
7689
  this.adRequestQueue = [];
6915
7690
  this.inAdBreak = false;
6916
7691
  this.adDetectSentForCurrentBreak = false;
7692
+ this.activeScte35BreakKey = void 0;
7693
+ this.scheduledScte35BreakKey = void 0;
6917
7694
  this.expectedAdBreakDurationMs = void 0;
6918
7695
  this.currentAdBreakStartWallClockMs = void 0;
6919
7696
  this.clearAdStartTimer();