stormcloud-video-player 0.8.59 → 0.8.61

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.
Files changed (82) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1369 -1369
  3. package/dist/stormcloud-vp.min.js +3 -1
  4. package/lib/Player.cjs +548 -0
  5. package/lib/Player.cjs.map +1 -0
  6. package/lib/Player.d.cts +146 -0
  7. package/lib/{index.js → StormcloudPlayer.cjs} +1193 -1908
  8. package/lib/StormcloudPlayer.cjs.map +1 -0
  9. package/lib/{index.d.ts → StormcloudPlayer.d.cts} +7 -400
  10. package/lib/index.cjs +1064 -280
  11. package/lib/index.cjs.map +1 -1
  12. package/lib/index.d.cts +18 -4032
  13. package/lib/patterns.cjs +111 -0
  14. package/lib/patterns.cjs.map +1 -0
  15. package/lib/patterns.d.cts +14 -0
  16. package/lib/player/AdBreakOrchestrator.cjs +51 -16
  17. package/lib/player/AdBreakOrchestrator.cjs.map +1 -1
  18. package/lib/player/AdBreakOrchestrator.d.cts +3 -1
  19. package/lib/player/AdConfigManager.cjs +206 -26
  20. package/lib/player/AdConfigManager.cjs.map +1 -1
  21. package/lib/player/AdConfigManager.d.cts +1 -1
  22. package/lib/player/AdTimingService.cjs.map +1 -1
  23. package/lib/player/AdTimingService.d.cts +1 -1
  24. package/lib/player/HlsEngine.cjs.map +1 -1
  25. package/lib/player/HlsEngine.d.cts +1 -1
  26. package/lib/player/PlaceholderLayer.cjs.map +1 -1
  27. package/lib/player/PlayerControls.cjs.map +1 -1
  28. package/lib/player/PlayerControls.d.cts +1 -1
  29. package/lib/player/Scte35CueManager.cjs.map +1 -1
  30. package/lib/player/Scte35CueManager.d.cts +1 -1
  31. package/lib/player/Scte35Parser.cjs.map +1 -1
  32. package/lib/player/Scte35Parser.d.cts +1 -1
  33. package/lib/player/StormcloudVideoPlayer.cjs +1060 -278
  34. package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
  35. package/lib/player/StormcloudVideoPlayer.d.cts +1 -1
  36. package/lib/player/playerTypes.cjs.map +1 -1
  37. package/lib/player/playerTypes.d.cts +1 -1
  38. package/lib/players/FilePlayer.cjs.map +1 -1
  39. package/lib/players/HlsPlayer.cjs +1060 -278
  40. package/lib/players/HlsPlayer.cjs.map +1 -1
  41. package/lib/players/HlsPlayer.d.cts +1 -1
  42. package/lib/players/index.cjs +1060 -278
  43. package/lib/players/index.cjs.map +1 -1
  44. package/lib/props.cjs +186 -0
  45. package/lib/props.cjs.map +1 -0
  46. package/lib/props.d.cts +62 -0
  47. package/lib/sdk/hlsAdPlayer.cjs +884 -234
  48. package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
  49. package/lib/sdk/hlsAdPlayer.d.cts +1 -1
  50. package/lib/sdk/pal.cjs +9 -5
  51. package/lib/sdk/pal.cjs.map +1 -1
  52. package/lib/sdk/pal.d.cts +1 -0
  53. package/lib/types.cjs +49 -0
  54. package/lib/types.cjs.map +1 -0
  55. package/lib/{types-52ASml2N.d.cts → types.d.cts} +48 -1
  56. package/lib/ui/StormcloudVideoPlayer.cjs +1064 -280
  57. package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
  58. package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
  59. package/lib/utils/browserCompat.cjs.map +1 -1
  60. package/lib/utils/ctvVastSignals.cjs +178 -19
  61. package/lib/utils/ctvVastSignals.cjs.map +1 -1
  62. package/lib/utils/devUrl.cjs.map +1 -1
  63. package/lib/utils/polyfills.cjs.map +1 -1
  64. package/lib/utils/tracking.cjs +45 -16
  65. package/lib/utils/tracking.cjs.map +1 -1
  66. package/lib/utils/tracking.d.cts +1 -1
  67. package/lib/utils/trackingIngest.cjs.map +1 -1
  68. package/lib/utils/vastEnvironmentSignals.cjs +192 -20
  69. package/lib/utils/vastEnvironmentSignals.cjs.map +1 -1
  70. package/lib/utils/vastEnvironmentSignals.d.cts +13 -2
  71. package/lib/utils/vastMacros.cjs +50 -4
  72. package/lib/utils/vastMacros.cjs.map +1 -1
  73. package/lib/utils/vastMacros.d.cts +2 -0
  74. package/lib/utils/vastTrackingMacros.cjs +5 -0
  75. package/lib/utils/vastTrackingMacros.cjs.map +1 -1
  76. package/lib/utils/vastTrackingMacros.d.cts +2 -0
  77. package/lib/utils.cjs +292 -0
  78. package/lib/utils.cjs.map +1 -0
  79. package/lib/utils.d.cts +17 -0
  80. package/package.json +91 -91
  81. package/rollup.config.js +90 -90
  82. package/lib/index.js.map +0 -1
@@ -1,4 +1,12 @@
1
1
  "use strict";
2
+ function _array_like_to_array(arr, len) {
3
+ if (len == null || len > arr.length) len = arr.length;
4
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
5
+ return arr2;
6
+ }
7
+ function _array_with_holes(arr) {
8
+ if (Array.isArray(arr)) return arr;
9
+ }
2
10
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
3
11
  try {
4
12
  var info = gen[key](arg);
@@ -25,6 +33,62 @@ function _async_to_generator(fn) {
25
33
  });
26
34
  };
27
35
  }
