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.
@@ -1747,6 +1747,16 @@ function createHlsAdPlayer(contentVideo, options) {
1747
1747
  });
1748
1748
  return bestMatch.file;
1749
1749
  }
1750
+ function isHlsMediaFile(mediaFile) {
1751
+ var type = mediaFile.type.toLowerCase();
1752
+ var url = mediaFile.url.toLowerCase();
1753
+ return type === "application/x-mpegurl" || type === "application/vnd.apple.mpegurl" || type.includes("mpegurl") || url.includes(".m3u8");
1754
+ }
1755
+ function isProgressiveMediaFile(mediaFile) {
1756
+ var type = mediaFile.type.toLowerCase();
1757
+ var url = mediaFile.url.toLowerCase();
1758
+ return type.startsWith("video/") || url.endsWith(".mp4") || url.includes(".mp4?");
1759
+ }
1750
1760
  function parseVastXml(xmlString) {
1751
1761
  try {
1752
1762
  var _xmlDoc_querySelector, _xmlDoc_querySelector1, _xmlDoc_querySelector_textContent, _xmlDoc_querySelector2;
@@ -1778,30 +1788,32 @@ function createHlsAdPlayer(contentVideo, options) {
1778
1788
  var width = mf.getAttribute("width") || "";
1779
1789
  var height = mf.getAttribute("height") || "";
1780
1790
  console.log("[HlsAdPlayer] MediaFile ".concat(index, ': type="').concat(type, '", url="').concat(url, '", width="').concat(width, '", height="').concat(height, '"'));
1781
- if (type === "application/x-mpegURL" || type.includes("m3u8")) {
1782
- if (!url) {
1783
- console.warn("[HlsAdPlayer] MediaFile ".concat(index, " has HLS type but empty URL"));
1784
- return;
1785
- }
1786
- var bitrateAttr = mf.getAttribute("bitrate");
1787
- var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
1788
- mediaFiles.push({
1789
- url: url,
1790
- type: type,
1791
- width: parseInt(width || "1920", 10),
1792
- height: parseInt(height || "1080", 10),
1793
- bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
1794
- });
1795
- console.log("[HlsAdPlayer] Added HLS MediaFile: ".concat(url));
1791
+ var mediaFile = {
1792
+ url: url,
1793
+ type: type,
1794
+ width: parseInt(width || "1920", 10),
1795
+ height: parseInt(height || "1080", 10),
1796
+ bitrate: void 0
1797
+ };
1798
+ if (!url) {
1799
+ console.warn("[HlsAdPlayer] MediaFile ".concat(index, " has empty URL"));
1800
+ return;
1801
+ }
1802
+ var bitrateAttr = mf.getAttribute("bitrate");
1803
+ var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
1804
+ mediaFile.bitrate = bitrateValue && bitrateValue > 0 ? bitrateValue : void 0;
1805
+ if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
1806
+ mediaFiles.push(mediaFile);
1807
+ console.log("[HlsAdPlayer] Added ".concat(isHlsMediaFile(mediaFile) ? "HLS" : "progressive", " MediaFile: ").concat(url));
1796
1808
  } else {
1797
- console.log("[HlsAdPlayer] MediaFile ".concat(index, ' ignored (type="').concat(type, '" is not HLS)'));
1809
+ console.log("[HlsAdPlayer] MediaFile ".concat(index, ' ignored (type="').concat(type, '" is not supported)'));
1798
1810
  }
1799
1811
  });
1800
1812
  if (mediaFiles.length === 0) {
1801
1813
  if (isNoAdAvailable) {
1802
1814
  console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
1803
1815
  } else {
1804
- console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
1816
+ console.warn("[HlsAdPlayer] No supported media files found in VAST XML");
1805
1817
  }
1806
1818
  return null;
1807
1819
  }
@@ -2098,7 +2110,7 @@ function createHlsAdPlayer(contentVideo, options) {
2098
2110
  },
2099
2111
  play: function play() {
2100
2112
  return _async_to_generator(function() {
2101
- var contentVolume, adVolume, mediaFile;
2113
+ var contentVolume, adVolume, mediaFile, isHlsAd;
2102
2114
  return _ts_generator(this, function(_state) {
2103
2115
  if (!currentAd) {
2104
2116
  console.warn("[HlsAdPlayer] Cannot play: No ad loaded (no ads available)");
@@ -2150,8 +2162,9 @@ function createHlsAdPlayer(contentVideo, options) {
2150
2162
  if (!mediaFile) {
2151
2163
  throw new Error("No media file available for ad");
2152
2164
  }
2153
- console.log("[HlsAdPlayer] Loading ad from: ".concat(mediaFile.url));
2154
- if (import_hls.default.isSupported()) {
2165
+ isHlsAd = isHlsMediaFile(mediaFile);
2166
+ console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad from: ").concat(mediaFile.url));
2167
+ if (isHlsAd && import_hls.default.isSupported()) {
2155
2168
  if (adHls) {
2156
2169
  adHls.destroy();
2157
2170
  }
@@ -2174,14 +2187,25 @@ function createHlsAdPlayer(contentVideo, options) {
2174
2187
  handleAdError();
2175
2188
  }
2176
2189
  });
2177
- } else if (adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
2190
+ } else if (isHlsAd && adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
2178
2191
  adVideoElement.src = mediaFile.url;
2179
2192
  adVideoElement.play().catch(function(error) {
2180
2193
  console.error("[HlsAdPlayer] Error starting ad playback:", error);
2181
2194
  handleAdError();
2182
2195
  });
2196
+ } else if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {
2197
+ if (adHls) {
2198
+ adHls.destroy();
2199
+ adHls = void 0;
2200
+ }
2201
+ adVideoElement.src = mediaFile.url;
2202
+ adVideoElement.load();
2203
+ adVideoElement.play().catch(function(error) {
2204
+ console.error("[HlsAdPlayer] Error starting progressive ad playback:", error);
2205
+ handleAdError();
2206
+ });
2183
2207
  } else {
2184
- throw new Error("HLS not supported");
2208
+ throw new Error("Unsupported ad media file type: ".concat(mediaFile.type));
2185
2209
  }
2186
2210
  return [
2187
2211
  2,
@@ -3262,6 +3286,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3262
3286
  this.adRequestQueue = [];
3263
3287
  this.maxPlaceholderDurationMs = 5e3;
3264
3288
  this.isShowingPlaceholder = false;
3289
+ this.tsScte35Pids = /* @__PURE__ */ new Set();
3290
+ this.pmtPids = /* @__PURE__ */ new Set();
3291
+ this.processedTsScte35Sections = /* @__PURE__ */ new Set();
3292
+ this.pendingScte35Cues = /* @__PURE__ */ new Map();
3293
+ this.recentScte35CueKeys = /* @__PURE__ */ new Map();
3294
+ this.recentScte35CueLimit = 200;
3265
3295
  this.totalAdRequestsInBreak = 0;
3266
3296
  this.maxTotalAdRequestsPerBreak = 10;
3267
3297
  this.pendingAdBreak = null;
@@ -3531,7 +3561,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3531
3561
  if (_this.config.debugAdTiming) {
3532
3562
  console.log("[StormcloudVideoPlayer] \uD83C\uDFAF EARLY SCTE-35 DETECTION: Ad break marker found in fragment", i, "- starting pre-fetch (NOT playing yet)");
3533
3563
  }
3534
- _this.startAdPrefetch(marker, frag === null || frag === void 0 ? void 0 : frag.sn);
3564
+ _this.onScte35Cue(marker, _object_spread({}, _this.createScte35CueContext("manifest", "early", frag)));
3535
3565
  return;
3536
3566
  }
3537
3567
  }
@@ -3612,10 +3642,21 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3612
3642
  return _this.onId3Tag(tag);
3613
3643
  });
3614
3644
  });
3645
+ this.hls.on(import_hls2.default.Events.FRAG_LOADED, function(_evt, data) {
3646
+ var _data_frag;
3647
+ _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));
3648
+ });
3649
+ this.hls.on(import_hls2.default.Events.FRAG_DECRYPTED, function(_evt, data) {
3650
+ var _data_frag;
3651
+ _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));
3652
+ });
3615
3653
  this.hls.on(import_hls2.default.Events.FRAG_CHANGED, function(_evt, data) {
3616
3654
  var frag = data === null || data === void 0 ? void 0 : data.frag;
3617
3655
  var tagList = frag === null || frag === void 0 ? void 0 : frag.tagList;
3618
- if (!Array.isArray(tagList)) return;
3656
+ if (!Array.isArray(tagList)) {
3657
+ _this.activatePendingScte35CuesForFragment(frag);
3658
+ return;
3659
+ }
3619
3660
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3620
3661
  try {
3621
3662
  for(var _iterator = tagList[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
@@ -3651,7 +3692,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3651
3692
  value: value
3652
3693
  }
3653
3694
  });
3654
- _this.onScte35Marker(marker);
3695
+ _this.onScte35Cue(marker, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3655
3696
  } else if (tag.includes("EXT-X-CUE-OUT")) {
3656
3697
  var durationSeconds = _this.parseCueOutDuration(value);
3657
3698
  var marker1 = _object_spread_props(_object_spread({
@@ -3664,15 +3705,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3664
3705
  value: value
3665
3706
  }
3666
3707
  });
3667
- _this.onScte35Marker(marker1);
3708
+ _this.onScte35Cue(marker1, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3668
3709
  } else if (tag.includes("EXT-X-CUE-IN")) {
3669
- _this.onScte35Marker({
3710
+ _this.onScte35Cue({
3670
3711
  type: "end",
3671
3712
  raw: {
3672
3713
  tag: tag,
3673
3714
  value: value
3674
3715
  }
3675
- });
3716
+ }, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3676
3717
  } else if (tag.includes("EXT-X-DATERANGE")) {
3677
3718
  var _attrs_CLASS;
3678
3719
  var attrs = _this.parseAttributeList(value);
@@ -3692,17 +3733,17 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3692
3733
  attrs: attrs
3693
3734
  }
3694
3735
  });
3695
- _this.onScte35Marker(marker2);
3736
+ _this.onScte35Cue(marker2, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3696
3737
  }
3697
3738
  if (hasScteIn) {
3698
- _this.onScte35Marker({
3739
+ _this.onScte35Cue({
3699
3740
  type: "end",
3700
3741
  raw: {
3701
3742
  tag: tag,
3702
3743
  value: value,
3703
3744
  attrs: attrs
3704
3745
  }
3705
- });
3746
+ }, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3706
3747
  }
3707
3748
  }
3708
3749
  }
@@ -3720,6 +3761,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3720
3761
  }
