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.
package/lib/index.cjs CHANGED
@@ -1935,6 +1935,16 @@ function createHlsAdPlayer(contentVideo, options) {
1935
1935
  });
1936
1936
  return bestMatch.file;
1937
1937
  }
1938
+ function isHlsMediaFile(mediaFile) {
1939
+ var type = mediaFile.type.toLowerCase();
1940
+ var url = mediaFile.url.toLowerCase();
1941
+ return type === "application/x-mpegurl" || type === "application/vnd.apple.mpegurl" || type.includes("mpegurl") || url.includes(".m3u8");
1942
+ }
1943
+ function isProgressiveMediaFile(mediaFile) {
1944
+ var type = mediaFile.type.toLowerCase();
1945
+ var url = mediaFile.url.toLowerCase();
1946
+ return type.startsWith("video/") || url.endsWith(".mp4") || url.includes(".mp4?");
1947
+ }
1938
1948
  function parseVastXml(xmlString) {
1939
1949
  try {
1940
1950
  var _xmlDoc_querySelector, _xmlDoc_querySelector1, _xmlDoc_querySelector_textContent, _xmlDoc_querySelector2;
@@ -1966,30 +1976,32 @@ function createHlsAdPlayer(contentVideo, options) {
1966
1976
  var width = mf.getAttribute("width") || "";
1967
1977
  var height = mf.getAttribute("height") || "";
1968
1978
  console.log("[HlsAdPlayer] MediaFile ".concat(index, ': type="').concat(type, '", url="').concat(url, '", width="').concat(width, '", height="').concat(height, '"'));
1969
- if (type === "application/x-mpegURL" || type.includes("m3u8")) {
1970
- if (!url) {
1971
- console.warn("[HlsAdPlayer] MediaFile ".concat(index, " has HLS type but empty URL"));
1972
- return;
1973
- }
1974
- var bitrateAttr = mf.getAttribute("bitrate");
1975
- var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
1976
- mediaFiles.push({
1977
- url: url,
1978
- type: type,
1979
- width: parseInt(width || "1920", 10),
1980
- height: parseInt(height || "1080", 10),
1981
- bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
1982
- });
1983
- console.log("[HlsAdPlayer] Added HLS MediaFile: ".concat(url));
1979
+ var mediaFile = {
1980
+ url: url,
1981
+ type: type,
1982
+ width: parseInt(width || "1920", 10),
1983
+ height: parseInt(height || "1080", 10),
1984
+ bitrate: void 0
1985
+ };
1986
+ if (!url) {
1987
+ console.warn("[HlsAdPlayer] MediaFile ".concat(index, " has empty URL"));
1988
+ return;
1989
+ }
1990
+ var bitrateAttr = mf.getAttribute("bitrate");
1991
+ var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
1992
+ mediaFile.bitrate = bitrateValue && bitrateValue > 0 ? bitrateValue : void 0;
1993
+ if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
1994
+ mediaFiles.push(mediaFile);
1995
+ console.log("[HlsAdPlayer] Added ".concat(isHlsMediaFile(mediaFile) ? "HLS" : "progressive", " MediaFile: ").concat(url));
1984
1996
  } else {
1985
- console.log("[HlsAdPlayer] MediaFile ".concat(index, ' ignored (type="').concat(type, '" is not HLS)'));
1997
+ console.log("[HlsAdPlayer] MediaFile ".concat(index, ' ignored (type="').concat(type, '" is not supported)'));
1986
1998
  }
1987
1999
  });
1988
2000
  if (mediaFiles.length === 0) {
1989
2001
  if (isNoAdAvailable) {
1990
2002
  console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
1991
2003
  } else {
1992
- console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
2004
+ console.warn("[HlsAdPlayer] No supported media files found in VAST XML");
1993
2005
  }
1994
2006
  return null;
1995
2007
  }
@@ -2286,7 +2298,7 @@ function createHlsAdPlayer(contentVideo, options) {
2286
2298
  },
2287
2299
  play: function play() {
2288
2300
  return _async_to_generator(function() {
2289
- var contentVolume, adVolume, mediaFile;
2301
+ var contentVolume, adVolume, mediaFile, isHlsAd;
2290
2302
  return _ts_generator(this, function(_state) {
2291
2303
  if (!currentAd) {
2292
2304
  console.warn("[HlsAdPlayer] Cannot play: No ad loaded (no ads available)");
@@ -2338,8 +2350,9 @@ function createHlsAdPlayer(contentVideo, options) {
2338
2350
  if (!mediaFile) {
2339
2351
  throw new Error("No media file available for ad");
2340
2352
  }
2341
- console.log("[HlsAdPlayer] Loading ad from: ".concat(mediaFile.url));
2342
- if (import_hls.default.isSupported()) {
2353
+ isHlsAd = isHlsMediaFile(mediaFile);
2354
+ console.log("[HlsAdPlayer] Loading ".concat(isHlsAd ? "HLS" : "progressive", " ad from: ").concat(mediaFile.url));
2355
+ if (isHlsAd && import_hls.default.isSupported()) {
2343
2356
  if (adHls) {
2344
2357
  adHls.destroy();
2345
2358
  }
@@ -2362,14 +2375,25 @@ function createHlsAdPlayer(contentVideo, options) {
2362
2375
  handleAdError();
2363
2376
  }
2364
2377
  });
2365
- } else if (adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
2378
+ } else if (isHlsAd && adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
2366
2379
  adVideoElement.src = mediaFile.url;
2367
2380
  adVideoElement.play().catch(function(error) {
2368
2381
  console.error("[HlsAdPlayer] Error starting ad playback:", error);
2369
2382
  handleAdError();
2370
2383
  });
2384
+ } else if (!isHlsAd && isProgressiveMediaFile(mediaFile)) {
2385
+ if (adHls) {
2386
+ adHls.destroy();
2387
+ adHls = void 0;
2388
+ }
2389
+ adVideoElement.src = mediaFile.url;
2390
+ adVideoElement.load();
2391
+ adVideoElement.play().catch(function(error) {
2392
+ console.error("[HlsAdPlayer] Error starting progressive ad playback:", error);
2393
+ handleAdError();
2394
+ });
2371
2395
  } else {
2372
- throw new Error("HLS not supported");
2396
+ throw new Error("Unsupported ad media file type: ".concat(mediaFile.type));
2373
2397
  }
2374
2398
  return [
2375
2399
  2,
@@ -3450,6 +3474,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3450
3474
  this.adRequestQueue = [];
3451
3475
  this.maxPlaceholderDurationMs = 5e3;
3452
3476
  this.isShowingPlaceholder = false;
3477
+ this.tsScte35Pids = /* @__PURE__ */ new Set();
3478
+ this.pmtPids = /* @__PURE__ */ new Set();
3479
+ this.processedTsScte35Sections = /* @__PURE__ */ new Set();
3480
+ this.pendingScte35Cues = /* @__PURE__ */ new Map();
3481
+ this.recentScte35CueKeys = /* @__PURE__ */ new Map();
3482
+ this.recentScte35CueLimit = 200;
3453
3483
  this.totalAdRequestsInBreak = 0;
3454
3484
  this.maxTotalAdRequestsPerBreak = 10;
3455
3485
  this.pendingAdBreak = null;
@@ -3719,7 +3749,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3719
3749
  if (_this.config.debugAdTiming) {
3720
3750
  console.log("[StormcloudVideoPlayer] \uD83C\uDFAF EARLY SCTE-35 DETECTION: Ad break marker found in fragment", i, "- starting pre-fetch (NOT playing yet)");
3721
3751
  }
3722
- _this.startAdPrefetch(marker, frag === null || frag === void 0 ? void 0 : frag.sn);
3752
+ _this.onScte35Cue(marker, _object_spread({}, _this.createScte35CueContext("manifest", "early", frag)));
3723
3753
  return;
3724
3754
  }
3725
3755
  }
@@ -3800,10 +3830,21 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3800
3830
  return _this.onId3Tag(tag);
3801
3831
  });
3802
3832
  });
3833
+ this.hls.on(import_hls2.default.Events.FRAG_LOADED, function(_evt, data) {
3834
+ var _data_frag;
3835
+ _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));
3836
+ });
3837
+ this.hls.on(import_hls2.default.Events.FRAG_DECRYPTED, function(_evt, data) {
3838
+ var _data_frag;
3839
+ _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));
3840
+ });
3803
3841
  this.hls.on(import_hls2.default.Events.FRAG_CHANGED, function(_evt, data) {
3804
3842
  var frag = data === null || data === void 0 ? void 0 : data.frag;
3805
3843
  var tagList = frag === null || frag === void 0 ? void 0 : frag.tagList;
3806
- if (!Array.isArray(tagList)) return;
3844
+ if (!Array.isArray(tagList)) {
3845
+ _this.activatePendingScte35CuesForFragment(frag);
3846
+ return;
3847
+ }
3807
3848
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
3808
3849
  try {
3809
3850
  for(var _iterator = tagList[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
@@ -3839,7 +3880,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3839
3880
  value: value
3840
3881
  }
3841
3882
  });
3842
- _this.onScte35Marker(marker);
3883
+ _this.onScte35Cue(marker, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3843
3884
  } else if (tag.includes("EXT-X-CUE-OUT")) {
3844
3885
  var durationSeconds = _this.parseCueOutDuration(value);
3845
3886
  var marker1 = _object_spread_props(_object_spread({
@@ -3852,15 +3893,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3852
3893
  value: value
3853
3894
  }
3854
3895
  });
3855
- _this.onScte35Marker(marker1);
3896
+ _this.onScte35Cue(marker1, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3856
3897
  } else if (tag.includes("EXT-X-CUE-IN")) {
3857
- _this.onScte35Marker({
3898
+ _this.onScte35Cue({
3858
3899
  type: "end",
3859
3900
  raw: {
3860
3901
  tag: tag,
3861
3902
  value: value
3862
3903
  }
3863
- });
3904
+ }, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3864
3905
  } else if (tag.includes("EXT-X-DATERANGE")) {
3865
3906
  var _attrs_CLASS;
3866
3907
  var attrs = _this.parseAttributeList(value);
@@ -3880,17 +3921,17 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3880
3921
  attrs: attrs
3881
3922
  }
3882
3923
  });
3883
- _this.onScte35Marker(marker2);
3924
+ _this.onScte35Cue(marker2, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3884
3925
  }
3885
3926
  if (hasScteIn) {
3886
- _this.onScte35Marker({
3927
+ _this.onScte35Cue({
3887
3928
  type: "end",
3888
3929
  raw: {
3889
3930
  tag: tag,
3890
3931
  value: value,
3891
3932
  attrs: attrs
3892
3933
  }
3893
- });
3934
+ }, _object_spread({}, _this.createScte35CueContext("manifest", "playback", frag)));
3894
3935
  }
3895
3936
  }
3896
3937
  }