36
+ function _define_property(obj, key, value) {
37
+ if (key in obj) {
38
+ Object.defineProperty(obj, key, {
39
+ value: value,
40
+ enumerable: true,
41
+ configurable: true,
42
+ writable: true
43
+ });
44
+ } else obj[key] = value;
45
+ return obj;
46
+ }
47
+ function _iterable_to_array_limit(arr, i) {
48
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
49
+ if (_i == null) return;
50
+ var _arr = [];
51
+ var _n = true;
52
+ var _d = false;
53
+ var _s, _e;
54
+ try {
55
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
56
+ _arr.push(_s.value);
57
+ if (i && _arr.length === i) break;
58
+ }
59
+ } catch (err) {
60
+ _d = true;
61
+ _e = err;
62
+ } finally{
63
+ try {
64
+ if (!_n && _i["return"] != null) _i["return"]();
65
+ } finally{
66
+ if (_d) throw _e;
67
+ }
68
+ }
69
+ return _arr;
70
+ }
71
+ function _non_iterable_rest() {
72
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
73
+ }
74
+ function _object_spread(target) {
75
+ for(var i = 1; i < arguments.length; i++){
76
+ var source = arguments[i] != null ? arguments[i] : {};
77
+ var ownKeys = Object.keys(source);
78
+ if (typeof Object.getOwnPropertySymbols === "function") {
79
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
80
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
81
+ }));
82
+ }
83
+ ownKeys.forEach(function(key) {
84
+ _define_property(target, key, source[key]);
85
+ });
86
+ }
87
+ return target;
88
+ }
89
+ function _sliced_to_array(arr, i) {
90
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
91
+ }
28
92
  function _ts_generator(thisArg, body) {
29
93
  var f, y, t, _ = {
30
94
  label: 0,
@@ -128,6 +192,14 @@ function _type_of(obj) {
128
192
  "@swc/helpers - typeof";
129
193
  return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
130
194
  }
195
+ function _unsupported_iterable_to_array(o, minLen) {
196
+ if (!o) return;
197
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
198
+ var n = Object.prototype.toString.call(o).slice(8, -1);
199
+ if (n === "Object" && o.constructor) n = o.constructor.name;
200
+ if (n === "Map" || n === "Set") return Array.from(n);
201
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
202
+ }
131
203
  var __create = Object.create;
132
204
  var __defProp = Object.defineProperty;
133
205
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -383,6 +455,7 @@ var KNOWN_VAST_MACROS = /* @__PURE__ */ new Set([
383
455
  "PLAYERSIZE",
384
456
  "PLAYERSTATE",
385
457
  "PODSEQUENCE",
458
+ "REASON",
386
459
  "REGULATIONS",
387
460
  "SERVERSIDE",
388
461
  "SERVERUA",
@@ -441,6 +514,10 @@ function resolveMacroValues(ctx) {
441
514
  if (ctx.podSequence != null) {
442
515
  set("PODSEQUENCE", String(ctx.podSequence));
443
516
  }
517
+ set("ADSERVINGID", ctx.adServingId);
518
+ if (ctx.reason != null && ctx.reason !== "") {
519
+ set("REASON", String(ctx.reason));
520
+ }
444
521
  return values;
445
522
  }
446
523
  function substituteVastTrackingMacros(url) {
@@ -457,10 +534,72 @@ function substituteVastTrackingMacros(url) {
457
534
  });
458
535
  }
459
536
  // src/sdk/hlsAdPlayer.ts
537
+ var LINEAR_TRACKING_EVENTS = [
538
+ "creativeView",
539
+ "loaded",
540
+ "start",
541
+ "firstQuartile",
542
+ "midpoint",
543
+ "thirdQuartile",
544
+ "complete",
545
+ "mute",
546
+ "unmute",
547
+ "pause",
548
+ "resume",
549
+ "fullscreen",
550
+ "exitFullscreen",
551
+ "playerExpand",
552
+ "playerCollapse",
553
+ "notUsed"
554
+ ];
555
+ function textOf(el) {
556
+ var _el_textContent;
557
+ var value = el === null || el === void 0 ? void 0 : (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
558
+ return value ? value : void 0;
559
+ }
560
+ function parseVastTime(value) {
561
+ if (!value) return void 0;
562
+ var parts = value.trim().split(":");
563
+ if (parts.length !== 3) return void 0;
564
+ var _parts_map = _sliced_to_array(parts.map(function(p) {
565
+ return parseFloat(p);
566
+ }), 3), h = _parts_map[0], m = _parts_map[1], s = _parts_map[2];
567
+ if (![
568
+ h,
569
+ m,
570
+ s
571
+ ].every(function(n) {
572
+ return n !== void 0 && Number.isFinite(n);
573
+ })) {
574
+ return void 0;
575
+ }
576
+ return h * 3600 + m * 60 + s;
577
+ }
578
+ function parseProgressOffset(offset) {
579
+ if (!offset) return void 0;
580
+ var trimmed = offset.trim();
581
+ if (trimmed.endsWith("%")) {
582
+ var percent = parseFloat(trimmed);
583
+ return Number.isFinite(percent) ? {
584
+ offsetPercent: percent
585
+ } : void 0;
586
+ }
587
+ var seconds = parseVastTime(trimmed);
588
+ return seconds !== void 0 ? {
589
+ offsetSeconds: seconds
590
+ } : void 0;
591
+ }
460
592
  var MAX_VAST_WRAPPER_DEPTH = 5;
461
593
  var BEACON_TIMEOUT_MS = 3e4;
462
594
  var inFlightBeacons = /* @__PURE__ */ new Set();
463
595
  var VAST_ERROR_MEDIA_DISPLAY = 405;
596
+ var VAST_ERROR_WRAPPER_TIMEOUT = 301;
597
+ var VAST_ERROR_WRAPPER_LIMIT = 302;
598
+ var VAST_ERROR_WRAPPER_NO_ADS = 303;
599
+ var VAST_ERROR_NO_SUPPORTED_MEDIA = 403;
600
+ var VERIFICATION_NOT_SUPPORTED_REASON = 2;
601
+ var VIEWABLE_MIN_VISIBLE_RATIO = 0.5;
602
+ var VIEWABLE_MIN_CONTINUOUS_S = 2;
464
603
  function toVastMediaErrorCode(error) {
465
604
  switch(error === null || error === void 0 ? void 0 : error.code){
466
605
  case 1:
@@ -488,6 +627,7 @@ function createHlsAdPlayer(contentVideo, options) {
488
627
  var adHls;
489
628
  var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
490
629
  var adEventHandlers = [];
630
+ var containerHandlers = [];
491
631
  var currentAd;
492
632
  var currentAdMediaFile;
493
633
  var podAds = [];
@@ -505,14 +645,28 @@ function createHlsAdPlayer(contentVideo, options) {
505
645
  var sawDecodedVideoFrame = false;
506
646
  var videoFrameCallbackHandle;
507
647
  var pendingPlayPromise;
508
- var trackingFired = {
509
- impression: false,
510
- start: false,
511
- firstQuartile: false,
512
- midpoint: false,
513
- thirdQuartile: false,
514
- complete: false
515
- };
648
+ function createTrackingState() {
649
+ return {
650
+ impression: false,
651
+ loaded: false,
652
+ start: false,
653
+ firstQuartile: false,
654
+ midpoint: false,
655
+ thirdQuartile: false,
656
+ complete: false,
657
+ viewabilitySettled: false,
658
+ lastMuted: void 0,
659
+ progressFired: /* @__PURE__ */ new Set()
660
+ };
661
+ }
662
+ var trackingFired = createTrackingState();
663
+ var resolvedAds = /* @__PURE__ */ new Set();
664
+ var viewObserver;
665
+ var visibleRatio = 0;
666
+ var continuousVisibleS = 0;
667
+ var lastViewSampleTime;
668
+ var lastPlayerExpanded = false;
669
+ var documentHandlers = [];
516
670
  function emit(event, payload) {
517
671
  var set = listeners.get(event);
518
672
  if (!set) return;
@@ -541,7 +695,11 @@ function createHlsAdPlayer(contentVideo, options) {
541
695
  }
542
696
  }
543
697
  }
544
- function buildTrackingMacroContext(errorCode) {
698
+ function buildTrackingMacroContext() {
699
+ var options2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
700
+ var _options2_ad;
701
+ var errorCode = options2.errorCode, reason = options2.reason;
702
+ var ad = (_options2_ad = options2.ad) !== null && _options2_ad !== void 0 ? _options2_ad : currentAd;
545
703
  var context = {
546
704
  adPlayheadSeconds: adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.currentTime,
547
705
  contentPlayheadSeconds: contentVideo.currentTime,
@@ -562,11 +720,17 @@ function createHlsAdPlayer(contentVideo, options) {
562
720
  if (podAds.length > 0) {
563
721
  context.podSequence = podIndex + 1;
564
722
  }
723
+ if (ad === null || ad === void 0 ? void 0 : ad.adServingId) {
724
+ context.adServingId = ad.adServingId;
725
+ }
726
+ if (reason != null) {
727
+ context.reason = reason;
728
+ }
565
729
  return context;
566
730
  }
567
731
  function fireTrackingPixels(urls, options2) {
568
732
  if (!urls || urls.length === 0) return;
569
- var macroContext = buildTrackingMacroContext(options2 === null || options2 === void 0 ? void 0 : options2.errorCode);
733
+ var macroContext = buildTrackingMacroContext(options2);
570
734
  urls.forEach(function(url) {
571
735
  try {
572
736
  var trackingUrl = substituteVastTrackingMacros(url, macroContext);
@@ -677,8 +841,8 @@ function createHlsAdPlayer(contentVideo, options) {
677
841
  var url = (mediaFile.url.toLowerCase().split("?")[0] || "").trim();
678
842
  return type.startsWith("audio/") || url.endsWith(".mp3") || url.endsWith(".aac") || url.endsWith(".m4a") || url.endsWith(".ogg") || url.endsWith(".oga") || url.endsWith(".opus") || url.endsWith(".wav") || url.endsWith(".weba");
679
843
  }
680
- function collectVideoMediaFiles(scope, verbose) {
681
- var mediaFileElements = scope.querySelectorAll("MediaFile");
844
+ function collectVideoMediaFiles(linear, verbose) {
845
+ var mediaFileElements = linear.querySelectorAll(":scope > MediaFiles > MediaFile");
682
846
  var mediaFiles = [];
683
847
  if (verbose) {
684
848
  console.log("[HlsAdPlayer] Found ".concat(mediaFileElements.length, " MediaFile element(s) in VAST XML"));
@@ -698,6 +862,13 @@ function createHlsAdPlayer(contentVideo, options) {
698
862
  }
699
863
  return;
700
864
  }
865
+ var apiFramework = (mf.getAttribute("apiFramework") || "").toUpperCase();
866
+ if (apiFramework === "VPAID") {
867
+ if (verbose) {
868
+ console.log("[HlsAdPlayer] MediaFile ".concat(index, " ignored (VPAID creatives are not supported)"));
869
+ }
870
+ return;
871
+ }
701
872
  var bitrateAttr = mf.getAttribute("bitrate");
702
873
  var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
703
874
  var mediaFile = {
@@ -728,114 +899,144 @@ function createHlsAdPlayer(contentVideo, options) {
728
899
  return mediaFiles;
729
900
  }
730
901
  function createEmptyTrackingUrls() {
731
- return {
902
+ var urls = {
732
903
  impression: [],
733
- start: [],
734
- firstQuartile: [],
735
- midpoint: [],
736
- thirdQuartile: [],
737
- complete: [],
738
- mute: [],
739
- unmute: [],
740
- pause: [],
741
- resume: [],
742
- fullscreen: [],
743
- exitFullscreen: [],
744
- skip: [],
745
- error: []
904
+ clickTracking: [],
905
+ error: [],
906
+ viewable: [],
907
+ notViewable: [],
908
+ viewUndetermined: [],
909
+ verificationNotExecuted: [],
910
+ progress: []
746
911
  };
912
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
913
+ try {
914
+ for(var _iterator = LINEAR_TRACKING_EVENTS[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
915
+ var event = _step.value;
916
+ urls[event] = [];
917
+ }
918
+ } catch (err) {
919
+ _didIteratorError = true;
920
+ _iteratorError = err;
921
+ } finally{
922
+ try {
923
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
924
+ _iterator.return();
925
+ }
926
+ } finally{
927
+ if (_didIteratorError) {
928
+ throw _iteratorError;
929
+ }
930
+ }
931
+ }
932
+ return urls;
747
933
  }
748
- function extractTrackingUrls(scope) {
749
- var trackingUrls = createEmptyTrackingUrls();
750
- scope.querySelectorAll("Impression").forEach(function(el) {
751
- var _el_textContent;
752
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
753
- if (url) trackingUrls.impression.push(url);
934
+ function pushUrls(target, elements) {
935
+ elements.forEach(function(el) {
936
+ var url = textOf(el);
937
+ if (url) target.push(url);
754
938
  });
755
- scope.querySelectorAll("Tracking").forEach(function(el) {
756
- var _el_textContent;
939
+ }
940
+ function collectLinearTracking(linear, into) {
941
+ linear.querySelectorAll(":scope > TrackingEvents > Tracking").forEach(function(el) {
757
942
  var event = el.getAttribute("event");
758
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
759
- if (event && url) {
760
- var eventKey = event;
761
- if (trackingUrls[eventKey]) {
762
- trackingUrls[eventKey].push(url);
763
- }
943
+ var url = textOf(el);
944
+ if (!event || !url) return;
945
+ if (event === "progress") {
946
+ var offset = parseProgressOffset(el.getAttribute("offset"));
947
+ if (offset) into.progress.push(_object_spread({
948
+ url: url
949
+ }, offset));
950
+ return;
951
+ }
952
+ if (LINEAR_TRACKING_EVENTS.indexOf(event) !== -1) {
953
+ into[event].push(url);
764
954
  }
765
955
  });
766
- scope.querySelectorAll("Error").forEach(function(el) {
767
- var _el_textContent;
768
- var url = (_el_textContent = el.textContent) === null || _el_textContent === void 0 ? void 0 : _el_textContent.trim();
769
- if (url) trackingUrls.error.push(url);
956
+ pushUrls(into.clickTracking, linear.querySelectorAll(":scope > VideoClicks > ClickTracking"));
957
+ }
958
+ function collectAdLevelTracking(adBody, into) {
959
+ pushUrls(into.impression, adBody.querySelectorAll(":scope > Impression"));
960
+ pushUrls(into.error, adBody.querySelectorAll(":scope > Error"));
961
+ pushUrls(into.viewable, adBody.querySelectorAll(":scope > ViewableImpression > Viewable"));
962
+ pushUrls(into.notViewable, adBody.querySelectorAll(":scope > ViewableImpression > NotViewable"));
963
+ pushUrls(into.viewUndetermined, adBody.querySelectorAll(":scope > ViewableImpression > ViewUndetermined"));
964
+ adBody.querySelectorAll(':scope > AdVerifications > Verification, :scope > Extensions > Extension[type="AdVerifications"] > AdVerifications > Verification').forEach(function(verification) {
965
+ pushUrls(into.verificationNotExecuted, verification.querySelectorAll(':scope > TrackingEvents > Tracking[event="verificationNotExecuted"]'));
770
966
  });
771
- return trackingUrls;
772
967
  }
773
968
  function mergeTrackingUrls(target, source) {
774
- Object.keys(target).forEach(function(key) {
775
- if (source[key] && source[key].length > 0) {
776
- target[key] = target[key].concat(source[key]);
969
+ var targetLists = target;
970
+ var sourceLists = source;
971
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
972
+ try {
973
+ for(var _iterator = Object.keys(targetLists)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
974
+ var key = _step.value;
975
+ var incoming = sourceLists[key];
976
+ if (incoming && incoming.length > 0) {
977
+ targetLists[key] = targetLists[key].concat(incoming);
978
+ }
777
979
  }
778
- });
980
+ } catch (err) {
981
+ _didIteratorError = true;
982
+ _iteratorError = err;
983
+ } finally{
984
+ try {
985
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
986
+ _iterator.return();
987
+ }
988
+ } finally{
989
+ if (_didIteratorError) {
990
+ throw _iteratorError;
991
+ }
992
+ }
993
+ }
779
994
  return target;
780
995
  }
996
+ function parseXml(xmlString) {
997
+ var xmlDoc = new DOMParser().parseFromString(xmlString, "text/xml");
998
+ var parserError = xmlDoc.querySelector("parsererror");
999
+ if (parserError) {
1000
+ console.error("[HlsAdPlayer] XML parsing error (malformed VAST XML):", parserError.textContent);
1001
+ return null;
1002
+ }
1003
+ return xmlDoc;
1004
+ }
1005
+ function getAdSequence(adElement) {
1006
+ var sequence = parseInt(adElement.getAttribute("sequence") || "", 10);
1007
+ return Number.isFinite(sequence) ? sequence : void 0;
1008
+ }
1009
+ function emptyVastResult(root) {
1010
+ var errorUrls = [];
1011
+ pushUrls(errorUrls, root.querySelectorAll(":scope > Error"));
1012
+ return {
1013
+ type: "empty",
1014
+ errorUrls: errorUrls,
1015
+ errorCode: VAST_ERROR_WRAPPER_NO_ADS
1016
+ };
1017
+ }
781
1018
  function parseVastXml(xmlString) {
782
1019
  try {
783
- var _xmlDoc_querySelector, _xmlDoc_querySelector_textContent, _xmlDoc_querySelector1, _xmlDoc_querySelector_textContent1, _xmlDoc_querySelector2, _xmlDoc_querySelector3;
784
- var parser = new DOMParser();
785
- var xmlDoc = parser.parseFromString(xmlString, "text/xml");
786
- var parserError = xmlDoc.querySelector("parsererror");
787
- if (parserError) {
788
- console.error("[HlsAdPlayer] XML parsing error (malformed VAST XML):", parserError.textContent);
789
- return {
790
- type: "empty"
791
- };
792
- }
793
- var adElement = xmlDoc.querySelector("Ad");
1020
+ var _adElements_find;
1021
+ var xmlDoc = parseXml(xmlString);
1022
+ if (!xmlDoc) return {
1023
+ type: "empty"
1024
+ };
1025
+ var root = xmlDoc.documentElement;
1026
+ var adElements = Array.from(root.querySelectorAll(":scope > Ad"));
1027
+ var adElement = (_adElements_find = adElements.find(function(el) {
1028
+ return getAdSequence(el) === void 0;
1029
+ })) !== null && _adElements_find !== void 0 ? _adElements_find : adElements[0];
794
1030
  if (!adElement) {
795
- console.warn("[HlsAdPlayer] No Ad element found in VAST XML");
796
- return {
797
- type: "empty"
798
- };
799
- }
800
- var adId = adElement.getAttribute("id") || "unknown";
801
- var title = ((_xmlDoc_querySelector = xmlDoc.querySelector("AdTitle")) === null || _xmlDoc_querySelector === void 0 ? void 0 : _xmlDoc_querySelector.textContent) || "Ad";
802
- var clickThrough = (_xmlDoc_querySelector1 = xmlDoc.querySelector("ClickThrough")) === null || _xmlDoc_querySelector1 === void 0 ? void 0 : (_xmlDoc_querySelector_textContent = _xmlDoc_querySelector1.textContent) === null || _xmlDoc_querySelector_textContent === void 0 ? void 0 : _xmlDoc_querySelector_textContent.trim();
803
- var wrapperUri = (_xmlDoc_querySelector2 = xmlDoc.querySelector("VASTAdTagURI")) === null || _xmlDoc_querySelector2 === void 0 ? void 0 : (_xmlDoc_querySelector_textContent1 = _xmlDoc_querySelector2.textContent) === null || _xmlDoc_querySelector_textContent1 === void 0 ? void 0 : _xmlDoc_querySelector_textContent1.trim();
804
- if (wrapperUri) {
805
- console.log("[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ".concat(wrapperUri));
806
- return {
807
- type: "wrapper",
808
- vastAdTagUri: wrapperUri,
809
- trackingUrls: extractTrackingUrls(xmlDoc),
810
- clickThrough: clickThrough
811
- };
1031
+ var _root_getAttribute;
1032
+ console.warn("[HlsAdPlayer] No Ad element found in VAST ".concat((_root_getAttribute = root.getAttribute("version")) !== null && _root_getAttribute !== void 0 ? _root_getAttribute : "", " response"));
1033
+ return emptyVastResult(root);
812
1034
  }
813
- var isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
814
- var durationText = ((_xmlDoc_querySelector3 = xmlDoc.querySelector("Duration")) === null || _xmlDoc_querySelector3 === void 0 ? void 0 : _xmlDoc_querySelector3.textContent) || "00:00:30";
815
- var durationParts = durationText.split(":");
816
- var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
817
- var mediaFiles = collectVideoMediaFiles(xmlDoc, true);
818
- if (mediaFiles.length === 0) {
819
- if (isNoAdAvailable) {
820
- console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
821
- } else {
822
- console.warn("[HlsAdPlayer] No supported media files found in VAST XML");
823
- }
824
- return {
825
- type: "empty"
826
- };
1035
+ var parsed = parseAdElement(adElement, true);
1036
+ if (parsed.type === "wrapper") {
1037
+ console.log("[HlsAdPlayer] VAST wrapper detected, following VASTAdTagURI: ".concat(parsed.vastAdTagUri));
827
1038
  }
828
- return {
829
- type: "inline",
830
- ad: {
831
- id: adId,
832
- title: title,
833
- duration: duration,
834
- mediaFiles: mediaFiles,
835
- trackingUrls: extractTrackingUrls(xmlDoc),
836
- clickThrough: clickThrough
837
- }
838
- };
1039
+ return parsed;
839
1040
  } catch (error) {
840
1041
  console.error("[HlsAdPlayer] Error parsing VAST XML:", error);
841
1042
  return {
@@ -844,48 +1045,101 @@ function createHlsAdPlayer(contentVideo, options) {
844
1045
  }
845
1046
  }
846
1047
  function parseAdElement(adElement) {
1048
+ var verbose = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false;
847
1049
  try {
848
- var _adElement_querySelector, _adElement_querySelector_textContent, _adElement_querySelector1, _adElement_querySelector_textContent1, _adElement_querySelector2, _adElement_querySelector3;
849
- var adId = adElement.getAttribute("id") || "unknown";
850
- var title = ((_adElement_querySelector = adElement.querySelector("AdTitle")) === null || _adElement_querySelector === void 0 ? void 0 : _adElement_querySelector.textContent) || "Ad";
851
- var clickThrough = (_adElement_querySelector1 = adElement.querySelector("ClickThrough")) === null || _adElement_querySelector1 === void 0 ? void 0 : (_adElement_querySelector_textContent = _adElement_querySelector1.textContent) === null || _adElement_querySelector_textContent === void 0 ? void 0 : _adElement_querySelector_textContent.trim();
852
- var wrapperUri = (_adElement_querySelector2 = adElement.querySelector("VASTAdTagURI")) === null || _adElement_querySelector2 === void 0 ? void 0 : (_adElement_querySelector_textContent1 = _adElement_querySelector2.textContent) === null || _adElement_querySelector_textContent1 === void 0 ? void 0 : _adElement_querySelector_textContent1.trim();
853
- if (wrapperUri) {
1050
+ var _parseVastTime;
1051
+ var wrapper = adElement.querySelector(":scope > Wrapper");
1052
+ if (wrapper) {
1053
+ var vastAdTagUri = textOf(wrapper.querySelector(":scope > VASTAdTagURI"));
1054
+ if (!vastAdTagUri) {
1055
+ console.warn("[HlsAdPlayer] <Wrapper> has no VASTAdTagURI");
1056
+ return {
1057
+ type: "empty"
1058
+ };
1059
+ }
1060
+ var trackingUrls2 = createEmptyTrackingUrls();
1061
+ collectAdLevelTracking(wrapper, trackingUrls2);
1062
+ wrapper.querySelectorAll(":scope > Creatives > Creative > Linear").forEach(function(linear2) {
1063
+ return collectLinearTracking(linear2, trackingUrls2);
1064
+ });
854
1065
  return {
855
1066
  type: "wrapper",
856
- vastAdTagUri: wrapperUri,
857
- trackingUrls: extractTrackingUrls(adElement),
858
- clickThrough: clickThrough
1067
+ vastAdTagUri: vastAdTagUri,
1068
+ trackingUrls: trackingUrls2,
1069
+ rules: {
1070
+ followAdditionalWrappers: wrapper.getAttribute("followAdditionalWrappers") !== "false"
1071
+ }
859
1072
  };
860
1073
  }
861
- var isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
862
- var durationText = ((_adElement_querySelector3 = adElement.querySelector("Duration")) === null || _adElement_querySelector3 === void 0 ? void 0 : _adElement_querySelector3.textContent) || "00:00:30";
863
- var durationParts = durationText.split(":");
864
- var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
865
- var mediaFiles = collectVideoMediaFiles(adElement, false);
866
- if (mediaFiles.length === 0) {
867
- if (isNoAdAvailable) {
868
- console.warn("[HlsAdPlayer] Pod <Ad> indicates no ad available");
869
- } else {
870
- console.warn("[HlsAdPlayer] No supported media files in pod <Ad>");
871
- }
1074
+ var inLine = adElement.querySelector(":scope > InLine");
1075
+ if (!inLine) {
1076
+ console.warn("[HlsAdPlayer] <Ad> has neither <InLine> nor <Wrapper>");
872
1077
  return {
873
1078
  type: "empty"
874
1079
  };
875
1080
  }
1081
+ var errorUrls = [];
1082
+ pushUrls(errorUrls, inLine.querySelectorAll(":scope > Error"));
1083
+ if (adElement.getAttribute("conditionalAd") === "true") {
1084
+ console.warn("[HlsAdPlayer] Skipping conditional <Ad> (VPAID-only)");
1085
+ return {
1086
+ type: "empty",
1087
+ errorUrls: errorUrls,
1088
+ errorCode: VAST_ERROR_NO_SUPPORTED_MEDIA
1089
+ };
1090
+ }
1091
+ var linear;
1092
+ var mediaFiles = [];
1093
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1094
+ try {
1095
+ for(var _iterator = Array.from(inLine.querySelectorAll(":scope > Creatives > Creative > Linear"))[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1096
+ var candidate = _step.value;
1097
+ var files = collectVideoMediaFiles(candidate, verbose);
1098
+ if (files.length > 0) {
1099
+ linear = candidate;
1100
+ mediaFiles = files;
1101
+ break;
1102
+ }
1103
+ }
1104
+ } catch (err) {
1105
+ _didIteratorError = true;
1106
+ _iteratorError = err;
1107
+ } finally{
1108
+ try {
1109
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1110
+ _iterator.return();
1111
+ }
1112
+ } finally{
1113
+ if (_didIteratorError) {
1114
+ throw _iteratorError;
1115
+ }
1116
+ }
1117
+ }
1118
+ if (!linear) {
1119
+ console.warn("[HlsAdPlayer] No supported linear media files in <Ad>");
1120
+ return {
1121
+ type: "empty",
1122
+ errorUrls: errorUrls,
1123
+ errorCode: VAST_ERROR_NO_SUPPORTED_MEDIA
1124
+ };
1125
+ }
1126
+ var trackingUrls = createEmptyTrackingUrls();
1127
+ collectAdLevelTracking(inLine, trackingUrls);
1128
+ collectLinearTracking(linear, trackingUrls);
876
1129
  return {
877
1130
  type: "inline",
878
1131
  ad: {
879
- id: adId,
880
- title: title,
881
- duration: duration,
1132
+ id: adElement.getAttribute("id") || "unknown",
1133
+ title: textOf(inLine.querySelector(":scope > AdTitle")) || "Ad",
1134
+ duration: (_parseVastTime = parseVastTime(textOf(linear.querySelector(":scope > Duration")))) !== null && _parseVastTime !== void 0 ? _parseVastTime : 30,
882
1135
  mediaFiles: mediaFiles,
883
- trackingUrls: extractTrackingUrls(adElement),
884
- clickThrough: clickThrough
1136
+ trackingUrls: trackingUrls,
1137
+ clickThrough: textOf(linear.querySelector(":scope > VideoClicks > ClickThrough")),
1138
+ adServingId: textOf(inLine.querySelector(":scope > AdServingId"))
885
1139
  }
886
1140
  };
887
1141
  } catch (error) {
888
- console.error("[HlsAdPlayer] Error parsing pod <Ad> element:", error);
1142
+ console.error("[HlsAdPlayer] Error parsing <Ad> element:", error);
889
1143
  return {
890
1144
  type: "empty"
891
1145
  };
@@ -964,30 +1218,63 @@ function createHlsAdPlayer(contentVideo, options) {
964
1218
  }
965
1219
  function fetchAndParseVastAd(_0) {
966
1220
  return _async_to_generator(function(vastTagUrl) {
967
- var depth, accumulatedTracking, vastXml, parsed;
1221
+ var depth, accumulatedTracking, rules, vastXml, error, parsed, _parsed_errorUrls, _parsed_errorCode;
968
1222
  var _arguments = arguments;
969
1223
  return _ts_generator(this, function(_state) {
970
1224
  switch(_state.label){
971
1225
  case 0:
972
- depth = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : 0, accumulatedTracking = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : createEmptyTrackingUrls();
1226
+ depth = _arguments.length > 1 && _arguments[1] !== void 0 ? _arguments[1] : 0, accumulatedTracking = _arguments.length > 2 && _arguments[2] !== void 0 ? _arguments[2] : createEmptyTrackingUrls(), rules = _arguments.length > 3 && _arguments[3] !== void 0 ? _arguments[3] : {
1227
+ followAdditionalWrappers: true
1228
+ };
1229
+ _state.label = 1;
1230
+ case 1:
1231
+ _state.trys.push([
1232
+ 1,
1233
+ 3,
1234
+ ,
1235
+ 4
1236
+ ]);
973
1237
  return [
974
1238
  4,
975
1239
  fetchVastXml(vastTagUrl, depth === 0 ? "include" : "omit")
976
1240
  ];
977
- case 1:
1241
+ case 2:
978
1242
  vastXml = _state.sent();
1243
+ return [
1244
+ 3,
1245
+ 4
1246
+ ];
1247
+ case 3:
1248
+ error = _state.sent();
1249
+ if (depth === 0) throw error;
1250
+ console.warn("[HlsAdPlayer] Wrapped VAST request failed:", error);
1251
+ fireTrackingPixels(accumulatedTracking.error, {
1252
+ errorCode: VAST_ERROR_WRAPPER_TIMEOUT
1253
+ });
1254
+ return [
1255
+ 2,
1256
+ null
1257
+ ];
1258
+ case 4:
979
1259
  console.log("[HlsAdPlayer] VAST XML received");
980
1260
  console.log("[HlsAdPlayer] VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
981
1261
  parsed = parseVastXml(vastXml);
982
1262
  if (parsed.type === "empty") {
1263
+ ;
1264
+ fireTrackingPixels(((_parsed_errorUrls = parsed.errorUrls) !== null && _parsed_errorUrls !== void 0 ? _parsed_errorUrls : []).concat(accumulatedTracking.error), {
1265
+ errorCode: (_parsed_errorCode = parsed.errorCode) !== null && _parsed_errorCode !== void 0 ? _parsed_errorCode : VAST_ERROR_WRAPPER_NO_ADS
1266
+ });
983
1267
  return [
984
1268
  2,
985
1269
  null
986
1270
  ];
987
1271
  }
988
1272
  if (parsed.type === "wrapper") {
989
- if (depth >= MAX_VAST_WRAPPER_DEPTH) {
990
- console.warn("[HlsAdPlayer] VAST wrapper depth limit (".concat(MAX_VAST_WRAPPER_DEPTH, ") reached, aborting redirect chain"));
1273
+ if (depth >= MAX_VAST_WRAPPER_DEPTH || !rules.followAdditionalWrappers) {
1274
+ console.warn(rules.followAdditionalWrappers ? "[HlsAdPlayer] VAST wrapper depth limit (".concat(MAX_VAST_WRAPPER_DEPTH, ") reached, aborting redirect chain") : '[HlsAdPlayer] Parent wrapper set followAdditionalWrappers="false"; rejecting nested wrapper');
1275
+ fireTrackingPixels(accumulatedTracking.error.concat(parsed.trackingUrls.error), {
1276
+ errorCode: VAST_ERROR_WRAPPER_LIMIT
1277
+ });
991
1278
  return [
992
1279
  2,
993
1280
  null
@@ -996,7 +1283,7 @@ function createHlsAdPlayer(contentVideo, options) {
996
1283
  mergeTrackingUrls(accumulatedTracking, parsed.trackingUrls);
997
1284
  return [
998
1285
  2,
999
- fetchAndParseVastAd(parsed.vastAdTagUri, depth + 1, accumulatedTracking)
1286
+ fetchAndParseVastAd(parsed.vastAdTagUri, depth + 1, accumulatedTracking, parsed.rules)
1000
1287
  ];
1001
1288
  }
1002
1289
  mergeTrackingUrls(parsed.ad.trackingUrls, accumulatedTracking);
@@ -1010,7 +1297,7 @@ function createHlsAdPlayer(contentVideo, options) {
1010
1297
  }
1011
1298
  function fetchAndParsePod(vastTagUrl) {
1012
1299
  return _async_to_generator(function() {
1013
- var vastXml, trimmedXml, parser, xmlDoc, adElements, ads, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, adElement, parsed, resolved, error, err;
1300
+ var _root_getAttribute, vastXml, trimmedXml, xmlDoc, root, adElements, _root_getAttribute1, _empty_errorUrls, empty, _empty_errorCode, resolveAd, podElements, buffet, ads, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, adElement, ad, err, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, adElement1, ad1, err;
1014
1301
  return _ts_generator(this, function(_state) {
1015
1302
  switch(_state.label){
1016
1303
  case 0:
@@ -1029,125 +1316,212 @@ function createHlsAdPlayer(contentVideo, options) {
1029
1316
  []
1030
1317
  ];
1031
1318
  }
1032
- parser = new DOMParser();
1033
- xmlDoc = parser.parseFromString(vastXml, "text/xml");
1034
- if (xmlDoc.querySelector("parsererror")) {
1035
- console.error("[HlsAdPlayer] Pod VAST XML parsing error (malformed). Content (first 2000 chars):", vastXml.substring(0, 2e3));
1319
+ xmlDoc = parseXml(vastXml);
1320
+ if (!xmlDoc) {
1321
+ console.error("[HlsAdPlayer] Pod VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
1036
1322
  return [
1037
1323
  2,
1038
1324
  []
1039
1325
  ];
1040
1326
  }
1041
- adElements = Array.from(xmlDoc.querySelectorAll("Ad"));
1327
+ root = xmlDoc.documentElement;
1328
+ adElements = Array.from(root.querySelectorAll(":scope > Ad"));
1042
1329
  if (adElements.length === 0) {
1043
- console.warn("[HlsAdPlayer] No <Ad> elements found in pod VAST response (no fill). Content (first 2000 chars):", vastXml.substring(0, 2e3));
1330
+ ;
1331
+ ;
1332
+ console.warn("[HlsAdPlayer] No <Ad> elements in VAST ".concat((_root_getAttribute1 = root.getAttribute("version")) !== null && _root_getAttribute1 !== void 0 ? _root_getAttribute1 : "", " pod response (no fill)"));
1333
+ empty = emptyVastResult(root);
1334
+ if (empty.type === "empty" && ((_empty_errorUrls = empty.errorUrls) === null || _empty_errorUrls === void 0 ? void 0 : _empty_errorUrls.length)) {
1335
+ ;
1336
+ fireTrackingPixels(empty.errorUrls, {
1337
+ errorCode: (_empty_errorCode = empty.errorCode) !== null && _empty_errorCode !== void 0 ? _empty_errorCode : VAST_ERROR_WRAPPER_NO_ADS
1338
+ });
1339
+ }
1044
1340
  return [
1045
1341
  2,
1046
1342
  []
1047
1343
  ];
1048
1344
  }
1049
- adElements.sort(function(a, b) {
1050
- var aSeq = parseInt(a.getAttribute("sequence") || "", 10);
1051
- var bSeq = parseInt(b.getAttribute("sequence") || "", 10);
1052
- var aVal = Number.isFinite(aSeq) ? aSeq : Number.MAX_SAFE_INTEGER;
1053
- var bVal = Number.isFinite(bSeq) ? bSeq : Number.MAX_SAFE_INTEGER;
1054
- return aVal - bVal;
1345
+ resolveAd = function resolveAd(adElement) {
1346
+ return _async_to_generator(function() {
1347
+ var _parsed_errorUrls, parsed, _parsed_errorCode;
1348
+ return _ts_generator(this, function(_state) {
1349
+ parsed = parseAdElement(adElement);
1350
+ if (parsed.type === "inline") return [
1351
+ 2,
1352
+ parsed.ad
1353
+ ];
1354
+ if (parsed.type === "wrapper") {
1355
+ return [
1356
+ 2,
1357
+ fetchAndParseVastAd(parsed.vastAdTagUri, 1, parsed.trackingUrls, parsed.rules)
1358
+ ];
1359
+ }
1360
+ if ((_parsed_errorUrls = parsed.errorUrls) === null || _parsed_errorUrls === void 0 ? void 0 : _parsed_errorUrls.length) {
1361
+ ;
1362
+ fireTrackingPixels(parsed.errorUrls, {
1363
+ errorCode: (_parsed_errorCode = parsed.errorCode) !== null && _parsed_errorCode !== void 0 ? _parsed_errorCode : VAST_ERROR_NO_SUPPORTED_MEDIA
1364
+ });
1365
+ }
1366
+ return [
1367
+ 2,
1368
+ null
1369
+ ];
1370
+ });
1371
+ })();
1372
+ };
1373
+ podElements = adElements.filter(function(el) {
1374
+ return getAdSequence(el) !== void 0;
1375
+ }).sort(function(a, b) {
1376
+ return getAdSequence(a) - getAdSequence(b);
1377
+ });
1378
+ buffet = adElements.filter(function(el) {
1379
+ return getAdSequence(el) === void 0;
1055
1380
  });
1056
1381
  ads = [];
1382
+ if (!(podElements.length === 0)) return [
1383
+ 3,
1384
+ 10
1385
+ ];
1057
1386
  _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1058
1387
  _state.label = 2;
1059
1388
  case 2:
1060
1389
  _state.trys.push([
1061
1390
  2,
1062
- 10,
1063
- 11,
1064
- 12
1391
+ 7,
1392
+ 8,
1393
+ 9
1065
1394
  ]);
1066
- _iterator = adElements[Symbol.iterator]();
1395
+ _iterator = buffet[Symbol.iterator]();
1067
1396
  _state.label = 3;
1068
1397
  case 3:
1069
1398
  if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
1070
1399
  3,
1071
- 9
1400
+ 6
1072
1401
  ];
1073
1402
  adElement = _step.value;
1074
- parsed = parseAdElement(adElement);
1075
- if (!(parsed.type === "inline")) return [
1076
- 3,
1077
- 4
1078
- ];
1079
- ads.push(parsed.ad);
1080
1403
  return [
1081
- 3,
1082
- 8
1404
+ 4,
1405
+ resolveAd(adElement)
1083
1406
  ];
1084
1407
  case 4:
1085
- if (!(parsed.type === "wrapper")) return [
1086
- 3,
1087
- 8
1088
- ];
1408
+ ad = _state.sent();
1409
+ if (ad) ads.push(ad);
1089
1410
  _state.label = 5;
1090
1411
  case 5:
1091
- _state.trys.push([
1092
- 5,
1093
- 7,
1094
- ,
1095
- 8
1096
- ]);
1412
+ _iteratorNormalCompletion = true;
1097
1413
  return [
1098
- 4,
1099
- fetchAndParseVastAd(parsed.vastAdTagUri, 1, parsed.trackingUrls)
1414
+ 3,
1415
+ 3
1100
1416
  ];
1101
1417
  case 6:
1102
- resolved = _state.sent();
1103
- if (resolved) {
1104
- ads.push(resolved);
1105
- }
1106
1418
  return [
1107
1419
  3,
1108
- 8
1420
+ 9
1109
1421
  ];
1110
1422
  case 7:
1111
- error = _state.sent();
1112
- console.warn("[HlsAdPlayer] Failed to resolve wrapper <Ad> in pod:", error);
1423
+ err = _state.sent();
1424
+ _didIteratorError = true;
1425
+ _iteratorError = err;
1113
1426
  return [
1114
1427
  3,
1115
- 8
1428
+ 9
1116
1429
  ];
1117
1430
  case 8:
1118
- _iteratorNormalCompletion = true;
1431
+ try {
1432
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1433
+ _iterator.return();
1434
+ }
1435
+ } finally{
1436
+ if (_didIteratorError) {
1437
+ throw _iteratorError;
1438
+ }
1439
+ }
1119
1440
  return [
1120
- 3,
1121
- 3
1441
+ 7
1122
1442
  ];
1123
1443
  case 9:
1124
1444
  return [
1125
1445
  3,
1126
- 12
1446
+ 21
1127
1447
  ];
1128
1448
  case 10:
1129
- err = _state.sent();
1130
- _didIteratorError = true;
1131
- _iteratorError = err;
1449
+ _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
1450
+ _state.label = 11;
1451
+ case 11:
1452
+ _state.trys.push([
1453
+ 11,
1454
+ 19,
1455
+ 20,
1456
+ 21
1457
+ ]);
1458
+ _iterator1 = podElements[Symbol.iterator]();
1459
+ _state.label = 12;
1460
+ case 12:
1461
+ if (!!(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done)) return [
1462
+ 3,
1463
+ 18
1464
+ ];
1465
+ adElement1 = _step1.value;
1466
+ return [
1467
+ 4,
1468
+ resolveAd(adElement1)
1469
+ ];
1470
+ case 13:
1471
+ ad1 = _state.sent();
1472
+ _state.label = 14;
1473
+ case 14:
1474
+ if (!(!ad1 && buffet.length > 0)) return [
1475
+ 3,
1476
+ 16
1477
+ ];
1478
+ return [
1479
+ 4,
1480
+ resolveAd(buffet.shift())
1481
+ ];
1482
+ case 15:
1483
+ ad1 = _state.sent();
1484
+ return [
1485
+ 3,
1486
+ 14
1487
+ ];
1488
+ case 16:
1489
+ if (ad1) ads.push(ad1);
1490
+ _state.label = 17;
1491
+ case 17:
1492
+ _iteratorNormalCompletion1 = true;
1132
1493
  return [
1133
1494
  3,
1134
1495
  12
1135
1496
  ];
1136
- case 11:
1497
+ case 18:
1498
+ return [
1499
+ 3,
1500
+ 21
1501
+ ];
1502
+ case 19:
1503
+ err = _state.sent();
1504
+ _didIteratorError1 = true;
1505
+ _iteratorError1 = err;
1506
+ return [
1507
+ 3,
1508
+ 21
1509
+ ];
1510
+ case 20:
1137
1511
  try {
1138
- if (!_iteratorNormalCompletion && _iterator.return != null) {
1139
- _iterator.return();
1512
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
1513
+ _iterator1.return();
1140
1514
  }
1141
1515
  } finally{
1142
- if (_didIteratorError) {
1143
- throw _iteratorError;
1516
+ if (_didIteratorError1) {
1517
+ throw _iteratorError1;
1144
1518
  }
1145
1519
  }
1146
1520
  return [
1147
1521
  7
1148
1522
  ];
1149
- case 12:
1150
- console.log("[HlsAdPlayer] Parsed ".concat(ads.length, " ad(s) from pod VAST response"));
1523
+ case 21:
1524
+ console.log("[HlsAdPlayer] Parsed ".concat(ads.length, " ad(s) from VAST ").concat((_root_getAttribute = root.getAttribute("version")) !== null && _root_getAttribute !== void 0 ? _root_getAttribute : "", " pod response"));
1151
1525
  return [
1152
1526
  2,
1153
1527
  ads
@@ -1177,7 +1551,40 @@ function createHlsAdPlayer(contentVideo, options) {
1177
1551
  var onTimeUpdate = function onTimeUpdate() {
1178
1552
  if (!currentAd || !adVideoElement) return;
1179
1553
  noteAdProgress();
1180
- var progress = adVideoElement.currentTime / currentAd.duration;
1554
+ sampleViewability();
1555
+ var currentTime = adVideoElement.currentTime;
1556
+ if (trackingFired.start) {
1557
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1558
+ try {
1559
+ for(var _iterator = currentAd.trackingUrls.progress[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1560
+ var event = _step.value;
1561
+ var _event_offsetSeconds, _event_offsetPercent;
1562
+ if (trackingFired.progressFired.has(event)) continue;
1563
+ var threshold = (_event_offsetSeconds = event.offsetSeconds) !== null && _event_offsetSeconds !== void 0 ? _event_offsetSeconds : ((_event_offsetPercent = event.offsetPercent) !== null && _event_offsetPercent !== void 0 ? _event_offsetPercent : 0) / 100 * currentAd.duration;
1564
+ if (currentTime >= threshold) {
1565
+ trackingFired.progressFired.add(event);
1566
+ fireTrackingPixels([
1567
+ event.url
1568
+ ]);
1569
+ }
1570
+ }
1571
+ } catch (err) {
1572
+ _didIteratorError = true;
1573
+ _iteratorError = err;
1574
+ } finally{
1575
+ try {
1576
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1577
+ _iterator.return();
1578
+ }
1579
+ } finally{
1580
+ if (_didIteratorError) {
1581
+ throw _iteratorError;
1582
+ }
1583
+ }
1584
+ }
1585
+ }
1586
+ if (!(currentAd.duration > 0)) return;
1587
+ var progress = currentTime / currentAd.duration;
1181
1588
  if (progress >= 0.25 && !trackingFired.firstQuartile) {
1182
1589
  trackingFired.firstQuartile = true;
1183
1590
  fireTrackingPixels(currentAd.trackingUrls.firstQuartile);
@@ -1199,15 +1606,38 @@ function createHlsAdPlayer(contentVideo, options) {
1199
1606
  handleVideoDecodeFailure();
1200
1607
  }
1201
1608
  };
1609
+ var onCanPlay = function onCanPlay() {
1610
+ if (!currentAd || trackingFired.loaded) return;
1611
+ trackingFired.loaded = true;
1612
+ fireTrackingPixels(currentAd.trackingUrls.loaded);
1613
+ };
1202
1614
  var onPlaying = function onPlaying() {
1203
1615
  startStallWatchdog();
1204
- if (!currentAd || trackingFired.start) return;
1616
+ if (!currentAd || !adVideoElement) return;
1617
+ if (!trackingFired.impression) {
1618
+ trackingFired.impression = true;
1619
+ resolvedAds.add(currentAd);
1620
+ fireTrackingPixels(currentAd.trackingUrls.impression);
1621
+ fireTrackingPixels(currentAd.trackingUrls.creativeView);
1622
+ fireTrackingPixels(currentAd.trackingUrls.verificationNotExecuted, {
1623
+ reason: VERIFICATION_NOT_SUPPORTED_REASON
1624
+ });
1625
+ emit("ad_impression", {
1626
+ adId: currentAd.id,
1627
+ index: podIndex,
1628
+ total: podAds.length || 1
1629
+ });
1630
+ }
1631
+ if (trackingFired.start) return;
1205
1632
  trackingFired.start = true;
1633
+ trackingFired.lastMuted = adVideoElement.muted || adVideoElement.volume === 0;
1206
1634
  fireTrackingPixels(currentAd.trackingUrls.start);
1207
1635
  console.log("[HlsAdPlayer] Ad started playing");
1208
1636
  };
1209
1637
  var onEnded = function onEnded() {
1210
1638
  if (!currentAd || trackingFired.complete) return;
1639
+ sampleViewability();
1640
+ settleViewability();
1211
1641
  trackingFired.complete = true;
1212
1642
  fireTrackingPixels(currentAd.trackingUrls.complete);
1213
1643
  console.log("[HlsAdPlayer] Ad completed");
@@ -1219,11 +1649,7 @@ function createHlsAdPlayer(contentVideo, options) {
1219
1649
  var onError = function onError(e) {
1220
1650
  if (!adPlaying) return;
1221
1651
  console.error("[HlsAdPlayer] Ad video error:", e);
1222
- if (currentAd) {
1223
- fireTrackingPixels(currentAd.trackingUrls.error, {
1224
- errorCode: toVastMediaErrorCode(adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.error)
1225
- });
1226
- }
1652
+ reportCurrentAdError(toVastMediaErrorCode(adVideoElement === null || adVideoElement === void 0 ? void 0 : adVideoElement.error));
1227
1653
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1228
1654
  return;
1229
1655
  }
@@ -1231,19 +1657,26 @@ function createHlsAdPlayer(contentVideo, options) {
1231
1657
  };
1232
1658
  var onVolumeChange = function onVolumeChange() {
1233
1659
  if (!currentAd || !adVideoElement) return;
1234
- if (adVideoElement.muted) {
1235
- fireTrackingPixels(currentAd.trackingUrls.mute);
1236
- } else {
1237
- fireTrackingPixels(currentAd.trackingUrls.unmute);
1660
+ var muted = adVideoElement.muted || adVideoElement.volume === 0;
1661
+ if (!trackingFired.start) {
1662
+ trackingFired.lastMuted = muted;
1663
+ return;
1238
1664
  }
1665
+ if (muted === trackingFired.lastMuted) return;
1666
+ trackingFired.lastMuted = muted;
1667
+ fireTrackingPixels(muted ? currentAd.trackingUrls.mute : currentAd.trackingUrls.unmute);
1668
+ };
1669
+ var isTrackablePlayback = function isTrackablePlayback() {
1670
+ return adPlaying && !!currentAd && !!adVideoElement && trackingFired.start && !trackingFired.complete && !adVideoElement.ended;
1239
1671
  };
1240
1672
  var onPause = function onPause() {
1241
- if (currentAd && adVideoElement && !adVideoElement.ended) {
1673
+ continuousVisibleS = 0;
1674
+ if (isTrackablePlayback()) {
1242
1675
  fireTrackingPixels(currentAd.trackingUrls.pause);
1243
1676
  }
1244
1677
  };
1245
1678
  var onPlay = function onPlay() {
1246
- if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
1679
+ if (isTrackablePlayback()) {
1247
1680
  fireTrackingPixels(currentAd.trackingUrls.resume);
1248
1681
  }
1249
1682
  };
@@ -1256,6 +1689,10 @@ function createHlsAdPlayer(contentVideo, options) {
1256
1689
  type: "loadedmetadata",
1257
1690
  handler: onLoadedMetadata
1258
1691
  },
1692
+ {
1693
+ type: "canplay",
1694
+ handler: onCanPlay
1695
+ },
1259
1696
  {
1260
1697
  type: "playing",
1261
1698
  handler: onPlaying
@@ -1327,6 +1764,229 @@ function createHlsAdPlayer(contentVideo, options) {
1327
1764
  }
1328
1765
  adEventHandlers = [];
1329
1766
  }
1767
+ function handleAdClick() {
1768
+ if (!adPlaying || !currentAd) return;
1769
+ fireTrackingPixels(currentAd.trackingUrls.clickTracking);
1770
+ emit("ad_click", {
1771
+ adId: currentAd.id,
1772
+ clickThrough: currentAd.clickThrough
1773
+ });
1774
+ if (currentAd.clickThrough) {
1775
+ try {
1776
+ window.open(currentAd.clickThrough, "_blank", "noopener");
1777
+ } catch (error) {
1778
+ console.warn("[HlsAdPlayer] Failed to open ClickThrough URL:", error);
1779
+ }
1780
+ }
1781
+ }
1782
+ function reportCurrentAdError(errorCode) {
1783
+ if (!currentAd) return;
1784
+ resolvedAds.add(currentAd);
1785
+ fireTrackingPixels(currentAd.trackingUrls.error, {
1786
+ errorCode: errorCode
1787
+ });
1788
+ }
1789
+ function fireNotUsedForUnplayedAds() {
1790
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1791
+ try {
1792
+ for(var _iterator = podAds[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1793
+ var ad = _step.value;
1794
+ if (resolvedAds.has(ad)) continue;
1795
+ resolvedAds.add(ad);
1796
+ fireTrackingPixels(ad.trackingUrls.notUsed, {
1797
+ ad: ad
1798
+ });
1799
+ }
1800
+ } catch (err) {
1801
+ _didIteratorError = true;
1802
+ _iteratorError = err;
1803
+ } finally{
1804
+ try {
1805
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1806
+ _iterator.return();
1807
+ }
1808
+ } finally{
1809
+ if (_didIteratorError) {
1810
+ throw _iteratorError;
1811
+ }
1812
+ }
1813
+ }
1814
+ }
1815
+ function sampleViewability() {
1816
+ if (!currentAd || !adVideoElement || !viewObserver || !trackingFired.impression || trackingFired.viewabilitySettled) {
1817
+ return;
1818
+ }
1819
+ var now = adVideoElement.currentTime;
1820
+ var inView = visibleRatio >= VIEWABLE_MIN_VISIBLE_RATIO && document.visibilityState === "visible" && !adVideoElement.paused;
1821
+ if (!inView) {
1822
+ continuousVisibleS = 0;
1823
+ } else if (lastViewSampleTime !== void 0 && now >= lastViewSampleTime) {
1824
+ continuousVisibleS += now - lastViewSampleTime;
1825
+ }
1826
+ lastViewSampleTime = now;
1827
+ if (continuousVisibleS >= VIEWABLE_MIN_CONTINUOUS_S) {
1828
+ trackingFired.viewabilitySettled = true;
1829
+ fireTrackingPixels(currentAd.trackingUrls.viewable);
1830
+ }
1831
+ }
1832
+ function settleViewability() {
1833
+ if (!currentAd || !trackingFired.impression || trackingFired.viewabilitySettled) {
1834
+ return;
1835
+ }
1836
+ trackingFired.viewabilitySettled = true;
1837
+ fireTrackingPixels(viewObserver ? currentAd.trackingUrls.notViewable : currentAd.trackingUrls.viewUndetermined);
1838
+ }
1839
+ function handleFullscreenChange() {
1840
+ var _document_fullscreenElement;
1841
+ if (!adPlaying || !currentAd || !adContainerEl || !trackingFired.start) return;
1842
+ var fullscreenEl = (_document_fullscreenElement = document.fullscreenElement) !== null && _document_fullscreenElement !== void 0 ? _document_fullscreenElement : document.webkitFullscreenElement;
1843
+ var expanded = !!fullscreenEl && fullscreenEl.contains(adContainerEl);
1844
+ if (expanded === lastPlayerExpanded) return;
1845
+ lastPlayerExpanded = expanded;
1846
+ var urls = currentAd.trackingUrls;
1847
+ fireTrackingPixels(expanded ? urls.fullscreen.concat(urls.playerExpand) : urls.exitFullscreen.concat(urls.playerCollapse));
1848
+ }
1849
+ function attachContainerHandlers() {
1850
+ if (!adContainerEl || containerHandlers.length > 0) return;
1851
+ var onClick = function onClick() {
1852
+ return handleAdClick();
1853
+ };
1854
+ var onInteraction = function onInteraction(event) {
1855
+ if (adPlaying) emit("ad_interaction", event);
1856
+ };
1857
+ containerHandlers = [
1858
+ {
1859
+ type: "click",
1860
+ handler: onClick
1861
+ },
1862
+ {
1863
+ type: "mousedown",
1864
+ handler: onInteraction
1865
+ },
1866
+ {
1867
+ type: "touchstart",
1868
+ handler: onInteraction
1869
+ }
1870
+ ];
1871
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1872
+ try {
1873
+ for(var _iterator = containerHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1874
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
1875
+ adContainerEl.addEventListener(type, handler);
1876
+ }
1877
+ } catch (err) {
1878
+ _didIteratorError = true;
1879
+ _iteratorError = err;
1880
+ } finally{
1881
+ try {
1882
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1883
+ _iterator.return();
1884
+ }
1885
+ } finally{
1886
+ if (_didIteratorError) {
1887
+ throw _iteratorError;
1888
+ }
1889
+ }
1890
+ }
1891
+ var onFullscreenChange = function onFullscreenChange() {
1892
+ return handleFullscreenChange();
1893
+ };
1894
+ documentHandlers = [
1895
+ {
1896
+ type: "fullscreenchange",
1897
+ handler: onFullscreenChange
1898
+ },
1899
+ {
1900
+ type: "webkitfullscreenchange",
1901
+ handler: onFullscreenChange
1902
+ }
1903
+ ];
1904
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
1905
+ try {
1906
+ for(var _iterator1 = documentHandlers[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
1907
+ var _step_value1 = _step1.value, type1 = _step_value1.type, handler1 = _step_value1.handler;
1908
+ document.addEventListener(type1, handler1);
1909
+ }
1910
+ } catch (err) {
1911
+ _didIteratorError1 = true;
1912
+ _iteratorError1 = err;
1913
+ } finally{
1914
+ try {
1915
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
1916
+ _iterator1.return();
1917
+ }
1918
+ } finally{
1919
+ if (_didIteratorError1) {
1920
+ throw _iteratorError1;
1921
+ }
1922
+ }
1923
+ }
1924
+ if (typeof IntersectionObserver !== "undefined") {
1925
+ viewObserver = new IntersectionObserver(function(entries) {
1926
+ var entry = entries[entries.length - 1];
1927
+ if (entry) {
1928
+ visibleRatio = entry.isIntersecting ? entry.intersectionRatio : 0;
1929
+ }
1930
+ }, {
1931
+ threshold: [
1932
+ 0,
1933
+ 0.25,
1934
+ 0.5,
1935
+ 0.75,
1936
+ 1
1937
+ ]
1938
+ });
1939
+ viewObserver.observe(adContainerEl);
1940
+ }
1941
+ }
1942
+ function detachContainerHandlers() {
1943
+ if (adContainerEl) {
1944
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1945
+ try {
1946
+ for(var _iterator = containerHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1947
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
1948
+ adContainerEl.removeEventListener(type, handler);
1949
+ }
1950
+ } catch (err) {
1951
+ _didIteratorError = true;
1952
+ _iteratorError = err;
1953
+ } finally{
1954
+ try {
1955
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1956
+ _iterator.return();
1957
+ }
1958
+ } finally{
1959
+ if (_didIteratorError) {
1960
+ throw _iteratorError;
1961
+ }
1962
+ }
1963
+ }
1964
+ }
1965
+ containerHandlers = [];
1966
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
1967
+ try {
1968
+ for(var _iterator1 = documentHandlers[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
1969
+ var _step_value1 = _step1.value, type1 = _step_value1.type, handler1 = _step_value1.handler;
1970
+ document.removeEventListener(type1, handler1);
1971
+ }
1972
+ } catch (err) {
1973
+ _didIteratorError1 = true;
1974
+ _iteratorError1 = err;
1975
+ } finally{
1976
+ try {
1977
+ if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
1978
+ _iterator1.return();
1979
+ }
1980
+ } finally{
1981
+ if (_didIteratorError1) {
1982
+ throw _iteratorError1;
1983
+ }
1984
+ }
1985
+ }
1986
+ documentHandlers = [];
1987
+ viewObserver === null || viewObserver === void 0 ? void 0 : viewObserver.disconnect();
1988
+ viewObserver = void 0;
1989
+ }
1330
1990
  function setAdPlayingFlag(isPlaying) {
1331
1991
  if (isPlaying) {
1332
1992
  contentVideo.dataset.stormcloudAdPlaying = "true";
@@ -1334,15 +1994,10 @@ function createHlsAdPlayer(contentVideo, options) {
1334
1994
  delete contentVideo.dataset.stormcloudAdPlaying;
1335
1995
  }
1336
1996
  }
1337
- function resetQuartileTracking(preserveImpression) {
1338
- trackingFired = {
1339
- impression: preserveImpression ? trackingFired.impression : false,
1340
- start: false,
1341
- firstQuartile: false,
1342
- midpoint: false,
1343
- thirdQuartile: false,
1344
- complete: false
1345
- };
1997
+ function resetAdTracking() {
1998
+ trackingFired = createTrackingState();
1999
+ continuousVisibleS = 0;
2000
+ lastViewSampleTime = void 0;
1346
2001
  }
1347
2002
  function isRvfcSupported(video) {
1348
2003
  return typeof video.requestVideoFrameCallback === "function";
@@ -1448,13 +2103,12 @@ function createHlsAdPlayer(contentVideo, options) {
1448
2103
  if (podIndex >= podAds.length - 1) {
1449
2104
  return false;
1450
2105
  }
2106
+ settleViewability();
1451
2107
  podIndex++;
1452
2108
  currentAd = podAds[podIndex];
1453
2109
  currentAdMediaFile = void 0;
1454
- resetQuartileTracking(false);
2110
+ resetAdTracking();
1455
2111
  if (currentAd) {
1456
- fireTrackingPixels(currentAd.trackingUrls.impression);
1457
- trackingFired.impression = true;
1458
2112
  console.log("[HlsAdPlayer] Advancing to next pod ad (".concat(podIndex + 1, "/").concat(podAds.length, "): ").concat(currentAd.title, ", duration: ").concat(currentAd.duration, "s"));
1459
2113
  }
1460
2114
  clearStallWatchdog();
@@ -1492,11 +2146,7 @@ function createHlsAdPlayer(contentVideo, options) {
1492
2146
  function handleAdStall() {
1493
2147
  console.warn("[HlsAdPlayer] Ad playback stalled (no progress) - recovering to avoid a blank frame");
1494
2148
  clearStallWatchdog();
1495
- if (currentAd) {
1496
- fireTrackingPixels(currentAd.trackingUrls.error, {
1497
- errorCode: VAST_ERROR_MEDIA_DISPLAY
1498
- });
1499
- }
2149
+ reportCurrentAdError(VAST_ERROR_MEDIA_DISPLAY);
1500
2150
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1501
2151
  return;
1502
2152
  }
@@ -1562,11 +2212,7 @@ function createHlsAdPlayer(contentVideo, options) {
1562
2212
  function handleVideoDecodeFailure() {
1563
2213
  console.warn("[HlsAdPlayer] Ad audio is advancing but no video frames decoded (black screen) - skipping this creative");
1564
2214
  clearStallWatchdog();
1565
- if (currentAd) {
1566
- fireTrackingPixels(currentAd.trackingUrls.error, {
1567
- errorCode: VAST_ERROR_MEDIA_DISPLAY
1568
- });
1569
- }
2215
+ reportCurrentAdError(VAST_ERROR_MEDIA_DISPLAY);
1570
2216
  if (podIndex < podAds.length - 1 && advanceToNextPodAd()) {
1571
2217
  return;
1572
2218
  }
@@ -1621,6 +2267,7 @@ function createHlsAdPlayer(contentVideo, options) {
1621
2267
  }
1622
2268
  function handleAdComplete() {
1623
2269
  console.log("[HlsAdPlayer] Handling ad completion");
2270
+ settleViewability();
1624
2271
  clearStallWatchdog();
1625
2272
  adPlaying = false;
1626
2273
  setAdPlayingFlag(false);
@@ -1644,6 +2291,7 @@ function createHlsAdPlayer(contentVideo, options) {
1644
2291
  }
1645
2292
  function handleAdError() {
1646
2293
  console.log("[HlsAdPlayer] Handling ad error");
2294
+ settleViewability();
1647
2295
  clearStallWatchdog();
1648
2296
  adPlaying = false;
1649
2297
  setAdPlayingFlag(false);
@@ -1676,6 +2324,7 @@ function createHlsAdPlayer(contentVideo, options) {
1676
2324
  adContainerEl = container;
1677
2325
  }
1678
2326
  contentVideo[AD_CONTAINER_PROP] = adContainerEl;
2327
+ attachContainerHandlers();
1679
2328
  },
1680
2329
  requestAds: function requestAds(vastTagUrl) {
1681
2330
  return _async_to_generator(function() {
@@ -1738,10 +2387,6 @@ function createHlsAdPlayer(contentVideo, options) {
1738
2387
  currentAd = ads[0];
1739
2388
  currentAdMediaFile = void 0;
1740
2389
  console.log("[HlsAdPlayer] Pod parsed: ".concat(ads.length, ' ad(s), first="').concat(currentAd === null || currentAd === void 0 ? void 0 : currentAd.title, '", duration=').concat(currentAd === null || currentAd === void 0 ? void 0 : currentAd.duration, "s"));
1741
- if (currentAd) {
1742
- fireTrackingPixels(currentAd.trackingUrls.impression);
1743
- trackingFired.impression = true;
1744
- }
1745
2390
  return [
1746
2391
  2,
1747
2392
  Promise.resolve()
@@ -1781,7 +2426,7 @@ function createHlsAdPlayer(contentVideo, options) {
1781
2426
  contentVideo[AD_VIDEO_PROP] = adVideoElement;
1782
2427
  }
1783
2428
  setupAdEventListeners();
1784
- resetQuartileTracking(true);
2429
+ resetAdTracking();
1785
2430
  contentVolume = contentVideo.volume;
1786
2431
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1787
2432
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
@@ -1852,6 +2497,8 @@ function createHlsAdPlayer(contentVideo, options) {
1852
2497
  var previousMutedState;
1853
2498
  return _ts_generator(this, function(_state) {
1854
2499
  console.log("[HlsAdPlayer] Stopping ad");
2500
+ settleViewability();
2501
+ fireNotUsedForUnplayedAds();
1855
2502
  clearStallWatchdog();
1856
2503
  adPlaying = false;
1857
2504
  setAdPlayingFlag(false);
@@ -1882,6 +2529,8 @@ function createHlsAdPlayer(contentVideo, options) {
1882
2529
  },
1883
2530
  destroy: function destroy() {
1884
2531
  console.log("[HlsAdPlayer] Destroying");
2532
+ settleViewability();
2533
+ fireNotUsedForUnplayedAds();
1885
2534
  destroyed = true;
1886
2535
  clearStallWatchdog();
1887
2536
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
@@ -1910,6 +2559,7 @@ function createHlsAdPlayer(contentVideo, options) {
1910
2559
  contentVideo.muted = originalMutedState;
1911
2560
  contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
1912
2561
  teardownAdEventListeners();
2562
+ detachContainerHandlers();
1913
2563
  releaseAdDecoder();
1914
2564
  currentAd = void 0;
1915
2565
  currentAdMediaFile = void 0;