3721
3762
  }
3722
3763
  }
3764
+ _this.activatePendingScte35CuesForFragment(frag);
3723
3765
  });
3724
3766
  this.hls.on(import_hls2.default.Events.ERROR, function(_evt, data) {
3725
3767
  if (data === null || data === void 0 ? void 0 : data.fatal) {
@@ -4025,7 +4067,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4025
4067
  }
4026
4068
  var marker = this.parseScte35FromId3(tag);
4027
4069
  if (marker) {
4028
- this.onScte35Marker(marker);
4070
+ this.onScte35Cue(marker, {
4071
+ source: "id3",
4072
+ readiness: "playback"
4073
+ });
4029
4074
  }
4030
4075
  }
4031
4076
  },
@@ -4169,9 +4214,251 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4169
4214
  }
4170
4215
  }
4171
4216
  },
4217
+ {
4218
+ key: "createScte35CueContext",
4219
+ value: function createScte35CueContext(source, readiness, frag) {
4220
+ var context = {
4221
+ source: source,
4222
+ readiness: readiness
4223
+ };
4224
+ if (typeof (frag === null || frag === void 0 ? void 0 : frag.sn) === "number") {
4225
+ context.fragmentSn = frag.sn;
4226
+ }
4227
+ var fragmentStartSeconds = this.getFragmentStartSeconds(frag);
4228
+ if (fragmentStartSeconds !== void 0) {
4229
+ context.fragmentStartSeconds = fragmentStartSeconds;
4230
+ }
4231
+ return context;
4232
+ }
4233
+ },
4234
+ {
4235
+ key: "getFragmentStartSeconds",
4236
+ value: function getFragmentStartSeconds(frag) {
4237
+ var candidates = [
4238
+ frag === null || frag === void 0 ? void 0 : frag.start,
4239
+ frag === null || frag === void 0 ? void 0 : frag.startPTS
4240
+ ];
4241
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
4242
+ try {
4243
+ for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
4244
+ var candidate = _step.value;
4245
+ if (typeof candidate === "number" && Number.isFinite(candidate)) {
4246
+ return candidate;
4247
+ }
4248
+ }
4249
+ } catch (err) {
4250
+ _didIteratorError = true;
4251
+ _iteratorError = err;
4252
+ } finally{
4253
+ try {
4254
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
4255
+ _iterator.return();
4256
+ }
4257
+ } finally{
4258
+ if (_didIteratorError) {
4259
+ throw _iteratorError;
4260
+ }
4261
+ }
4262
+ }
4263
+ return void 0;
4264
+ }
4265
+ },
4266
+ {
4267
+ key: "onScte35Cue",
4268
+ value: function onScte35Cue(marker, context) {
4269
+ var cue = this.createScte35Cue(marker, context);
4270
+ var pendingKey = this.getPendingScte35CueKey(cue);
4271
+ if (context.readiness === "early") {
4272
+ this.pendingScte35Cues.set(pendingKey, cue);
4273
+ this.trimRecentScte35CueMaps();
4274
+ if (marker.type === "start") {
4275
+ this.startAdPrefetch(marker, context.fragmentSn, cue.key);
4276
+ }
4277
+ return;
4278
+ }
4279
+ if (marker.type === "end" && !this.shouldAcceptScte35EndCue(cue)) {
4280
+ if (this.config.debugAdTiming) {
4281
+ console.log("[StormcloudVideoPlayer] Ignoring SCTE-35 end cue", {
4282
+ key: cue.key,
4283
+ activeScte35BreakKey: this.activeScte35BreakKey,
4284
+ inAdBreak: this.inAdBreak,
4285
+ source: cue.source
4286
+ });
4287
+ }
4288
+ return;
4289
+ }
4290
+ if (marker.type === "start" && this.hasRecentlyHandledScte35Cue(cue)) {
4291
+ if (this.config.debugAdTiming) {
4292
+ console.log("[StormcloudVideoPlayer] Ignoring duplicate SCTE-35 start cue", {
4293
+ key: cue.key,
4294
+ source: cue.source
4295
+ });
4296
+ }
4297
+ return;
4298
+ }
4299
+ this.pendingScte35Cues.delete(pendingKey);
4300
+ this.markScte35CueHandled(cue);
4301
+ this.onScte35Marker(marker, cue.key);
4302
+ }
4303
+ },
4304
+ {
4305
+ key: "createScte35Cue",
4306
+ value: function createScte35Cue(marker, context) {
4307
+ var cue = {
4308
+ marker: marker,
4309
+ source: context.source,
4310
+ readiness: context.readiness,
4311
+ key: this.getScte35CueKey(marker, context)
4312
+ };
4313
+ if (context.fragmentSn !== void 0) {
4314
+ cue.fragmentSn = context.fragmentSn;
4315
+ }
4316
+ if (context.fragmentStartSeconds !== void 0) {
4317
+ cue.fragmentStartSeconds = context.fragmentStartSeconds;
4318
+ }
4319
+ return cue;
4320
+ }
4321
+ },
4322
+ {
4323
+ key: "getScte35CueKey",
4324
+ value: function getScte35CueKey(marker, context) {
4325
+ var _raw_attrs, _raw_attrs1, _raw_attrs2;
4326
+ var raw = this.getScte35MarkerRaw(marker);
4327
+ var spliceEventId = this.toIdentityString(raw === null || raw === void 0 ? void 0 : raw.splice_event_id);
4328
+ if (spliceEventId) {
4329
+ return "splice:".concat(spliceEventId);
4330
+ }
4331
+ var segmentationEventId = this.toIdentityString(raw === null || raw === void 0 ? void 0 : raw.segmentation_event_id);
4332
+ if (segmentationEventId) {
4333
+ return "segmentation:".concat(segmentationEventId);
4334
+ }
4335
+ 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);
4336
+ if (daterangeId) {
4337
+ return "daterange:".concat(daterangeId);
4338
+ }
4339
+ 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"]);
4340
+ if (scteValue) {
4341
+ return "daterange-scte:".concat(scteValue);
4342
+ }
4343
+ if (typeof marker.ptsSeconds === "number" && Number.isFinite(marker.ptsSeconds)) {
4344
+ return "pts:".concat(Math.round(marker.ptsSeconds * 2) / 2);
4345
+ }
4346
+ if (context.fragmentSn !== void 0) {
4347
+ return "fragment:".concat(context.fragmentSn);
4348
+ }
4349
+ return "".concat(context.source, ":wallclock:").concat(Math.floor(Date.now() / 1e3));
4350
+ }
4351
+ },
4352
+ {
4353
+ key: "getPendingScte35CueKey",
4354
+ value: function getPendingScte35CueKey(cue) {
4355
+ return "".concat(cue.marker.type, ":").concat(cue.key, ":").concat(cue.fragmentSn !== void 0 ? cue.fragmentSn : "unknown");
4356
+ }
4357
+ },
4358
+ {
4359
+ key: "getScte35MarkerRaw",
4360
+ value: function getScte35MarkerRaw(marker) {
4361
+ return _type_of(marker.raw) === "object" && marker.raw !== null ? marker.raw : {};
4362
+ }
4363
+ },
4364
+ {
4365
+ key: "toIdentityString",
4366
+ value: function toIdentityString(value) {
4367
+ if (typeof value === "number" && Number.isFinite(value)) {
4368
+ return String(value);
4369
+ }
4370
+ if (typeof value === "string" && value.trim().length > 0) {
4371
+ return value.trim();
4372
+ }
4373
+ return void 0;
4374
+ }
4375
+ },
4376
+ {
4377
+ key: "isStrongScte35CueKey",
4378
+ value: function isStrongScte35CueKey(key) {
4379
+ return !!(key && (key.startsWith("splice:") || key.startsWith("segmentation:") || key.startsWith("daterange:") || key.startsWith("daterange-scte:")));
4380
+ }
4381
+ },
4382
+ {
4383
+ key: "hasRecentlyHandledScte35Cue",
4384
+ value: function hasRecentlyHandledScte35Cue(cue) {
4385
+ if (this.activeScte35BreakKey === cue.key || this.scheduledScte35BreakKey === cue.key) {
4386
+ return true;
4387
+ }
4388
+ var recentKey = "".concat(cue.marker.type, ":").concat(cue.key);
4389
+ return this.recentScte35CueKeys.has(recentKey);
4390
+ }
4391
+ },
4392
+ {
4393
+ key: "markScte35CueHandled",
4394
+ value: function markScte35CueHandled(cue) {
4395
+ this.recentScte35CueKeys.set("".concat(cue.marker.type, ":").concat(cue.key), Date.now());
4396
+ this.trimRecentScte35CueMaps();
4397
+ }
4398
+ },
4399
+ {
4400
+ key: "trimRecentScte35CueMaps",
4401
+ value: function trimRecentScte35CueMaps() {
4402
+ while(this.recentScte35CueKeys.size > this.recentScte35CueLimit){
4403
+ var firstKey = this.recentScte35CueKeys.keys().next().value;
4404
+ if (!firstKey) {
4405
+ break;
4406
+ }
4407
+ this.recentScte35CueKeys.delete(firstKey);
4408
+ }
4409
+ while(this.pendingScte35Cues.size > this.recentScte35CueLimit){
4410
+ var firstKey1 = this.pendingScte35Cues.keys().next().value;
4411
+ if (!firstKey1) {
4412
+ break;
4413
+ }
4414
+ this.pendingScte35Cues.delete(firstKey1);
4415
+ }
4416
+ }
4417
+ },
4418
+ {
4419
+ key: "shouldAcceptScte35EndCue",
4420
+ value: function shouldAcceptScte35EndCue(cue) {
4421
+ if (!this.inAdBreak) {
4422
+ return false;
4423
+ }
4424
+ if (this.isStrongScte35CueKey(this.activeScte35BreakKey) && this.isStrongScte35CueKey(cue.key) && this.activeScte35BreakKey !== cue.key) {
4425
+ return false;
4426
+ }
4427
+ return true;
4428
+ }
4429
+ },
4430
+ {
4431
+ key: "activatePendingScte35CuesForFragment",
4432
+ value: function activatePendingScte35CuesForFragment(frag) {
4433
+ var _this = this;
4434
+ var fragmentSn = typeof (frag === null || frag === void 0 ? void 0 : frag.sn) === "number" ? frag.sn : void 0;
4435
+ if (fragmentSn === void 0) {
4436
+ return;
4437
+ }
4438
+ var matchingCues = Array.from(this.pendingScte35Cues.entries()).filter(function(param) {
4439
+ var _param = _sliced_to_array(param, 2), cue = _param[1];
4440
+ return cue.fragmentSn === fragmentSn;
4441
+ });
4442
+ matchingCues.forEach(function(param) {
4443
+ var _param = _sliced_to_array(param, 2), pendingKey = _param[0], cue = _param[1];
4444
+ var _cue_fragmentStartSeconds;
4445
+ _this.pendingScte35Cues.delete(pendingKey);
4446
+ var context = {
4447
+ source: cue.source,
4448
+ readiness: "playback"
4449
+ };
4450
+ context.fragmentSn = fragmentSn;
4451
+ var fragmentStartSeconds = (_cue_fragmentStartSeconds = cue.fragmentStartSeconds) !== null && _cue_fragmentStartSeconds !== void 0 ? _cue_fragmentStartSeconds : _this.getFragmentStartSeconds(frag);
4452
+ if (fragmentStartSeconds !== void 0) {
4453
+ context.fragmentStartSeconds = fragmentStartSeconds;
4454
+ }
4455
+ _this.onScte35Cue(cue.marker, context);
4456
+ });
4457
+ }
4458
+ },
4172
4459
  {
4173
4460
  key: "onScte35Marker",
4174
- value: function onScte35Marker(marker) {
4461
+ value: function onScte35Marker(marker, cueKey) {
4175
4462
  if (this.config.debugAdTiming) {
4176
4463
  console.log("[StormcloudVideoPlayer] SCTE-35 marker detected:", {
4177
4464
  type: marker.type,
@@ -4185,13 +4472,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4185
4472
  if (marker.type === "start") {
4186
4473
  var _this_config_immediateManifestAds;
4187
4474
  var _this_pendingAdBreak;
4188
- if (!this.video.muted) {
4189
- this.video.muted = true;
4190
- this.video.volume = 0;
4191
- if (this.config.debugAdTiming) {
4192
- console.log("[StormcloudVideoPlayer] Muted video on SCTE start marker");
4193
- }
4194
- }
4195
4475
  if (this.inAdBreak) {
4196
4476
  if (marker.durationSeconds != null) {
4197
4477
  var newDurationMs = marker.durationSeconds * 1e3;
@@ -4215,10 +4495,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4215
4495
  sendAdDetectTracking(this.config.licenseKey, detectPayload).catch(function() {});
4216
4496
  }
4217
4497
  var hasPrefetchedAds = this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0;
4218
- this.inAdBreak = true;
4219
4498
  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;
4220
- this.expectedAdBreakDurationMs = durationMs;
4221
- this.currentAdBreakStartWallClockMs = Date.now();
4222
4499
  var isManifestMarker = this.isManifestBasedMarker(marker);
4223
4500
  var forceImmediate = (_this_config_immediateManifestAds = this.config.immediateManifestAds) !== null && _this_config_immediateManifestAds !== void 0 ? _this_config_immediateManifestAds : true;
4224
4501
  if (this.config.debugAdTiming) {
@@ -4234,7 +4511,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4234
4511
  console.log("[StormcloudVideoPlayer] Starting ad immediately (manifest-based)".concat(hasPrefetchedAds ? " with prefetched ads" : ""));
4235
4512
  }
4236
4513
  this.clearAdStartTimer();
4237
- this.handleAdStart(marker);
4514
+ this.startScte35AdBreak(marker, cueKey, durationMs);
4238
4515
  } else if (typeof marker.ptsSeconds === "number") {
4239
4516
  var _this_config_driftToleranceMs;
4240
4517
  var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
@@ -4254,23 +4531,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4254
4531
  if (this.config.debugAdTiming) {
4255
4532
  console.log("[StormcloudVideoPlayer] Scheduling ad start in ".concat(deltaMs, "ms"));
4256
4533
  }
4257
- this.scheduleAdStartIn(deltaMs);
4534
+ this.expectedAdBreakDurationMs = durationMs;
4535
+ this.scheduledScte35BreakKey = cueKey;
4536
+ this.scheduleAdStartIn(deltaMs, marker, cueKey);
4258
4537
  } else {
4259
4538
  if (this.config.debugAdTiming) {
4260
4539
  console.log("[StormcloudVideoPlayer] Starting ad immediately (within tolerance)");
4261
4540
  }
4262
4541
  this.clearAdStartTimer();
4263
- this.handleAdStart(marker);
4542
+ this.startScte35AdBreak(marker, cueKey, durationMs);
4264
4543
  }
4265
4544
  } else {
4266
4545
  if (this.config.debugAdTiming) {
4267
4546
  console.log("[StormcloudVideoPlayer] Starting ad immediately (fallback)");
4268
4547
  }
4269
4548
  this.clearAdStartTimer();
4270
- this.handleAdStart(marker);
4271
- }
4272
- if (this.expectedAdBreakDurationMs != null) {
4273
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
4549
+ this.startScte35AdBreak(marker, cueKey, durationMs);
4274
4550
  }
4275
4551
  return;
4276
4552
  }
@@ -4326,6 +4602,27 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4326
4602
  }
4327
4603
  }
4328
4604
  },
4605
+ {
4606
+ key: "startScte35AdBreak",
4607
+ value: function startScte35AdBreak(marker, cueKey, durationMs) {
4608
+ if (!this.video.muted) {
4609
+ this.video.muted = true;
4610
+ this.video.volume = 0;
4611
+ if (this.config.debugAdTiming) {
4612
+ console.log("[StormcloudVideoPlayer] Muted video on SCTE start marker");
4613
+ }
4614
+ }
4615
+ this.inAdBreak = true;
4616
+ this.activeScte35BreakKey = cueKey !== null && cueKey !== void 0 ? cueKey : this.pendingScte35CueKey;
4617
+ this.scheduledScte35BreakKey = void 0;
4618
+ this.expectedAdBreakDurationMs = durationMs;
4619
+ this.currentAdBreakStartWallClockMs = Date.now();
4620
+ this.handleAdStart(marker);
4621
+ if (this.expectedAdBreakDurationMs != null) {
4622
+ this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
4623
+ }
4624
+ }
4625
+ },
4329
4626
  {
4330
4627
  key: "parseCueOutDuration",
4331
4628
  value: function parseCueOutDuration(value) {
@@ -4409,6 +4706,336 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4409
4706
  return false;
4410
4707
  }
4411
4708
  },
4709
+ {
4710
+ key: "normalizeFragmentPayload",
4711
+ value: function normalizeFragmentPayload(payload) {
4712
+ if (_instanceof(payload, Uint8Array)) {
4713
+ return payload;
4714
+ }
4715
+ if (_instanceof(payload, ArrayBuffer)) {
4716
+ return new Uint8Array(payload);
4717
+ }
4718
+ if (ArrayBuffer.isView(payload)) {
4719
+ var view = payload;
4720
+ return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
4721
+ }
4722
+ return void 0;
4723
+ }
4724
+ },
4725
+ {
4726
+ key: "processFragmentScte35Payload",
4727
+ value: function processFragmentScte35Payload(payloadData, fragmentSn, fragmentStartSeconds) {
4728
+ var _this = this;
4729
+ var payload = this.normalizeFragmentPayload(payloadData);
4730
+ if (!payload) {
4731
+ return;
4732
+ }
4733
+ var markers = this.parseScte35FromTsPackets(payload);
4734
+ markers.forEach(function(marker) {
4735
+ var context = {
4736
+ source: "ts",
4737
+ readiness: "early"
4738
+ };
4739
+ if (fragmentSn !== void 0) {
4740
+ context.fragmentSn = fragmentSn;
4741
+ }
4742
+ if (fragmentStartSeconds !== void 0) {
4743
+ context.fragmentStartSeconds = fragmentStartSeconds;
4744
+ }
4745
+ _this.onScte35Cue(marker, context);
4746
+ });
4747
+ }
4748
+ },
4749
+ {
4750
+ key: "parseScte35FromTsPackets",
4751
+ value: function parseScte35FromTsPackets(data) {
4752
+ var packetInfo = this.detectTsPacketFormat(data);
4753
+ if (!packetInfo) {
4754
+ return [];
4755
+ }
4756
+ var markers = [];
4757
+ var sectionAssemblers = /* @__PURE__ */ new Map();
4758
+ for(var packetStart = packetInfo.offset; packetStart + packetInfo.packetSize <= data.length; packetStart += packetInfo.packetSize){
4759
+ var tsStart = packetStart + packetInfo.tsPayloadOffset;
4760
+ if (data[tsStart] !== 71) {
4761
+ continue;
4762
+ }
4763
+ var secondByte = data[tsStart + 1];
4764
+ var thirdByte = data[tsStart + 2];
4765
+ var fourthByte = data[tsStart + 3];
4766
+ if (secondByte == null || thirdByte == null || fourthByte == null || (secondByte & 128) !== 0) {
4767
+ continue;
4768
+ }
4769
+ var payloadUnitStart = (secondByte & 64) !== 0;
4770
+ var pid = (secondByte & 31) << 8 | thirdByte;
4771
+ var adaptationFieldControl = fourthByte >> 4 & 3;
4772
+ var hasPayload = adaptationFieldControl === 1 || adaptationFieldControl === 3;
4773
+ if (!hasPayload) {
4774
+ continue;
4775
+ }
4776
+ var payloadStart = tsStart + 4;
4777
+ if (adaptationFieldControl === 3) {
4778
+ var adaptationLength = data[payloadStart];
4779
+ if (adaptationLength == null) {
4780
+ continue;
4781
+ }
4782
+ payloadStart += 1 + adaptationLength;
4783
+ }
4784
+ var payloadEnd = Math.min(tsStart + 188, data.length);
4785
+ if (payloadStart >= payloadEnd || payloadStart >= data.length) {
4786
+ continue;
4787
+ }
4788
+ var payload = data.subarray(payloadStart, payloadEnd);
4789
+ if (pid === 0) {
4790
+ this.parsePatSection(payload, payloadUnitStart);
4791
+ } else if (this.pmtPids.has(pid)) {
4792
+ this.parsePmtSection(payload, payloadUnitStart);
4793
+ } else if (this.tsScte35Pids.has(pid)) {
4794
+ this.collectScte35SectionsFromPayload(pid, payload, payloadUnitStart, sectionAssemblers, markers);
4795
+ }
4796
+ }
4797
+ return markers;
4798
+ }
4799
+ },
4800
+ {
4801
+ key: "detectTsPacketFormat",
4802
+ value: function detectTsPacketFormat(data) {
4803
+ var packetSizes = [
4804
+ 188,
4805
+ 192,
4806
+ 204
4807
+ ];
4808
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
4809
+ try {
4810
+ for(var _iterator = packetSizes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
4811
+ var packetSize = _step.value;
4812
+ var tsPayloadOffset = packetSize === 192 ? 4 : 0;
4813
+ for(var offset = 0; offset < packetSize; offset++){
4814
+ var matchedPackets = 0;
4815
+ for(var packetStart = offset; packetStart + tsPayloadOffset < data.length && matchedPackets < 5; packetStart += packetSize){
4816
+ if (data[packetStart + tsPayloadOffset] !== 71) {
4817
+ break;
4818
+ }
4819
+ matchedPackets++;
4820
+ }
4821
+ if (matchedPackets >= 2) {
4822
+ return {
4823
+ offset: offset,
4824
+ packetSize: packetSize,
4825
+ tsPayloadOffset: tsPayloadOffset
4826
+ };
4827
+ }
4828
+ }
4829
+ }
4830
+ } catch (err) {
4831
+ _didIteratorError = true;
4832
+ _iteratorError = err;
4833
+ } finally{
4834
+ try {
4835
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
4836
+ _iterator.return();
4837
+ }
4838
+ } finally{
4839
+ if (_didIteratorError) {
4840
+ throw _iteratorError;
4841
+ }
4842
+ }
4843
+ }
4844
+ return void 0;
4845
+ }
4846
+ },
4847
+ {
4848
+ key: "parsePatSection",
4849
+ value: function parsePatSection(payload, payloadUnitStart) {
4850
+ var sectionStart = this.getPsiSectionStart(payload, payloadUnitStart);
4851
+ if (sectionStart == null || sectionStart + 8 >= payload.length) {
4852
+ return;
4853
+ }
4854
+ if (payload[sectionStart] !== 0) {
4855
+ return;
4856
+ }
4857
+ var sectionLength = this.getPsiSectionLength(payload, sectionStart);
4858
+ var sectionEnd = Math.min(payload.length, sectionStart + 3 + sectionLength);
4859
+ for(var offset = sectionStart + 8; offset + 4 <= sectionEnd - 4; offset += 4){
4860
+ var _payload_offset, _payload_, _payload_1, _payload_2;
4861
+ 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);
4862
+ 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);
4863
+ if (programNumber !== 0) {
4864
+ this.pmtPids.add(pid);
4865
+ }
4866
+ }
4867
+ }
4868
+ },
4869
+ {
4870
+ key: "parsePmtSection",
4871
+ value: function parsePmtSection(payload, payloadUnitStart) {
4872
+ var _payload_, _payload_1;
4873
+ var sectionStart = this.getPsiSectionStart(payload, payloadUnitStart);
4874
+ if (sectionStart == null || sectionStart + 12 >= payload.length) {
4875
+ return;
4876
+ }
4877
+ if (payload[sectionStart] !== 2) {
4878
+ return;
4879
+ }
4880
+ var sectionLength = this.getPsiSectionLength(payload, sectionStart);
4881
+ var sectionEnd = Math.min(payload.length, sectionStart + 3 + sectionLength);
4882
+ 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);
4883
+ var offset = sectionStart + 12 + programInfoLength;
4884
+ while(offset + 5 <= sectionEnd - 4){
4885
+ var _payload_offset, _payload_2, _payload_3, _payload_4, _payload_5;
4886
+ var streamType = (_payload_offset = payload[offset]) !== null && _payload_offset !== void 0 ? _payload_offset : 0;
4887
+ 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);
4888
+ 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);
4889
+ var descriptorStart = offset + 5;
4890
+ var descriptorEnd = Math.min(descriptorStart + esInfoLength, sectionEnd - 4);
4891
+ if (streamType === 134 || streamType === 6 && this.descriptorsIdentifyScte35(payload, descriptorStart, descriptorEnd)) {
4892
+ this.tsScte35Pids.add(elementaryPid);
4893
+ }
4894
+ offset = descriptorStart + esInfoLength;
4895
+ }
4896
+ }
4897
+ },
4898
+ {
4899
+ key: "descriptorsIdentifyScte35",
4900
+ value: function descriptorsIdentifyScte35(data, start, end) {
4901
+ var offset = start;
4902
+ while(offset + 2 <= end){
4903
+ var _data_offset, _data_, _data_descriptorStart, _data_1, _data_2, _data_3;
4904
+ var tag = (_data_offset = data[offset]) !== null && _data_offset !== void 0 ? _data_offset : 0;
4905
+ var length = (_data_ = data[offset + 1]) !== null && _data_ !== void 0 ? _data_ : 0;
4906
+ var descriptorStart = offset + 2;
4907
+ var descriptorEnd = descriptorStart + length;
4908
+ if (descriptorEnd > end) {
4909
+ return false;
4910
+ }
4911
+ 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) : "";
4912
+ if (tag === 138 || registration === "CUEI" || registration === "SCTE") {
4913
+ return true;
4914
+ }
4915
+ offset = descriptorEnd;
4916
+ }
4917
+ return false;
4918
+ }
4919
+ },
4920
+ {
4921
+ key: "collectScte35SectionsFromPayload",
4922
+ value: function collectScte35SectionsFromPayload(pid, payload, payloadUnitStart, assemblers, markers) {
4923
+ if (payload.length === 0) {
4924
+ return;
4925
+ }
4926
+ var offset = 0;
4927
+ if (payloadUnitStart) {
4928
+ var _payload_;
4929
+ var pointerField = (_payload_ = payload[0]) !== null && _payload_ !== void 0 ? _payload_ : 0;
4930
+ var previousAssembler = assemblers.get(pid);
4931
+ if (previousAssembler && pointerField > 0) {
4932
+ this.appendScte35Bytes(pid, payload.subarray(1, Math.min(1 + pointerField, payload.length)), assemblers, markers);
4933
+ }
4934
+ assemblers.delete(pid);
4935
+ offset = 1 + pointerField;
4936
+ } else {
4937
+ this.appendScte35Bytes(pid, payload, assemblers, markers);
4938
+ return;
4939
+ }
4940
+ while(offset + 3 <= payload.length){
4941
+ var tableId = payload[offset];
4942
+ if (tableId == null || tableId === 255) {
4943
+ return;
4944
+ }
4945
+ var sectionLength = this.getPsiSectionLength(payload, offset);
4946
+ var totalLength = 3 + sectionLength;
4947
+ if (sectionLength <= 0 || totalLength <= 3) {
4948
+ return;
4949
+ }
4950
+ if (offset + totalLength <= payload.length) {
4951
+ this.addScte35SectionMarker(payload.subarray(offset, offset + totalLength), markers);
4952
+ offset += totalLength;
4953
+ } else {
4954
+ assemblers.set(pid, {
4955
+ bytes: Array.from(payload.subarray(offset)),
4956
+ expectedLength: totalLength
4957
+ });
4958
+ return;
4959
+ }
4960
+ }
4961
+ }
4962
+ },
4963
+ {
4964
+ key: "appendScte35Bytes",
4965
+ value: function appendScte35Bytes(pid, bytes, assemblers, markers) {
4966
+ var assembler = assemblers.get(pid);
4967
+ if (!assembler) {
4968
+ return;
4969
+ }
4970
+ for(var i = 0; i < bytes.length && assembler.bytes.length < assembler.expectedLength; i++){
4971
+ var _bytes_i;
4972
+ assembler.bytes.push((_bytes_i = bytes[i]) !== null && _bytes_i !== void 0 ? _bytes_i : 0);
4973
+ }
4974
+ if (assembler.bytes.length >= assembler.expectedLength) {
4975
+ assemblers.delete(pid);
4976
+ this.addScte35SectionMarker(new Uint8Array(assembler.bytes), markers);
4977
+ }
4978
+ }
4979
+ },
4980
+ {
4981
+ key: "addScte35SectionMarker",
4982
+ value: function addScte35SectionMarker(section, markers) {
4983
+ if (section[0] !== 252 || this.hasProcessedTsScte35Section(section)) {
4984
+ return;
4985
+ }
4986
+ var marker = this.parseScte35Binary(section);
4987
+ if (!marker) {
4988
+ return;
4989
+ }
4990
+ marker.raw = _object_spread_props(_object_spread({}, _type_of(marker.raw) === "object" && marker.raw ? marker.raw : {}), {
4991
+ source: "ts-packet"
4992
+ });
4993
+ markers.push(marker);
4994
+ }
4995
+ },
4996
+ {
4997
+ key: "hasProcessedTsScte35Section",
4998
+ value: function hasProcessedTsScte35Section(section) {
4999
+ var checksum = 0;
5000
+ for(var i = 0; i < section.length; i++){
5001
+ var _section_i;
5002
+ checksum = checksum * 31 + ((_section_i = section[i]) !== null && _section_i !== void 0 ? _section_i : 0) >>> 0;
5003
+ }
5004
+ var key = "".concat(section.length, ":").concat(checksum);
5005
+ if (this.processedTsScte35Sections.has(key)) {
5006
+ return true;
5007
+ }
5008
+ this.processedTsScte35Sections.add(key);
5009
+ if (this.processedTsScte35Sections.size > 200) {
5010
+ var firstKey = this.processedTsScte35Sections.values().next().value;
5011
+ if (firstKey) {
5012
+ this.processedTsScte35Sections.delete(firstKey);
5013
+ }
5014
+ }
5015
+ return false;
5016
+ }
5017
+ },
5018
+ {
5019
+ key: "getPsiSectionStart",
5020
+ value: function getPsiSectionStart(payload, payloadUnitStart) {
5021
+ if (!payloadUnitStart) {
5022
+ return void 0;
5023
+ }
5024
+ var pointerField = payload[0];
5025
+ if (pointerField == null) {
5026
+ return void 0;
5027
+ }
5028
+ var sectionStart = 1 + pointerField;
5029
+ return sectionStart < payload.length ? sectionStart : void 0;
5030
+ }
5031
+ },
5032
+ {
5033
+ key: "getPsiSectionLength",
5034
+ value: function getPsiSectionLength(data, offset) {
5035
+ var _data_, _data_1;
5036
+ 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);
5037
+ }
5038
+ },
4412
5039
  {
4413
5040
  key: "parseScte35Binary",
4414
5041
  value: function parseScte35Binary(data) {
@@ -4448,10 +5075,28 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4448
5075
  value: function skipBits(n) {
4449
5076
  this.readBits(n);
4450
5077
  }
5078
+ },
5079
+ {
5080
+ key: "bytePosition",
5081
+ get: function get() {
5082
+ return this.bitPos === 0 ? this.bytePos : this.bytePos + 1;
5083
+ }
4451
5084
  }
4452
5085
  ]);