@@ -3908,6 +3949,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3908
3949
  }
3909
3950
  }
3910
3951
  }
3952
+ _this.activatePendingScte35CuesForFragment(frag);
3911
3953
  });
3912
3954
  this.hls.on(import_hls2.default.Events.ERROR, function(_evt, data) {
3913
3955
  if (data === null || data === void 0 ? void 0 : data.fatal) {
@@ -4213,7 +4255,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4213
4255
  }
4214
4256
  var marker = this.parseScte35FromId3(tag);
4215
4257
  if (marker) {
4216
- this.onScte35Marker(marker);
4258
+ this.onScte35Cue(marker, {
4259
+ source: "id3",
4260
+ readiness: "playback"
4261
+ });
4217
4262
  }
4218
4263
  }
4219
4264
  },
@@ -4357,9 +4402,251 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4357
4402
  }
4358
4403
  }
4359
4404
  },
4405
+ {
4406
+ key: "createScte35CueContext",
4407
+ value: function createScte35CueContext(source, readiness, frag) {
4408
+ var context = {
4409
+ source: source,
4410
+ readiness: readiness
4411
+ };
4412
+ if (typeof (frag === null || frag === void 0 ? void 0 : frag.sn) === "number") {
4413
+ context.fragmentSn = frag.sn;
4414
+ }
4415
+ var fragmentStartSeconds = this.getFragmentStartSeconds(frag);
4416
+ if (fragmentStartSeconds !== void 0) {
4417
+ context.fragmentStartSeconds = fragmentStartSeconds;
4418
+ }
4419
+ return context;
4420
+ }
4421
+ },
4422
+ {
4423
+ key: "getFragmentStartSeconds",
4424
+ value: function getFragmentStartSeconds(frag) {
4425
+ var candidates = [
4426
+ frag === null || frag === void 0 ? void 0 : frag.start,
4427
+ frag === null || frag === void 0 ? void 0 : frag.startPTS
4428
+ ];
4429
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
4430
+ try {
4431
+ for(var _iterator = candidates[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
4432
+ var candidate = _step.value;
4433
+ if (typeof candidate === "number" && Number.isFinite(candidate)) {
4434
+ return candidate;
4435
+ }
4436
+ }
4437
+ } catch (err) {
4438
+ _didIteratorError = true;
4439
+ _iteratorError = err;
4440
+ } finally{
4441
+ try {
4442
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
4443
+ _iterator.return();
4444
+ }
4445
+ } finally{
4446
+ if (_didIteratorError) {
4447
+ throw _iteratorError;
4448
+ }
4449
+ }
4450
+ }
4451
+ return void 0;
4452
+ }
4453
+ },
4454
+ {
4455
+ key: "onScte35Cue",
4456
+ value: function onScte35Cue(marker, context) {
4457
+ var cue = this.createScte35Cue(marker, context);
4458
+ var pendingKey = this.getPendingScte35CueKey(cue);
4459
+ if (context.readiness === "early") {
4460
+ this.pendingScte35Cues.set(pendingKey, cue);
4461
+ this.trimRecentScte35CueMaps();
4462
+ if (marker.type === "start") {
4463
+ this.startAdPrefetch(marker, context.fragmentSn, cue.key);
4464
+ }
4465
+ return;
4466
+ }
4467
+ if (marker.type === "end" && !this.shouldAcceptScte35EndCue(cue)) {
4468
+ if (this.config.debugAdTiming) {
4469
+ console.log("[StormcloudVideoPlayer] Ignoring SCTE-35 end cue", {
4470
+ key: cue.key,
4471
+ activeScte35BreakKey: this.activeScte35BreakKey,
4472
+ inAdBreak: this.inAdBreak,
4473
+ source: cue.source
4474
+ });
4475
+ }
4476
+ return;
4477
+ }
4478
+ if (marker.type === "start" && this.hasRecentlyHandledScte35Cue(cue)) {
4479
+ if (this.config.debugAdTiming) {
4480
+ console.log("[StormcloudVideoPlayer] Ignoring duplicate SCTE-35 start cue", {
4481
+ key: cue.key,
4482
+ source: cue.source
4483
+ });
4484
+ }
4485
+ return;
4486
+ }
4487
+ this.pendingScte35Cues.delete(pendingKey);
4488
+ this.markScte35CueHandled(cue);
4489
+ this.onScte35Marker(marker, cue.key);
4490
+ }
4491
+ },
4492
+ {
4493
+ key: "createScte35Cue",
4494
+ value: function createScte35Cue(marker, context) {
4495
+ var cue = {
4496
+ marker: marker,
4497
+ source: context.source,
4498
+ readiness: context.readiness,
4499
+ key: this.getScte35CueKey(marker, context)
4500
+ };
4501
+ if (context.fragmentSn !== void 0) {
4502
+ cue.fragmentSn = context.fragmentSn;
4503
+ }
4504
+ if (context.fragmentStartSeconds !== void 0) {
4505
+ cue.fragmentStartSeconds = context.fragmentStartSeconds;
4506
+ }
4507
+ return cue;
4508
+ }
4509
+ },
4510
+ {
4511
+ key: "getScte35CueKey",
4512
+ value: function getScte35CueKey(marker, context) {
4513
+ var _raw_attrs, _raw_attrs1, _raw_attrs2;
4514
+ var raw = this.getScte35MarkerRaw(marker);
4515
+ var spliceEventId = this.toIdentityString(raw === null || raw === void 0 ? void 0 : raw.splice_event_id);
4516
+ if (spliceEventId) {
4517
+ return "splice:".concat(spliceEventId);
4518
+ }
4519
+ var segmentationEventId = this.toIdentityString(raw === null || raw === void 0 ? void 0 : raw.segmentation_event_id);
4520
+ if (segmentationEventId) {
4521
+ return "segmentation:".concat(segmentationEventId);
4522
+ }
4523
+ 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);
4524
+ if (daterangeId) {
4525
+ return "daterange:".concat(daterangeId);
4526
+ }
4527
+ 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"]);
4528
+ if (scteValue) {
4529
+ return "daterange-scte:".concat(scteValue);
4530
+ }
4531
+ if (typeof marker.ptsSeconds === "number" && Number.isFinite(marker.ptsSeconds)) {
4532
+ return "pts:".concat(Math.round(marker.ptsSeconds * 2) / 2);
4533
+ }
4534
+ if (context.fragmentSn !== void 0) {
4535
+ return "fragment:".concat(context.fragmentSn);
4536
+ }
4537
+ return "".concat(context.source, ":wallclock:").concat(Math.floor(Date.now() / 1e3));
4538
+ }
4539
+ },
4540
+ {
4541
+ key: "getPendingScte35CueKey",
4542
+ value: function getPendingScte35CueKey(cue) {
4543
+ return "".concat(cue.marker.type, ":").concat(cue.key, ":").concat(cue.fragmentSn !== void 0 ? cue.fragmentSn : "unknown");
4544
+ }
4545
+ },
4546
+ {
4547
+ key: "getScte35MarkerRaw",
4548
+ value: function getScte35MarkerRaw(marker) {
4549
+ return _type_of(marker.raw) === "object" && marker.raw !== null ? marker.raw : {};
4550
+ }
4551
+ },
4552
+ {
4553
+ key: "toIdentityString",
4554
+ value: function toIdentityString(value) {
4555
+ if (typeof value === "number" && Number.isFinite(value)) {
4556
+ return String(value);
4557
+ }
4558
+ if (typeof value === "string" && value.trim().length > 0) {
4559
+ return value.trim();
4560
+ }
4561
+ return void 0;
4562
+ }
4563
+ },
4564
+ {
4565
+ key: "isStrongScte35CueKey",
4566
+ value: function isStrongScte35CueKey(key) {
4567
+ return !!(key && (key.startsWith("splice:") || key.startsWith("segmentation:") || key.startsWith("daterange:") || key.startsWith("daterange-scte:")));
4568
+ }
4569
+ },
4570
+ {
4571
+ key: "hasRecentlyHandledScte35Cue",
4572
+ value: function hasRecentlyHandledScte35Cue(cue) {
4573
+ if (this.activeScte35BreakKey === cue.key || this.scheduledScte35BreakKey === cue.key) {
4574
+ return true;
4575
+ }
4576
+ var recentKey = "".concat(cue.marker.type, ":").concat(cue.key);
4577
+ return this.recentScte35CueKeys.has(recentKey);
4578
+ }
4579
+ },
4580
+ {
4581
+ key: "markScte35CueHandled",
4582
+ value: function markScte35CueHandled(cue) {
4583
+ this.recentScte35CueKeys.set("".concat(cue.marker.type, ":").concat(cue.key), Date.now());
4584
+ this.trimRecentScte35CueMaps();
4585
+ }
4586
+ },
4587
+ {
4588
+ key: "trimRecentScte35CueMaps",
4589
+ value: function trimRecentScte35CueMaps() {
4590
+ while(this.recentScte35CueKeys.size > this.recentScte35CueLimit){
4591
+ var firstKey = this.recentScte35CueKeys.keys().next().value;
4592
+ if (!firstKey) {
4593
+ break;
4594
+ }
4595
+ this.recentScte35CueKeys.delete(firstKey);
4596
+ }
4597
+ while(this.pendingScte35Cues.size > this.recentScte35CueLimit){
4598
+ var firstKey1 = this.pendingScte35Cues.keys().next().value;
4599
+ if (!firstKey1) {
4600
+ break;
4601
+ }
4602
+ this.pendingScte35Cues.delete(firstKey1);
4603
+ }
4604
+ }
4605
+ },
4606
+ {
4607
+ key: "shouldAcceptScte35EndCue",
4608
+ value: function shouldAcceptScte35EndCue(cue) {
4609
+ if (!this.inAdBreak) {
4610
+ return false;
4611
+ }
4612
+ if (this.isStrongScte35CueKey(this.activeScte35BreakKey) && this.isStrongScte35CueKey(cue.key) && this.activeScte35BreakKey !== cue.key) {
4613
+ return false;
4614
+ }
4615
+ return true;
4616
+ }
4617
+ },
4618
+ {
4619
+ key: "activatePendingScte35CuesForFragment",
4620
+ value: function activatePendingScte35CuesForFragment(frag) {
4621
+ var _this = this;
4622
+ var fragmentSn = typeof (frag === null || frag === void 0 ? void 0 : frag.sn) === "number" ? frag.sn : void 0;
4623
+ if (fragmentSn === void 0) {
4624
+ return;
4625
+ }
4626
+ var matchingCues = Array.from(this.pendingScte35Cues.entries()).filter(function(param) {
4627
+ var _param = _sliced_to_array(param, 2), cue = _param[1];
4628
+ return cue.fragmentSn === fragmentSn;
4629
+ });
4630
+ matchingCues.forEach(function(param) {
4631
+ var _param = _sliced_to_array(param, 2), pendingKey = _param[0], cue = _param[1];
4632
+ var _cue_fragmentStartSeconds;
4633
+ _this.pendingScte35Cues.delete(pendingKey);
4634
+ var context = {
4635
+ source: cue.source,
4636
+ readiness: "playback"
4637
+ };
4638
+ context.fragmentSn = fragmentSn;
4639
+ var fragmentStartSeconds = (_cue_fragmentStartSeconds = cue.fragmentStartSeconds) !== null && _cue_fragmentStartSeconds !== void 0 ? _cue_fragmentStartSeconds : _this.getFragmentStartSeconds(frag);
4640
+ if (fragmentStartSeconds !== void 0) {
4641
+ context.fragmentStartSeconds = fragmentStartSeconds;
4642
+ }
4643
+ _this.onScte35Cue(cue.marker, context);
4644
+ });
4645
+ }
4646
+ },
4360
4647
  {
4361
4648
  key: "onScte35Marker",
4362
- value: function onScte35Marker(marker) {
4649
+ value: function onScte35Marker(marker, cueKey) {
4363
4650
  if (this.config.debugAdTiming) {
4364
4651
  console.log("[StormcloudVideoPlayer] SCTE-35 marker detected:", {
4365
4652
  type: marker.type,
@@ -4373,13 +4660,6 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4373
4660
  if (marker.type === "start") {
4374
4661
  var _this_config_immediateManifestAds;
4375
4662
  var _this_pendingAdBreak;
4376
- if (!this.video.muted) {
4377
- this.video.muted = true;
4378
- this.video.volume = 0;
4379
- if (this.config.debugAdTiming) {
4380
- console.log("[StormcloudVideoPlayer] Muted video on SCTE start marker");
4381
- }
4382
- }
4383
4663
  if (this.inAdBreak) {
4384
4664
  if (marker.durationSeconds != null) {
4385
4665
  var newDurationMs = marker.durationSeconds * 1e3;
@@ -4403,10 +4683,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4403
4683
  sendAdDetectTracking(this.config.licenseKey, detectPayload).catch(function() {});
4404
4684
  }
4405
4685
  var hasPrefetchedAds = this.pendingAdBreak && this.pendingAdBreak.vastUrls.length > 0;
4406
- this.inAdBreak = true;
4407
4686
  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;
4408
- this.expectedAdBreakDurationMs = durationMs;
4409
- this.currentAdBreakStartWallClockMs = Date.now();
4410
4687
  var isManifestMarker = this.isManifestBasedMarker(marker);
4411
4688
  var forceImmediate = (_this_config_immediateManifestAds = this.config.immediateManifestAds) !== null && _this_config_immediateManifestAds !== void 0 ? _this_config_immediateManifestAds : true;
4412
4689
  if (this.config.debugAdTiming) {
@@ -4422,7 +4699,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4422
4699
  console.log("[StormcloudVideoPlayer] Starting ad immediately (manifest-based)".concat(hasPrefetchedAds ? " with prefetched ads" : ""));
4423
4700
  }
4424
4701
  this.clearAdStartTimer();
4425
- this.handleAdStart(marker);
4702
+ this.startScte35AdBreak(marker, cueKey, durationMs);
4426
4703
  } else if (typeof marker.ptsSeconds === "number") {
4427
4704
  var _this_config_driftToleranceMs;
4428
4705
  var tol = (_this_config_driftToleranceMs = this.config.driftToleranceMs) !== null && _this_config_driftToleranceMs !== void 0 ? _this_config_driftToleranceMs : 1e3;
@@ -4442,23 +4719,22 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4442
4719
  if (this.config.debugAdTiming) {
4443
4720
  console.log("[StormcloudVideoPlayer] Scheduling ad start in ".concat(deltaMs, "ms"));
4444
4721
  }
4445
- this.scheduleAdStartIn(deltaMs);
4722
+ this.expectedAdBreakDurationMs = durationMs;
4723
+ this.scheduledScte35BreakKey = cueKey;
4724
+ this.scheduleAdStartIn(deltaMs, marker, cueKey);
4446
4725
  } else {
4447
4726
  if (this.config.debugAdTiming) {
4448
4727
  console.log("[StormcloudVideoPlayer] Starting ad immediately (within tolerance)");
4449
4728
  }
4450
4729
  this.clearAdStartTimer();
4451
- this.handleAdStart(marker);
4730
+ this.startScte35AdBreak(marker, cueKey, durationMs);
4452
4731
  }
4453
4732
  } else {
4454
4733
  if (this.config.debugAdTiming) {
4455
4734
  console.log("[StormcloudVideoPlayer] Starting ad immediately (fallback)");
4456
4735
  }
4457
4736
  this.clearAdStartTimer();
4458
- this.handleAdStart(marker);
4459
- }
4460
- if (this.expectedAdBreakDurationMs != null) {
4461
- this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
4737
+ this.startScte35AdBreak(marker, cueKey, durationMs);
4462
4738
  }
4463
4739
  return;
4464
4740
  }
@@ -4514,6 +4790,27 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4514
4790
  }
4515
4791
  }
4516
4792
  },
4793
+ {
4794
+ key: "startScte35AdBreak",
4795
+ value: function startScte35AdBreak(marker, cueKey, durationMs) {
4796
+ if (!this.video.muted) {
4797
+ this.video.muted = true;
4798
+ this.video.volume = 0;
4799
+ if (this.config.debugAdTiming) {
4800
+ console.log("[StormcloudVideoPlayer] Muted video on SCTE start marker");
4801
+ }
4802
+ }
4803
+ this.inAdBreak = true;
4804
+ this.activeScte35BreakKey = cueKey !== null && cueKey !== void 0 ? cueKey : this.pendingScte35CueKey;
4805
+ this.scheduledScte35BreakKey = void 0;
4806
+ this.expectedAdBreakDurationMs = durationMs;
4807
+ this.currentAdBreakStartWallClockMs = Date.now();
4808
+ this.handleAdStart(marker);
4809
+ if (this.expectedAdBreakDurationMs != null) {
4810
+ this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
4811
+ }
4812
+ }
4813
+ },
4517
4814
  {
4518
4815
  key: "parseCueOutDuration",
4519
4816
  value: function parseCueOutDuration(value) {
@@ -4597,6 +4894,336 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4597
4894
  return false;
4598
4895
  }
4599
4896
  },
4897
+ {
4898
+ key: "normalizeFragmentPayload",
4899
+ value: function normalizeFragmentPayload(payload) {
4900
+ if (_instanceof(payload, Uint8Array)) {
4901
+ return payload;
4902
+ }
4903
+ if (_instanceof(payload, ArrayBuffer)) {
4904
+ return new Uint8Array(payload);
4905
+ }
4906
+ if (ArrayBuffer.isView(payload)) {
4907
+ var view = payload;
4908
+ return new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
4909
+ }
4910
+ return void 0;
4911
+ }
4912
+ },
4913
+ {
4914
+ key: "processFragmentScte35Payload",
4915
+ value: function processFragmentScte35Payload(payloadData, fragmentSn, fragmentStartSeconds) {
4916
+ var _this = this;
4917
+ var payload = this.normalizeFragmentPayload(payloadData);
4918
+ if (!payload) {
4919
+ return;
4920
+ }
4921
+ var markers = this.parseScte35FromTsPackets(payload);
4922
+ markers.forEach(function(marker) {
4923
+ var context = {
4924
+ source: "ts",
4925
+ readiness: "early"
4926
+ };
4927
+ if (fragmentSn !== void 0) {
4928
+ context.fragmentSn = fragmentSn;
4929
+ }
4930
+ if (fragmentStartSeconds !== void 0) {
4931
+ context.fragmentStartSeconds = fragmentStartSeconds;
4932
+ }
4933
+ _this.onScte35Cue(marker, context);
4934
+ });
4935
+ }
4936
+ },
4937
+ {
4938
+ key: "parseScte35FromTsPackets",
4939
+ value: function parseScte35FromTsPackets(data) {
4940
+ var packetInfo = this.detectTsPacketFormat(data);
4941
+ if (!packetInfo) {
4942
+ return [];
4943
+ }
4944
+ var markers = [];
4945
+ var sectionAssemblers = /* @__PURE__ */ new Map();
4946
+ for(var packetStart = packetInfo.offset; packetStart + packetInfo.packetSize <= data.length; packetStart += packetInfo.packetSize){
4947
+ var tsStart = packetStart + packetInfo.tsPayloadOffset;
4948
+ if (data[tsStart] !== 71) {
4949
+ continue;
4950
+ }
4951
+ var secondByte = data[tsStart + 1];
4952
+ var thirdByte = data[tsStart + 2];
4953
+ var fourthByte = data[tsStart + 3];
4954
+ if (secondByte == null || thirdByte == null || fourthByte == null || (secondByte & 128) !== 0) {
4955
+ continue;
4956
+ }
4957
+ var payloadUnitStart = (secondByte & 64) !== 0;
4958
+ var pid = (secondByte & 31) << 8 | thirdByte;
4959
+ var adaptationFieldControl = fourthByte >> 4 & 3;
4960
+ var hasPayload = adaptationFieldControl === 1 || adaptationFieldControl === 3;
4961
+ if (!hasPayload) {
4962
+ continue;
4963
+ }
4964
+ var payloadStart = tsStart + 4;
4965
+ if (adaptationFieldControl === 3) {
4966
+ var adaptationLength = data[payloadStart];
4967
+ if (adaptationLength == null) {
4968
+ continue;
4969
+ }
4970
+ payloadStart += 1 + adaptationLength;
4971
+ }
4972
+ var payloadEnd = Math.min(tsStart + 188, data.length);
4973
+ if (payloadStart >= payloadEnd || payloadStart >= data.length) {
4974
+ continue;
4975
+ }
4976
+ var payload = data.subarray(payloadStart, payloadEnd);
4977
+ if (pid === 0) {
4978
+ this.parsePatSection(payload, payloadUnitStart);
4979
+ } else if (this.pmtPids.has(pid)) {
4980
+ this.parsePmtSection(payload, payloadUnitStart);
4981
+ } else if (this.tsScte35Pids.has(pid)) {
4982
+ this.collectScte35SectionsFromPayload(pid, payload, payloadUnitStart, sectionAssemblers, markers);
4983
+ }
4984
+ }
4985
+ return markers;
4986
+ }
4987
+ },
4988
+ {
4989
+ key: "detectTsPacketFormat",
4990
+ value: function detectTsPacketFormat(data) {
4991
+ var packetSizes = [
4992
+ 188,
4993
+ 192,
4994
+ 204
4995
+ ];
4996
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
4997
+ try {
4998
+ for(var _iterator = packetSizes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
4999
+ var packetSize = _step.value;
5000
+ var tsPayloadOffset = packetSize === 192 ? 4 : 0;
5001
+ for(var offset = 0; offset < packetSize; offset++){
5002
+ var matchedPackets = 0;
5003
+ for(var packetStart = offset; packetStart + tsPayloadOffset < data.length && matchedPackets < 5; packetStart += packetSize){
5004
+ if (data[packetStart + tsPayloadOffset] !== 71) {
5005
+ break;
5006
+ }
5007
+ matchedPackets++;
5008
+ }
5009
+ if (matchedPackets >= 2) {
5010
+ return {
5011
+ offset: offset,
5012
+ packetSize: packetSize,
5013
+ tsPayloadOffset: tsPayloadOffset
5014
+ };
5015
+ }
5016
+ }
5017
+ }
5018
+ } catch (err) {
5019
+ _didIteratorError = true;
5020
+ _iteratorError = err;
5021
+ } finally{
5022
+ try {
5023
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
5024
+ _iterator.return();
5025
+ }
5026
+ } finally{
5027
+ if (_didIteratorError) {
5028
+ throw _iteratorError;
5029
+ }
5030
+ }
5031
+ }
5032
+ return void 0;
5033
+ }
5034
+ },
5035
+ {
5036
+ key: "parsePatSection",
5037
+ value: function parsePatSection(payload, payloadUnitStart) {
5038
+ var sectionStart = this.getPsiSectionStart(payload, payloadUnitStart);
5039
+ if (sectionStart == null || sectionStart + 8 >= payload.length) {
5040
+ return;
5041
+ }
5042
+ if (payload[sectionStart] !== 0) {
5043
+ return;
5044
+ }
5045
+ var sectionLength = this.getPsiSectionLength(payload, sectionStart);
5046
+ var sectionEnd = Math.min(payload.length, sectionStart + 3 + sectionLength);
5047
+ for(var offset = sectionStart + 8; offset + 4 <= sectionEnd - 4; offset += 4){
5048
+ var _payload_offset, _payload_, _payload_1, _payload_2;
5049
+ 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);
5050
+ 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);
5051
+ if (programNumber !== 0) {
5052
+ this.pmtPids.add(pid);
5053
+ }
5054
+ }
5055
+ }
5056
+ },
5057
+ {
5058
+ key: "parsePmtSection",
5059
+ value: function parsePmtSection(payload, payloadUnitStart) {
5060
+ var _payload_, _payload_1;
5061
+ var sectionStart = this.getPsiSectionStart(payload, payloadUnitStart);
5062
+ if (sectionStart == null || sectionStart + 12 >= payload.length) {
5063
+ return;
5064
+ }
5065
+ if (payload[sectionStart] !== 2) {
5066
+ return;
5067
+ }
5068
+ var sectionLength = this.getPsiSectionLength(payload, sectionStart);
5069
+ var sectionEnd = Math.min(payload.length, sectionStart + 3 + sectionLength);
5070
+ 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);
5071
+ var offset = sectionStart + 12 + programInfoLength;
5072
+ while(offset + 5 <= sectionEnd - 4){
5073
+ var _payload_offset, _payload_2, _payload_3, _payload_4, _payload_5;
5074
+ var streamType = (_payload_offset = payload[offset]) !== null && _payload_offset !== void 0 ? _payload_offset : 0;
5075
+ 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);
5076
+ 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);
5077
+ var descriptorStart = offset + 5;
5078
+ var descriptorEnd = Math.min(descriptorStart + esInfoLength, sectionEnd - 4);
5079
+ if (streamType === 134 || streamType === 6 && this.descriptorsIdentifyScte35(payload, descriptorStart, descriptorEnd)) {
5080
+ this.tsScte35Pids.add(elementaryPid);
5081
+ }
5082
+ offset = descriptorStart + esInfoLength;
5083
+ }
5084
+ }
5085
+ },
5086
+ {
5087
+ key: "descriptorsIdentifyScte35",
5088
+ value: function descriptorsIdentifyScte35(data, start, end) {
5089
+ var offset = start;
5090
+ while(offset + 2 <= end){
5091
+ var _data_offset, _data_, _data_descriptorStart, _data_1, _data_2, _data_3;
5092
+ var tag = (_data_offset = data[offset]) !== null && _data_offset !== void 0 ? _data_offset : 0;
5093
+ var length = (_data_ = data[offset + 1]) !== null && _data_ !== void 0 ? _data_ : 0;
5094
+ var descriptorStart = offset + 2;
5095
+ var descriptorEnd = descriptorStart + length;
5096
+ if (descriptorEnd > end) {
5097
+ return false;
5098
+ }
5099
+ 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) : "";
5100
+ if (tag === 138 || registration === "CUEI" || registration === "SCTE") {
5101
+ return true;
5102
+ }
5103
+ offset = descriptorEnd;
5104
+ }
5105
+ return false;
5106
+ }
5107
+ },
5108
+ {
5109
+ key: "collectScte35SectionsFromPayload",
5110
+ value: function collectScte35SectionsFromPayload(pid, payload, payloadUnitStart, assemblers, markers) {
5111
+ if (payload.length === 0) {
5112
+ return;
5113
+ }
5114
+ var offset = 0;
5115
+ if (payloadUnitStart) {
5116
+ var _payload_;
5117
+ var pointerField = (_payload_ = payload[0]) !== null && _payload_ !== void 0 ? _payload_ : 0;
5118
+ var previousAssembler = assemblers.get(pid);
5119
+ if (previousAssembler && pointerField > 0) {
5120
+ this.appendScte35Bytes(pid, payload.subarray(1, Math.min(1 + pointerField, payload.length)), assemblers, markers);
5121
+ }
5122
+ assemblers.delete(pid);
5123
+ offset = 1 + pointerField;
5124
+ } else {
5125
+ this.appendScte35Bytes(pid, payload, assemblers, markers);
5126
+ return;
5127
+ }
5128
+ while(offset + 3 <= payload.length){
5129
+ var tableId = payload[offset];
5130
+ if (tableId == null || tableId === 255) {
5131
+ return;
5132
+ }
5133
+ var sectionLength = this.getPsiSectionLength(payload, offset);
5134
+ var totalLength = 3 + sectionLength;
5135
+ if (sectionLength <= 0 || totalLength <= 3) {
5136
+ return;
5137
+ }
5138
+ if (offset + totalLength <= payload.length) {
5139
+ this.addScte35SectionMarker(payload.subarray(offset, offset + totalLength), markers);
5140
+ offset += totalLength;
5141
+ } else {
5142
+ assemblers.set(pid, {
5143
+ bytes: Array.from(payload.subarray(offset)),
5144
+ expectedLength: totalLength
5145
+ });
5146
+ return;
5147
+ }
5148
+ }
5149
+ }
5150
+ },
5151
+ {
5152
+ key: "appendScte35Bytes",
5153
+ value: function appendScte35Bytes(pid, bytes, assemblers, markers) {
5154
+ var assembler = assemblers.get(pid);
5155
+ if (!assembler) {
5156
+ return;
5157
+ }
5158
+ for(var i = 0; i < bytes.length && assembler.bytes.length < assembler.expectedLength; i++){
5159
+ var _bytes_i;
5160
+ assembler.bytes.push((_bytes_i = bytes[i]) !== null && _bytes_i !== void 0 ? _bytes_i : 0);
5161
+ }
5162
+ if (assembler.bytes.length >= assembler.expectedLength) {
5163
+ assemblers.delete(pid);
5164
+ this.addScte35SectionMarker(new Uint8Array(assembler.bytes), markers);
5165
+ }
5166
+ }
5167
+ },
5168
+ {
5169
+ key: "addScte35SectionMarker",
5170
+ value: function addScte35SectionMarker(section, markers) {
5171
+ if (section[0] !== 252 || this.hasProcessedTsScte35Section(section)) {
5172
+ return;
5173
+ }
5174
+ var marker = this.parseScte35Binary(section);
5175
+ if (!marker) {
5176
+ return;
5177
+ }
5178
+ marker.raw = _object_spread_props(_object_spread({}, _type_of(marker.raw) === "object" && marker.raw ? marker.raw : {}), {
5179
+ source: "ts-packet"
5180
+ });
5181
+ markers.push(marker);
5182
+ }
5183
+ },
5184
+ {
5185
+ key: "hasProcessedTsScte35Section",
5186
+ value: function hasProcessedTsScte35Section(section) {
5187
+ var checksum = 0;
5188
+ for(var i = 0; i < section.length; i++){
5189
+ var _section_i;
5190
+ checksum = checksum * 31 + ((_section_i = section[i]) !== null && _section_i !== void 0 ? _section_i : 0) >>> 0;
5191
+ }
5192
+ var key = "".concat(section.length, ":").concat(checksum);
5193
+ if (this.processedTsScte35Sections.has(key)) {
5194
+ return true;
5195
+ }
5196
+ this.processedTsScte35Sections.add(key);
5197
+ if (this.processedTsScte35Sections.size > 200) {
5198
+ var firstKey = this.processedTsScte35Sections.values().next().value;
5199
+ if (firstKey) {
5200
+ this.processedTsScte35Sections.delete(firstKey);
5201
+ }
5202
+ }
5203
+ return false;
5204
+ }
5205
+ },
5206
+ {
5207
+ key: "getPsiSectionStart",
5208
+ value: function getPsiSectionStart(payload, payloadUnitStart) {
5209
+ if (!payloadUnitStart) {
5210
+ return void 0;
5211
+ }
5212
+ var pointerField = payload[0];
5213
+ if (pointerField == null) {
5214
+ return void 0;
5215
+ }
5216
+ var sectionStart = 1 + pointerField;
5217
+ return sectionStart < payload.length ? sectionStart : void 0;
5218
+ }
5219
+ },
5220
+ {
5221
+ key: "getPsiSectionLength",
5222
+ value: function getPsiSectionLength(data, offset) {
5223
+ var _data_, _data_1;
5224
+ 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);
5225
+ }
5226
+ },
4600
5227
  {
4601
5228
  key: "parseScte35Binary",
4602
5229
  value: function parseScte35Binary(data) {
@@ -4636,10 +5263,28 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4636
5263
  value: function skipBits(n) {
4637
5264
  this.readBits(n);
4638
5265
  }
5266
+ },
5267
+ {
5268
+ key: "bytePosition",
5269
+ get: function get() {
5270
+ return this.bitPos === 0 ? this.bytePos : this.bytePos + 1;
5271
+ }
4639
5272
  }
4640
5273
  ]);
