stormcloud-video-player 0.8.46 → 0.8.48

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.
@@ -200,15 +200,19 @@ module.exports = __toCommonJS(hlsAdPlayer_exports);
200
200
  var import_hls = __toESM(require("hls.js"), 1);
201
201
  var MAX_VAST_WRAPPER_DEPTH = 5;
202
202
  function createHlsAdPlayer(contentVideo, options) {
203
+ var _contentVideo_AD_VIDEO_PROP, _contentVideo_AD_CONTAINER_PROP;
203
204
  var adPlaying = false;
204
205
  var originalMutedState = false;
205
206
  var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
206
207
  var listeners = /* @__PURE__ */ new Map();
207
208
  var licenseKey = options === null || options === void 0 ? void 0 : options.licenseKey;
208
209
  var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
209
- var adVideoElement;
210
+ var AD_CONTAINER_PROP = "__stormcloudAdContainer";
211
+ var AD_VIDEO_PROP = "__stormcloudAdVideo";
212
+ var adVideoElement = (_contentVideo_AD_VIDEO_PROP = contentVideo[AD_VIDEO_PROP]) !== null && _contentVideo_AD_VIDEO_PROP !== void 0 ? _contentVideo_AD_VIDEO_PROP : void 0;
210
213
  var adHls;
211
- var adContainerEl;
214
+ var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
215
+ var adEventHandlers = [];
212
216
  var currentAd;
213
217
  var podAds = [];
214
218
  var podIndex = 0;
@@ -363,6 +367,56 @@ function createHlsAdPlayer(contentVideo, options) {
363
367
  var url = mediaFile.url.toLowerCase();
364
368
  return type.startsWith("video/") || url.endsWith(".mp4") || url.includes(".mp4?");
365
369
  }
370
+ function isAudioMediaFile(mediaFile) {
371
+ var type = mediaFile.type.toLowerCase();
372
+ var url = (mediaFile.url.toLowerCase().split("?")[0] || "").trim();
373
+ 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");
374
+ }
375
+ function collectVideoMediaFiles(scope, verbose) {
376
+ var mediaFileElements = scope.querySelectorAll("MediaFile");
377
+ var mediaFiles = [];
378
+ if (verbose) {
379
+ console.log("[HlsAdPlayer] Found ".concat(mediaFileElements.length, " MediaFile element(s) in VAST XML"));
380
+ }
381
+ mediaFileElements.forEach(function(mf, index) {
382
+ var _mf_textContent;
383
+ var type = mf.getAttribute("type") || "";
384
+ var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
385
+ var width = mf.getAttribute("width") || "";
386
+ var height = mf.getAttribute("height") || "";
387
+ if (verbose) {
388
+ console.log("[HlsAdPlayer] MediaFile ".concat(index, ': type="').concat(type, '", url="').concat(url, '", width="').concat(width, '", height="').concat(height, '"'));
389
+ }
390
+ if (!url) {
391
+ if (verbose) {
392
+ console.warn("[HlsAdPlayer] MediaFile ".concat(index, " has empty URL"));
393
+ }
394
+ return;
395
+ }
396
+ var bitrateAttr = mf.getAttribute("bitrate");
397
+ var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
398
+ var mediaFile = {
399
+ url: url,
400
+ type: type,
401
+ width: parseInt(width || "1920", 10),
402
+ height: parseInt(height || "1080", 10),
403
+ bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
404
+ };
405
+ if (isAudioMediaFile(mediaFile)) {
406
+ console.warn("[HlsAdPlayer] MediaFile ".concat(index, ' skipped (audio-only, type="').concat(type, '") — audio ads are not played to avoid a black screen'));
407
+ return;
408
+ }
409
+ if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
410
+ mediaFiles.push(mediaFile);
411
+ if (verbose) {
412
+ console.log("[HlsAdPlayer] Added ".concat(isHlsMediaFile(mediaFile) ? "HLS" : "progressive", " MediaFile: ").concat(url));
413
+ }
414
+ } else if (verbose) {
415
+ console.log("[HlsAdPlayer] MediaFile ".concat(index, ' ignored (type="').concat(type, '" is not supported)'));
416
+ }
417
+ });
418
+ return mediaFiles;
419
+ }
366
420
  function createEmptyTrackingUrls() {
367
421
  return {
368
422
  impression: [],
@@ -450,37 +504,7 @@ function createHlsAdPlayer(contentVideo, options) {
450
504
  var durationText = ((_xmlDoc_querySelector3 = xmlDoc.querySelector("Duration")) === null || _xmlDoc_querySelector3 === void 0 ? void 0 : _xmlDoc_querySelector3.textContent) || "00:00:30";
451
505
  var durationParts = durationText.split(":");
452
506
  var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
453
- var mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
454
- var mediaFiles = [];
455
- console.log("[HlsAdPlayer] Found ".concat(mediaFileElements.length, " MediaFile element(s) in VAST XML"));
456
- mediaFileElements.forEach(function(mf, index) {
457
- var _mf_textContent;
458
- var type = mf.getAttribute("type") || "";
459
- var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
460
- var width = mf.getAttribute("width") || "";
461
- var height = mf.getAttribute("height") || "";
462
- console.log("[HlsAdPlayer] MediaFile ".concat(index, ': type="').concat(type, '", url="').concat(url, '", width="').concat(width, '", height="').concat(height, '"'));
463
- var mediaFile = {
464
- url: url,
465
- type: type,
466
- width: parseInt(width || "1920", 10),
467
- height: parseInt(height || "1080", 10),
468
- bitrate: void 0
469
- };
470
- if (!url) {
471
- console.warn("[HlsAdPlayer] MediaFile ".concat(index, " has empty URL"));
472
- return;
473
- }
474
- var bitrateAttr = mf.getAttribute("bitrate");
475
- var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
476
- mediaFile.bitrate = bitrateValue && bitrateValue > 0 ? bitrateValue : void 0;
477
- if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
478
- mediaFiles.push(mediaFile);
479
- console.log("[HlsAdPlayer] Added ".concat(isHlsMediaFile(mediaFile) ? "HLS" : "progressive", " MediaFile: ").concat(url));
480
- } else {
481
- console.log("[HlsAdPlayer] MediaFile ".concat(index, ' ignored (type="').concat(type, '" is not supported)'));
482
- }
483
- });
507
+ var mediaFiles = collectVideoMediaFiles(xmlDoc, true);
484
508
  if (mediaFiles.length === 0) {
485
509
  if (isNoAdAvailable) {
486
510
  console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
@@ -528,28 +552,7 @@ function createHlsAdPlayer(contentVideo, options) {
528
552
  var durationText = ((_adElement_querySelector3 = adElement.querySelector("Duration")) === null || _adElement_querySelector3 === void 0 ? void 0 : _adElement_querySelector3.textContent) || "00:00:30";
529
553
  var durationParts = durationText.split(":");
530
554
  var duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
531
- var mediaFileElements = adElement.querySelectorAll("MediaFile");
532
- var mediaFiles = [];
533
- mediaFileElements.forEach(function(mf) {
534
- var _mf_textContent;
535
- var type = mf.getAttribute("type") || "";
536
- var url = ((_mf_textContent = mf.textContent) === null || _mf_textContent === void 0 ? void 0 : _mf_textContent.trim()) || "";
537
- var width = mf.getAttribute("width") || "";
538
- var height = mf.getAttribute("height") || "";
539
- if (!url) return;
540
- var bitrateAttr = mf.getAttribute("bitrate");
541
- var bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
542
- var mediaFile = {
543
- url: url,
544
- type: type,
545
- width: parseInt(width || "1920", 10),
546
- height: parseInt(height || "1080", 10),
547
- bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
548
- };
549
- if (isHlsMediaFile(mediaFile) || isProgressiveMediaFile(mediaFile)) {
550
- mediaFiles.push(mediaFile);
551
- }
552
- });
555
+ var mediaFiles = collectVideoMediaFiles(adElement, false);
553
556
  if (mediaFiles.length === 0) {
554
557
  if (isNoAdAvailable) {
555
558
  console.warn("[HlsAdPlayer] Pod <Ad> indicates no ad available");
@@ -852,7 +855,8 @@ function createHlsAdPlayer(contentVideo, options) {
852
855
  }
853
856
  function setupAdEventListeners() {
854
857
  if (!adVideoElement || !currentAd) return;
855
- adVideoElement.addEventListener("timeupdate", function() {
858
+ if (adEventHandlers.length > 0) return;
859
+ var onTimeUpdate = function onTimeUpdate() {
856
860
  if (!currentAd || !adVideoElement) return;
857
861
  noteAdProgress();
858
862
  var progress = adVideoElement.currentTime / currentAd.duration;
@@ -868,15 +872,15 @@ function createHlsAdPlayer(contentVideo, options) {
868
872
  trackingFired.thirdQuartile = true;
869
873
  fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
870
874
  }
871
- });
872
- adVideoElement.addEventListener("playing", function() {
875
+ };
876
+ var onPlaying = function onPlaying() {
873
877
  startStallWatchdog();
874
878
  if (!currentAd || trackingFired.start) return;
875
879
  trackingFired.start = true;
876
880
  fireTrackingPixels(currentAd.trackingUrls.start);
877
881
  console.log("[HlsAdPlayer] Ad started playing");
878
- });
879
- adVideoElement.addEventListener("ended", function() {
882
+ };
883
+ var onEnded = function onEnded() {
880
884
  if (!currentAd || trackingFired.complete) return;
881
885
  trackingFired.complete = true;
882
886
  fireTrackingPixels(currentAd.trackingUrls.complete);
@@ -885,8 +889,8 @@ function createHlsAdPlayer(contentVideo, options) {
885
889
  return;
886
890
  }
887
891
  handleAdComplete();
888
- });
889
- adVideoElement.addEventListener("error", function(e) {
892
+ };
893
+ var onError = function onError(e) {
890
894
  if (!adPlaying) return;
891
895
  console.error("[HlsAdPlayer] Ad video error:", e);
892
896
  if (currentAd) {
@@ -896,25 +900,100 @@ function createHlsAdPlayer(contentVideo, options) {
896
900
  return;
897
901
  }
898
902
  handleAdError();
899
- });
900
- adVideoElement.addEventListener("volumechange", function() {
901
- if (!currentAd) return;
903
+ };
904
+ var onVolumeChange = function onVolumeChange() {
905
+ if (!currentAd || !adVideoElement) return;
902
906
  if (adVideoElement.muted) {
903
907
  fireTrackingPixels(currentAd.trackingUrls.mute);
904
908
  } else {
905
909
  fireTrackingPixels(currentAd.trackingUrls.unmute);
906
910
  }
907
- });
908
- adVideoElement.addEventListener("pause", function() {
909
- if (currentAd && !adVideoElement.ended) {
911
+ };
912
+ var onPause = function onPause() {
913
+ if (currentAd && adVideoElement && !adVideoElement.ended) {
910
914
  fireTrackingPixels(currentAd.trackingUrls.pause);
911
915
  }
912
- });
913
- adVideoElement.addEventListener("play", function() {
914
- if (currentAd && adVideoElement.currentTime > 0) {
916
+ };
917
+ var onPlay = function onPlay() {
918
+ if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
915
919
  fireTrackingPixels(currentAd.trackingUrls.resume);
916
920
  }
917
- });
921
+ };
922
+ adEventHandlers = [
923
+ {
924
+ type: "timeupdate",
925
+ handler: onTimeUpdate
926
+ },
927
+ {
928
+ type: "playing",
929
+ handler: onPlaying
930
+ },
931
+ {
932
+ type: "ended",
933
+ handler: onEnded
934
+ },
935
+ {
936
+ type: "error",
937
+ handler: onError
938
+ },
939
+ {
940
+ type: "volumechange",
941
+ handler: onVolumeChange
942
+ },
943
+ {
944
+ type: "pause",
945
+ handler: onPause
946
+ },
947
+ {
948
+ type: "play",
949
+ handler: onPlay
950
+ }
951
+ ];
952
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
953
+ try {
954
+ for(var _iterator = adEventHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
955
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
956
+ adVideoElement.addEventListener(type, handler);
957
+ }
958
+ } catch (err) {
959
+ _didIteratorError = true;
960
+ _iteratorError = err;
961
+ } finally{
962
+ try {
963
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
964
+ _iterator.return();
965
+ }
966
+ } finally{
967
+ if (_didIteratorError) {
968
+ throw _iteratorError;
969
+ }
970
+ }
971
+ }
972
+ }
973
+ function teardownAdEventListeners() {
974
+ if (adVideoElement) {
975
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
976
+ try {
977
+ for(var _iterator = adEventHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
978
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
979
+ adVideoElement.removeEventListener(type, handler);
980
+ }
981
+ } catch (err) {
982
+ _didIteratorError = true;
983
+ _iteratorError = err;
984
+ } finally{
985
+ try {
986
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
987
+ _iterator.return();
988
+ }
989
+ } finally{
990
+ if (_didIteratorError) {
991
+ throw _iteratorError;
992
+ }
993
+ }
994
+ }
995
+ }
996
+ adEventHandlers = [];
918
997
  }
919
998
  function setAdPlayingFlag(isPlaying) {
920
999
  if (isPlaying) {
@@ -1060,15 +1139,13 @@ function createHlsAdPlayer(contentVideo, options) {
1060
1139
  adHls = void 0;
1061
1140
  }
1062
1141
  if (adVideoElement) {
1063
- adVideoElement.pause();
1064
- adVideoElement.removeAttribute("src");
1065
1142
  try {
1143
+ adVideoElement.pause();
1144
+ adVideoElement.removeAttribute("src");
1066
1145
  adVideoElement.load();
1067
1146
  } catch (error) {
1068
- console.warn("[HlsAdPlayer] adVideoElement.load() threw after src removal:", error);
1147
+ console.warn("[HlsAdPlayer] Error releasing ad decoder:", error);
1069
1148
  }
1070
- adVideoElement.remove();
1071
- adVideoElement = void 0;
1072
1149
  }
1073
1150
  if (adContainerEl) {
1074
1151
  adContainerEl.style.display = "none";
@@ -1131,6 +1208,7 @@ function createHlsAdPlayer(contentVideo, options) {
1131
1208
  (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1132
1209
  adContainerEl = container;
1133
1210
  }
1211
+ contentVideo[AD_CONTAINER_PROP] = adContainerEl;
1134
1212
  },
1135
1213
  requestAds: function requestAds(vastTagUrl) {
1136
1214
  return _async_to_generator(function() {
@@ -1233,8 +1311,9 @@ function createHlsAdPlayer(contentVideo, options) {
1233
1311
  if (!adVideoElement) {
1234
1312
  adVideoElement = createAdVideoElement();
1235
1313
  adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.appendChild(adVideoElement);
1236
- setupAdEventListeners();
1314
+ contentVideo[AD_VIDEO_PROP] = adVideoElement;
1237
1315
  }
1316
+ setupAdEventListeners();
1238
1317
  resetQuartileTracking(true);
1239
1318
  contentVolume = contentVideo.volume;
1240
1319
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
@@ -1362,11 +1441,8 @@ function createHlsAdPlayer(contentVideo, options) {
1362
1441
  setAdPlayingFlag(false);
1363
1442
  contentVideo.muted = originalMutedState;
1364
1443
  contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
1444
+ teardownAdEventListeners();
1365
1445
  releaseAdDecoder();
1366
- if (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.parentElement) {
1367
- adContainerEl.parentElement.removeChild(adContainerEl);
1368
- }
1369
- adContainerEl = void 0;
1370
1446
  currentAd = void 0;
1371
1447
  podAds = [];
1372
1448
  podIndex = 0;