4453
5086
  return BitReader;
4454
5087
  }();
5088
+ var readSpliceTime = function readSpliceTime(r2, ptsAdjustmentTicks2) {
5089
+ var timeSpecifiedFlag = r2.readBits(1) === 1;
5090
+ if (!timeSpecifiedFlag) {
5091
+ r2.readBits(7);
5092
+ return void 0;
5093
+ }
5094
+ r2.readBits(6);
5095
+ var high = r2.readBits(1);
5096
+ var low = r2.readBits(32);
5097
+ var ptsTicks = (high * 4294967296 + low + ptsAdjustmentTicks2) % 8589934592;
5098
+ return ptsTicks / 9e4;
5099
+ };
4455
5100
  var r = new BitReader(data);
4456
5101
  var tableId = r.readBits(8);
4457
5102
  if (tableId !== 252) return void 0;
@@ -4459,77 +5104,206 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4459
5104
  r.readBits(1);
4460
5105
  r.readBits(2);
4461
5106
  var sectionLength = r.readBits(12);
5107
+ if (sectionLength <= 0 || data.length < 3 + sectionLength) {
5108
+ return void 0;
5109
+ }
4462
5110
  r.readBits(8);
4463
5111
  r.readBits(1);
4464
5112
  r.readBits(6);
4465
5113
  var ptsAdjHigh = r.readBits(1);