4641
5274
  return BitReader;
4642
5275
  }();
5276
+ var readSpliceTime = function readSpliceTime(r2, ptsAdjustmentTicks2) {
5277
+ var timeSpecifiedFlag = r2.readBits(1) === 1;
5278
+ if (!timeSpecifiedFlag) {
5279
+ r2.readBits(7);
5280
+ return void 0;
5281
+ }
5282
+ r2.readBits(6);
5283
+ var high = r2.readBits(1);
5284
+ var low = r2.readBits(32);
5285
+ var ptsTicks = (high * 4294967296 + low + ptsAdjustmentTicks2) % 8589934592;
5286
+ return ptsTicks / 9e4;
5287
+ };
4643
5288
  var r = new BitReader(data);
4644
5289
  var tableId = r.readBits(8);
4645
5290
  if (tableId !== 252) return void 0;
@@ -4647,77 +5292,206 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4647
5292
  r.readBits(1);
4648
5293
  r.readBits(2);
4649
5294
  var sectionLength = r.readBits(12);
5295
+ if (sectionLength <= 0 || data.length < 3 + sectionLength) {
5296
+ return void 0;
5297
+ }
4650
5298
  r.readBits(8);
4651
5299
  r.readBits(1);
4652
5300
  r.readBits(6);
4653
5301
  var ptsAdjHigh = r.readBits(1);