4466
5114
  var ptsAdjLow = r.readBits(32);
4467
- void ptsAdjHigh;
4468
- void ptsAdjLow;
5115
+ var ptsAdjustmentTicks = ptsAdjHigh * 4294967296 + ptsAdjLow;
4469
5116
  r.readBits(8);
4470
5117
  r.readBits(12);
4471
5118
  var spliceCommandLength = r.readBits(12);
4472
5119
  var spliceCommandType = r.readBits(8);
4473
- if (spliceCommandType !== 5) {
5120
+ var markerType;
5121
+ var durationSeconds = void 0;
5122
+ var ptsSeconds = void 0;
5123
+ var spliceEventId = void 0;
5124
+ var commandBodyStart = r.bytePosition;
5125
+ if (spliceCommandType === 5) {
5126
+ spliceEventId = r.readBits(32);
5127
+ var cancel = r.readBits(1) === 1;
5128
+ r.readBits(7);
5129
+ if (cancel) return void 0;
5130
+ var outOfNetwork = r.readBits(1) === 1;
5131
+ var programSpliceFlag = r.readBits(1) === 1;
5132
+ var durationFlag = r.readBits(1) === 1;
5133
+ var spliceImmediateFlag = r.readBits(1) === 1;
5134
+ r.readBits(4);
5135
+ markerType = outOfNetwork ? "start" : "end";
5136
+ if (programSpliceFlag && !spliceImmediateFlag) {
5137
+ ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);
5138
+ } else if (!programSpliceFlag) {
5139
+ var componentCount = r.readBits(8);
5140
+ for(var i = 0; i < componentCount; i++){
5141
+ r.readBits(8);
5142
+ if (!spliceImmediateFlag) {
5143
+ var componentPtsSeconds = readSpliceTime(r, ptsAdjustmentTicks);
5144
+ if (ptsSeconds === void 0) {
5145
+ ptsSeconds = componentPtsSeconds;
5146
+ }
5147
+ }
5148
+ }
5149
+ }
5150
+ if (durationFlag) {
5151
+ r.readBits(6);
5152
+ r.readBits(1);
5153
+ var high = r.readBits(1);
5154
+ var low = r.readBits(32);
5155
+ var durationTicks = high * 4294967296 + low;
5156
+ durationSeconds = durationTicks / 9e4;
5157
+ }
5158
+ r.readBits(16);
5159
+ r.readBits(8);
5160
+ r.readBits(8);
5161
+ } else if (spliceCommandType === 6) {
5162
+ ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);
5163
+ } else {
4474
5164
  return void 0;
4475
5165
  }
4476
- r.readBits(32);
4477
- var cancel = r.readBits(1) === 1;
4478
- r.readBits(7);
4479
- if (cancel) return void 0;
4480
- var outOfNetwork = r.readBits(1) === 1;
4481
- var programSpliceFlag = r.readBits(1) === 1;
4482
- var durationFlag = r.readBits(1) === 1;
4483
- var spliceImmediateFlag = r.readBits(1) === 1;
4484
- r.readBits(4);
4485
- if (programSpliceFlag && !spliceImmediateFlag) {
4486
- var timeSpecifiedFlag = r.readBits(1) === 1;
4487
- if (timeSpecifiedFlag) {
4488
- r.readBits(6);
4489
- r.readBits(33);
4490
- } else {
4491
- r.readBits(7);
4492
- }
4493
- } else if (!programSpliceFlag) {
4494
- var componentCount = r.readBits(8);
4495
- for(var i = 0; i < componentCount; i++){
4496
- r.readBits(8);
4497
- if (!spliceImmediateFlag) {
4498
- var timeSpecifiedFlag1 = r.readBits(1) === 1;
4499
- if (timeSpecifiedFlag1) {
4500
- r.readBits(6);
4501
- r.readBits(33);
4502
- } else {
4503
- r.readBits(7);
4504
- }
5166
+ var expectedDescriptorOffset = spliceCommandLength === 4095 ? r.bytePosition : commandBodyStart + spliceCommandLength;
5167
+ var descriptorMarker = this.parseScte35SegmentationDescriptors(data, expectedDescriptorOffset);
5168
+ if (descriptorMarker) {
5169
+ markerType = descriptorMarker.type;
5170
+ if (durationSeconds === void 0) {
5171
+ durationSeconds = descriptorMarker.durationSeconds;
5172
+ }
5173
+ }
5174
+ if (!markerType) {
5175
+ return void 0;
5176
+ }
5177
+ var marker = _object_spread_props(_object_spread({
5178
+ type: markerType
5179
+ }, ptsSeconds !== void 0 ? {
5180
+ ptsSeconds: ptsSeconds
5181
+ } : {}, durationSeconds !== void 0 ? {
5182
+ durationSeconds: durationSeconds
5183
+ } : {}), {
5184
+ raw: _object_spread({
5185
+ splice_command_type: spliceCommandType
5186
+ }, spliceEventId !== void 0 ? {
5187
+ splice_event_id: spliceEventId
5188
+ } : {}, (descriptorMarker === null || descriptorMarker === void 0 ? void 0 : descriptorMarker.segmentationEventId) !== void 0 ? {
5189
+ segmentation_event_id: descriptorMarker.segmentationEventId
5190
+ } : {})
5191
+ });
5192
+ return marker;
5193
+ }
5194
+ },
5195
+ {
5196
+ key: "parseScte35SegmentationDescriptors",
5197
+ value: function parseScte35SegmentationDescriptors(data, offset) {
5198
+ var _data_offset, _data_;
5199
+ if (offset + 2 > data.length) {
5200
+ return void 0;
5201
+ }
5202
+ 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);
5203
+ var descriptorOffset = offset + 2;
5204
+ var descriptorEnd = Math.min(data.length, descriptorOffset + descriptorLoopLength);
5205
+ while(descriptorOffset + 2 <= descriptorEnd){
5206
+ var _data_descriptorOffset, _data_1;
5207
+ var descriptorTag = (_data_descriptorOffset = data[descriptorOffset]) !== null && _data_descriptorOffset !== void 0 ? _data_descriptorOffset : 0;
5208
+ var descriptorLength = (_data_1 = data[descriptorOffset + 1]) !== null && _data_1 !== void 0 ? _data_1 : 0;
5209
+ var descriptorDataStart = descriptorOffset + 2;
5210
+ var descriptorDataEnd = descriptorDataStart + descriptorLength;
5211
+ if (descriptorDataEnd > descriptorEnd) {
5212
+ return void 0;
5213
+ }
5214
+ if (descriptorTag === 2) {
5215
+ var descriptorMarker = this.parseScte35SegmentationDescriptor(data.subarray(descriptorDataStart, descriptorDataEnd));
5216
+ if (descriptorMarker) {
5217
+ return descriptorMarker;
4505
5218
  }
4506
5219
  }
5220
+ descriptorOffset = descriptorDataEnd;
5221
+ }
5222
+ return void 0;
5223
+ }
5224
+ },
5225
+ {
5226
+ key: "parseScte35SegmentationDescriptor",
5227
+ value: function parseScte35SegmentationDescriptor(descriptor) {
5228
+ var _descriptor_, _descriptor_1, _descriptor_2, _descriptor_3, _descriptor_4, _descriptor_5, _descriptor_6, _descriptor_7, _descriptor_8, _descriptor_9, _descriptor_offset, _descriptor_offset1;
5229
+ if (descriptor.length < 11) {
5230
+ return void 0;
5231
+ }
5232
+ 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);
5233
+ if (identifier !== "CUEI") {
5234
+ return void 0;
5235
+ }
5236
+ 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);
5237
+ var cancelIndicator = (((_descriptor_8 = descriptor[8]) !== null && _descriptor_8 !== void 0 ? _descriptor_8 : 0) & 128) !== 0;
5238
+ if (cancelIndicator) {
5239
+ return void 0;
5240
+ }
5241
+ var flags = (_descriptor_9 = descriptor[9]) !== null && _descriptor_9 !== void 0 ? _descriptor_9 : 0;
5242
+ var programSegmentationFlag = (flags & 128) !== 0;
5243
+ var segmentationDurationFlag = (flags & 64) !== 0;
5244
+ var offset = 10;
5245
+ if (!programSegmentationFlag) {
5246
+ var _descriptor_offset2;
5247
+ var componentCount = (_descriptor_offset2 = descriptor[offset]) !== null && _descriptor_offset2 !== void 0 ? _descriptor_offset2 : 0;
5248
+ offset += 1 + componentCount * 6;
5249
+ if (offset > descriptor.length) {
5250
+ return void 0;
5251
+ }
4507
5252
  }