4654
5302
  var ptsAdjLow = r.readBits(32);
4655
- void ptsAdjHigh;
4656
- void ptsAdjLow;
5303
+ var ptsAdjustmentTicks = ptsAdjHigh * 4294967296 + ptsAdjLow;
4657
5304
  r.readBits(8);
4658
5305
  r.readBits(12);
4659
5306
  var spliceCommandLength = r.readBits(12);
4660
5307
  var spliceCommandType = r.readBits(8);
4661
- if (spliceCommandType !== 5) {
5308
+ var markerType;
5309
+ var durationSeconds = void 0;
5310
+ var ptsSeconds = void 0;
5311
+ var spliceEventId = void 0;
5312
+ var commandBodyStart = r.bytePosition;
5313
+ if (spliceCommandType === 5) {
5314
+ spliceEventId = r.readBits(32);
5315
+ var cancel = r.readBits(1) === 1;
5316
+ r.readBits(7);
5317
+ if (cancel) return void 0;
5318
+ var outOfNetwork = r.readBits(1) === 1;
5319
+ var programSpliceFlag = r.readBits(1) === 1;
5320
+ var durationFlag = r.readBits(1) === 1;
5321
+ var spliceImmediateFlag = r.readBits(1) === 1;
5322
+ r.readBits(4);
5323
+ markerType = outOfNetwork ? "start" : "end";
5324
+ if (programSpliceFlag && !spliceImmediateFlag) {
5325
+ ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);
5326
+ } else if (!programSpliceFlag) {
5327
+ var componentCount = r.readBits(8);
5328
+ for(var i = 0; i < componentCount; i++){
5329
+ r.readBits(8);
5330
+ if (!spliceImmediateFlag) {
5331
+ var componentPtsSeconds = readSpliceTime(r, ptsAdjustmentTicks);
5332
+ if (ptsSeconds === void 0) {
5333
+ ptsSeconds = componentPtsSeconds;
5334
+ }
5335
+ }
5336
+ }
5337
+ }
5338
+ if (durationFlag) {
5339
+ r.readBits(6);
5340
+ r.readBits(1);
5341
+ var high = r.readBits(1);
5342
+ var low = r.readBits(32);
5343
+ var durationTicks = high * 4294967296 + low;
5344
+ durationSeconds = durationTicks / 9e4;
5345
+ }
5346
+ r.readBits(16);
5347
+ r.readBits(8);
5348
+ r.readBits(8);
5349
+ } else if (spliceCommandType === 6) {
5350
+ ptsSeconds = readSpliceTime(r, ptsAdjustmentTicks);
5351
+ } else {
4662
5352
  return void 0;
4663
5353
  }
4664
- r.readBits(32);
4665
- var cancel = r.readBits(1) === 1;
4666
- r.readBits(7);
4667
- if (cancel) return void 0;
4668
- var outOfNetwork = r.readBits(1) === 1;
4669
- var programSpliceFlag = r.readBits(1) === 1;
4670
- var durationFlag = r.readBits(1) === 1;
4671
- var spliceImmediateFlag = r.readBits(1) === 1;
4672
- r.readBits(4);
4673
- if (programSpliceFlag && !spliceImmediateFlag) {
4674
- var timeSpecifiedFlag = r.readBits(1) === 1;
4675
- if (timeSpecifiedFlag) {
4676
- r.readBits(6);
4677
- r.readBits(33);
4678
- } else {
4679
- r.readBits(7);
4680
- }
4681
- } else if (!programSpliceFlag) {
4682
- var componentCount = r.readBits(8);
4683
- for(var i = 0; i < componentCount; i++){
4684
- r.readBits(8);
4685
- if (!spliceImmediateFlag) {
4686
- var timeSpecifiedFlag1 = r.readBits(1) === 1;
4687
- if (timeSpecifiedFlag1) {
4688
- r.readBits(6);
4689
- r.readBits(33);
4690
- } else {
4691
- r.readBits(7);
4692
- }
5354
+ var expectedDescriptorOffset = spliceCommandLength === 4095 ? r.bytePosition : commandBodyStart + spliceCommandLength;
5355
+ var descriptorMarker = this.parseScte35SegmentationDescriptors(data, expectedDescriptorOffset);
5356
+ if (descriptorMarker) {
5357
+ markerType = descriptorMarker.type;
5358
+ if (durationSeconds === void 0) {
5359
+ durationSeconds = descriptorMarker.durationSeconds;
5360
+ }
5361
+ }
5362
+ if (!markerType) {
5363
+ return void 0;
5364
+ }
5365
+ var marker = _object_spread_props(_object_spread({
5366
+ type: markerType
5367
+ }, ptsSeconds !== void 0 ? {
5368
+ ptsSeconds: ptsSeconds
5369
+ } : {}, durationSeconds !== void 0 ? {
5370
+ durationSeconds: durationSeconds
5371
+ } : {}), {
5372
+ raw: _object_spread({
5373
+ splice_command_type: spliceCommandType
5374
+ }, spliceEventId !== void 0 ? {
5375
+ splice_event_id: spliceEventId
5376
+ } : {}, (descriptorMarker === null || descriptorMarker === void 0 ? void 0 : descriptorMarker.segmentationEventId) !== void 0 ? {
5377
+ segmentation_event_id: descriptorMarker.segmentationEventId
5378
+ } : {})
5379
+ });
5380
+ return marker;
5381
+ }
5382
+ },
5383
+ {
5384
+ key: "parseScte35SegmentationDescriptors",
5385
+ value: function parseScte35SegmentationDescriptors(data, offset) {
5386
+ var _data_offset, _data_;
5387
+ if (offset + 2 > data.length) {
5388
+ return void 0;
5389
+ }
5390
+ 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);
5391
+ var descriptorOffset = offset + 2;
5392
+ var descriptorEnd = Math.min(data.length, descriptorOffset + descriptorLoopLength);
5393
+ while(descriptorOffset + 2 <= descriptorEnd){
5394
+ var _data_descriptorOffset, _data_1;
5395
+ var descriptorTag = (_data_descriptorOffset = data[descriptorOffset]) !== null && _data_descriptorOffset !== void 0 ? _data_descriptorOffset : 0;
5396
+ var descriptorLength = (_data_1 = data[descriptorOffset + 1]) !== null && _data_1 !== void 0 ? _data_1 : 0;
5397
+ var descriptorDataStart = descriptorOffset + 2;
5398
+ var descriptorDataEnd = descriptorDataStart + descriptorLength;
5399
+ if (descriptorDataEnd > descriptorEnd) {
5400
+ return void 0;
5401
+ }
5402
+ if (descriptorTag === 2) {
5403
+ var descriptorMarker = this.parseScte35SegmentationDescriptor(data.subarray(descriptorDataStart, descriptorDataEnd));
5404
+ if (descriptorMarker) {
5405
+ return descriptorMarker;
4693
5406
  }
4694
5407
  }
5408
+ descriptorOffset = descriptorDataEnd;
5409
+ }
5410
+ return void 0;
5411
+ }
5412
+ },
5413
+ {
5414
+ key: "parseScte35SegmentationDescriptor",
5415
+ value: function parseScte35SegmentationDescriptor(descriptor) {
5416
+ var _descriptor_, _descriptor_1, _descriptor_2, _descriptor_3, _descriptor_4, _descriptor_5, _descriptor_6, _descriptor_7, _descriptor_8, _descriptor_9, _descriptor_offset, _descriptor_offset1;
5417
+ if (descriptor.length < 11) {
5418
+ return void 0;
5419
+ }
5420
+ 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);
5421
+ if (identifier !== "CUEI") {
5422
+ return void 0;
5423
+ }
5424
+ 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);
5425
+ var cancelIndicator = (((_descriptor_8 = descriptor[8]) !== null && _descriptor_8 !== void 0 ? _descriptor_8 : 0) & 128) !== 0;
5426
+ if (cancelIndicator) {
5427
+ return void 0;
5428
+ }
5429
+ var flags = (_descriptor_9 = descriptor[9]) !== null && _descriptor_9 !== void 0 ? _descriptor_9 : 0;
5430
+ var programSegmentationFlag = (flags & 128) !== 0;
5431
+ var segmentationDurationFlag = (flags & 64) !== 0;
5432
+ var offset = 10;
5433
+ if (!programSegmentationFlag) {
5434
+ var _descriptor_offset2;
5435
+ var componentCount = (_descriptor_offset2 = descriptor[offset]) !== null && _descriptor_offset2 !== void 0 ? _descriptor_offset2 : 0;
5436
+ offset += 1 + componentCount * 6;
5437
+ if (offset > descriptor.length) {
5438
+ return void 0;
5439
+ }
4695
5440
  }