4508
5253
  var durationSeconds = void 0;
4509
- if (durationFlag) {
4510
- r.readBits(6);
4511
- r.readBits(1);
4512
- var high = r.readBits(1);
4513
- var low = r.readBits(32);
4514
- var durationTicks = high * 4294967296 + low;
5254
+ if (segmentationDurationFlag) {
5255
+ var _descriptor_offset3, _descriptor_10, _descriptor_11, _descriptor_12, _descriptor_13;
5256
+ if (offset + 5 > descriptor.length) {
5257
+ return void 0;
5258
+ }
5259
+ 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);
4515
5260
  durationSeconds = durationTicks / 9e4;
5261
+ offset += 5;
4516
5262
  }
4517
- r.readBits(16);
4518
- r.readBits(8);
4519
- r.readBits(8);
4520
- if (outOfNetwork) {
4521
- var marker = _object_spread_props(_object_spread({
4522
- type: "start"
4523
- }, durationSeconds !== void 0 ? {
4524
- durationSeconds: durationSeconds
4525
- } : {}), {
4526
- raw: {
4527
- splice_command_type: 5
4528
- }
4529
- });
4530
- return marker;
5263
+ if (offset + 2 > descriptor.length) {
5264
+ return void 0;
5265
+ }
5266
+ offset += 1;
5267
+ var segmentationUpidLength = (_descriptor_offset = descriptor[offset]) !== null && _descriptor_offset !== void 0 ? _descriptor_offset : 0;
5268
+ offset += 1 + segmentationUpidLength;
5269
+ if (offset >= descriptor.length) {
5270
+ return void 0;
5271
+ }
5272
+ var segmentationTypeId = (_descriptor_offset1 = descriptor[offset]) !== null && _descriptor_offset1 !== void 0 ? _descriptor_offset1 : 0;
5273
+ var markerType = this.markerTypeFromSegmentationTypeId(segmentationTypeId);
5274
+ if (!markerType) {
5275
+ return void 0;
5276
+ }
5277
+ return _object_spread_props(_object_spread({
5278
+ type: markerType
5279
+ }, durationSeconds !== void 0 ? {
5280
+ durationSeconds: durationSeconds
5281
+ } : {}), {
5282
+ segmentationEventId: segmentationEventId
5283
+ });
5284
+ }
5285
+ },
5286
+ {
5287
+ key: "markerTypeFromSegmentationTypeId",
5288
+ value: function markerTypeFromSegmentationTypeId(segmentationTypeId) {
5289
+ switch(segmentationTypeId){
5290
+ case 16:
5291
+ case 34:
5292
+ case 48:
5293
+ case 50:
5294
+ case 52:
5295
+ case 54:
5296
+ return "start";
5297
+ case 17:
5298
+ case 35:
5299
+ case 49:
5300
+ case 51:
5301
+ case 53:
5302
+ case 55:
5303
+ return "end";
5304
+ default:
5305
+ return void 0;
4531
5306
  }
4532
- return void 0;
4533
5307
  }
4534
5308
  },