4696
5441
  var durationSeconds = void 0;
4697
- if (durationFlag) {
4698
- r.readBits(6);
4699
- r.readBits(1);
4700
- var high = r.readBits(1);
4701
- var low = r.readBits(32);
4702
- var durationTicks = high * 4294967296 + low;
5442
+ if (segmentationDurationFlag) {
5443
+ var _descriptor_offset3, _descriptor_10, _descriptor_11, _descriptor_12, _descriptor_13;
5444
+ if (offset + 5 > descriptor.length) {
5445
+ return void 0;
5446
+ }
5447
+ 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);
4703
5448
  durationSeconds = durationTicks / 9e4;
5449
+ offset += 5;
4704
5450
  }
4705
- r.readBits(16);
4706
- r.readBits(8);
4707
- r.readBits(8);
4708
- if (outOfNetwork) {
4709
- var marker = _object_spread_props(_object_spread({
4710
- type: "start"
4711
- }, durationSeconds !== void 0 ? {
4712
- durationSeconds: durationSeconds
4713
- } : {}), {
4714
- raw: {
4715
- splice_command_type: 5
4716
- }
4717
- });
4718
- return marker;
5451
+ if (offset + 2 > descriptor.length) {
5452
+ return void 0;
5453
+ }
5454
+ offset += 1;
5455
+ var segmentationUpidLength = (_descriptor_offset = descriptor[offset]) !== null && _descriptor_offset !== void 0 ? _descriptor_offset : 0;
5456
+ offset += 1 + segmentationUpidLength;
5457
+ if (offset >= descriptor.length) {
5458
+ return void 0;
5459
+ }
5460
+ var segmentationTypeId = (_descriptor_offset1 = descriptor[offset]) !== null && _descriptor_offset1 !== void 0 ? _descriptor_offset1 : 0;
5461
+ var markerType = this.markerTypeFromSegmentationTypeId(segmentationTypeId);
5462
+ if (!markerType) {
5463
+ return void 0;
5464
+ }
5465
+ return _object_spread_props(_object_spread({
5466
+ type: markerType
5467
+ }, durationSeconds !== void 0 ? {
5468
+ durationSeconds: durationSeconds
5469
+ } : {}), {
5470
+ segmentationEventId: segmentationEventId
5471
+ });
5472
+ }
5473
+ },
5474
+ {
5475
+ key: "markerTypeFromSegmentationTypeId",
5476
+ value: function markerTypeFromSegmentationTypeId(segmentationTypeId) {
5477
+ switch(segmentationTypeId){
5478
+ case 16:
5479
+ case 34:
5480
+ case 48:
5481
+ case 50:
5482
+ case 52:
5483
+ case 54:
5484
+ return "start";
5485
+ case 17:
5486
+ case 35:
5487
+ case 49:
5488
+ case 51:
5489
+ case 53:
5490
+ case 55:
5491
+ return "end";
5492
+ default:
5493
+ return void 0;
4719
5494
  }
4720
- return void 0;
4721
5495
  }
4722
5496
  },