4535
5309
  {
@@ -4926,7 +5700,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4926
5700
  },
4927
5701
  {
4928
5702
  key: "startAdPrefetch",
4929
- value: function startAdPrefetch(marker, fragmentSn) {
5703
+ value: function startAdPrefetch(marker, fragmentSn, cueKey) {
4930
5704
  if (this.pendingAdBreak || this.inAdBreak) {
4931
5705
  return;
4932
5706
  }
@@ -4954,6 +5728,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4954
5728
  isFetching: false,
4955
5729
  fetchStartTime: Date.now()
4956
5730
  });
5731
+ this.pendingScte35CueKey = cueKey;
4957
5732
  this.adDetectSentForCurrentBreak = true;
4958
5733
  var detectPayload = {};
4959
5734
  if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;
@@ -4975,6 +5750,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4975
5750
  this.prefetchTimerId = void 0;
4976
5751
  }
4977
5752
  this.pendingAdBreak = null;
5753
+ this.pendingScte35CueKey = void 0;
4978
5754
  }
4979
5755
  },
4980
5756
  {
@@ -6458,18 +7234,17 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6458
7234
  key: "scheduleAdStartIn",
6459
7235
  value: function scheduleAdStartIn(delayMs) {
6460
7236
  var _this = this;
7237
+ var marker = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {
7238
+ type: "start"
7239
+ }, cueKey = arguments.length > 2 ? arguments[2] : void 0;
6461
7240
  this.clearAdStartTimer();
6462
7241
  var ms = Math.max(0, Math.floor(delayMs));
6463
7242
  if (ms === 0) {
6464
- this.handleAdStart({
6465
- type: "start"
6466
- }).catch(function() {});
7243
+ this.startScte35AdBreak(marker, cueKey, marker.durationSeconds != null ? marker.durationSeconds * 1e3 : void 0);
6467
7244
  return;
6468
7245
  }
6469
7246
  this.adStartTimerId = window.setTimeout(function() {
6470
- _this.handleAdStart({
6471
- type: "start"
6472
- }).catch(function() {});
7247
+ _this.startScte35AdBreak(marker, cueKey, marker.durationSeconds != null ? marker.durationSeconds * 1e3 : _this.expectedAdBreakDurationMs);
6473
7248
  }, ms);
6474
7249
  }
6475
7250
  },
@@ -6900,6 +7675,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6900
7675
  this.adRequestQueue = [];
6901
7676
  this.inAdBreak = false;
6902
7677
  this.adDetectSentForCurrentBreak = false;
7678
+ this.activeScte35BreakKey = void 0;
7679
+ this.scheduledScte35BreakKey = void 0;
6903
7680
  this.expectedAdBreakDurationMs = void 0;
6904
7681
  this.currentAdBreakStartWallClockMs = void 0;
6905
7682
  this.clearAdStartTimer();