4723
5497
  {
@@ -5114,7 +5888,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5114
5888
  },
5115
5889
  {
5116
5890
  key: "startAdPrefetch",
5117
- value: function startAdPrefetch(marker, fragmentSn) {
5891
+ value: function startAdPrefetch(marker, fragmentSn, cueKey) {
5118
5892
  if (this.pendingAdBreak || this.inAdBreak) {
5119
5893
  return;
5120
5894
  }
@@ -5142,6 +5916,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5142
5916
  isFetching: false,
5143
5917
  fetchStartTime: Date.now()
5144
5918
  });
5919
+ this.pendingScte35CueKey = cueKey;
5145
5920
  this.adDetectSentForCurrentBreak = true;
5146
5921
  var detectPayload = {};
5147
5922
  if (marker.durationSeconds != null) detectPayload.durationSeconds = marker.durationSeconds;
@@ -5163,6 +5938,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5163
5938
  this.prefetchTimerId = void 0;
5164
5939
  }
5165
5940
  this.pendingAdBreak = null;
5941
+ this.pendingScte35CueKey = void 0;
5166
5942
  }
5167
5943
  },
5168
5944
  {
@@ -6646,18 +7422,17 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6646
7422
  key: "scheduleAdStartIn",
6647
7423
  value: function scheduleAdStartIn(delayMs) {
6648
7424
  var _this = this;
7425
+ var marker = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {
7426
+ type: "start"
7427
+ }, cueKey = arguments.length > 2 ? arguments[2] : void 0;
6649
7428
  this.clearAdStartTimer();
6650
7429
  var ms = Math.max(0, Math.floor(delayMs));
6651
7430
  if (ms === 0) {
6652
- this.handleAdStart({
6653
- type: "start"
6654
- }).catch(function() {});
7431
+ this.startScte35AdBreak(marker, cueKey, marker.durationSeconds != null ? marker.durationSeconds * 1e3 : void 0);
6655
7432
  return;
6656
7433
  }
6657
7434
  this.adStartTimerId = window.setTimeout(function() {
6658
- _this.handleAdStart({
6659
- type: "start"
6660
- }).catch(function() {});
7435
+ _this.startScte35AdBreak(marker, cueKey, marker.durationSeconds != null ? marker.durationSeconds * 1e3 : _this.expectedAdBreakDurationMs);
6661
7436
  }, ms);
6662
7437
  }
6663
7438
  },
@@ -7088,6 +7863,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
7088
7863
  this.adRequestQueue = [];
7089
7864
  this.inAdBreak = false;
7090
7865
  this.adDetectSentForCurrentBreak = false;
7866
+ this.activeScte35BreakKey = void 0;
7867
+ this.scheduledScte35BreakKey = void 0;
7091
7868
  this.expectedAdBreakDurationMs = void 0;
7092
7869
  this.currentAdBreakStartWallClockMs = void 0;
7093
7870
  this.clearAdStartTimer();