stormcloud-video-player 0.8.46 → 0.8.47

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.
@@ -388,15 +388,19 @@ var import_react = __toESM(require("react"), 1);
388
388
  var import_hls = __toESM(require("hls.js"), 1);
389
389
  var MAX_VAST_WRAPPER_DEPTH = 5;
390
390
  function createHlsAdPlayer(contentVideo, options) {
391
+ var _contentVideo_AD_VIDEO_PROP, _contentVideo_AD_CONTAINER_PROP;
391
392
  var adPlaying = false;
392
393
  var originalMutedState = false;
393
394
  var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
394
395
  var listeners = /* @__PURE__ */ new Map();
395
396
  var licenseKey = options === null || options === void 0 ? void 0 : options.licenseKey;
396
397
  var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
397
- var adVideoElement;
398
+ var AD_CONTAINER_PROP = "__stormcloudAdContainer";
399
+ var AD_VIDEO_PROP = "__stormcloudAdVideo";
400
+ var adVideoElement = (_contentVideo_AD_VIDEO_PROP = contentVideo[AD_VIDEO_PROP]) !== null && _contentVideo_AD_VIDEO_PROP !== void 0 ? _contentVideo_AD_VIDEO_PROP : void 0;
398
401
  var adHls;
399
- var adContainerEl;
402
+ var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
403
+ var adEventHandlers = [];
400
404
  var currentAd;
401
405
  var podAds = [];
402
406
  var podIndex = 0;
@@ -1040,7 +1044,8 @@ function createHlsAdPlayer(contentVideo, options) {
1040
1044
  }
1041
1045
  function setupAdEventListeners() {
1042
1046
  if (!adVideoElement || !currentAd) return;
1043
- adVideoElement.addEventListener("timeupdate", function() {
1047
+ if (adEventHandlers.length > 0) return;
1048
+ var onTimeUpdate = function onTimeUpdate() {
1044
1049
  if (!currentAd || !adVideoElement) return;
1045
1050
  noteAdProgress();
1046
1051
  var progress = adVideoElement.currentTime / currentAd.duration;
@@ -1056,15 +1061,15 @@ function createHlsAdPlayer(contentVideo, options) {
1056
1061
  trackingFired.thirdQuartile = true;
1057
1062
  fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
1058
1063
  }
1059
- });
1060
- adVideoElement.addEventListener("playing", function() {
1064
+ };
1065
+ var onPlaying = function onPlaying() {
1061
1066
  startStallWatchdog();
1062
1067
  if (!currentAd || trackingFired.start) return;
1063
1068
  trackingFired.start = true;
1064
1069
  fireTrackingPixels(currentAd.trackingUrls.start);
1065
1070
  console.log("[HlsAdPlayer] Ad started playing");
1066
- });
1067
- adVideoElement.addEventListener("ended", function() {
1071
+ };
1072
+ var onEnded = function onEnded() {
1068
1073
  if (!currentAd || trackingFired.complete) return;
1069
1074
  trackingFired.complete = true;
1070
1075
  fireTrackingPixels(currentAd.trackingUrls.complete);
@@ -1073,8 +1078,8 @@ function createHlsAdPlayer(contentVideo, options) {
1073
1078
  return;
1074
1079
  }
1075
1080
  handleAdComplete();
1076
- });
1077
- adVideoElement.addEventListener("error", function(e) {
1081
+ };
1082
+ var onError = function onError(e) {
1078
1083
  if (!adPlaying) return;
1079
1084
  console.error("[HlsAdPlayer] Ad video error:", e);
1080
1085
  if (currentAd) {
@@ -1084,25 +1089,100 @@ function createHlsAdPlayer(contentVideo, options) {
1084
1089
  return;
1085
1090
  }
1086
1091
  handleAdError();
1087
- });
1088
- adVideoElement.addEventListener("volumechange", function() {
1089
- if (!currentAd) return;
1092
+ };
1093
+ var onVolumeChange = function onVolumeChange() {
1094
+ if (!currentAd || !adVideoElement) return;
1090
1095
  if (adVideoElement.muted) {
1091
1096
  fireTrackingPixels(currentAd.trackingUrls.mute);
1092
1097
  } else {
1093
1098
  fireTrackingPixels(currentAd.trackingUrls.unmute);
1094
1099
  }
1095
- });
1096
- adVideoElement.addEventListener("pause", function() {
1097
- if (currentAd && !adVideoElement.ended) {
1100
+ };
1101
+ var onPause = function onPause() {
1102
+ if (currentAd && adVideoElement && !adVideoElement.ended) {
1098
1103
  fireTrackingPixels(currentAd.trackingUrls.pause);
1099
1104
  }
1100
- });
1101
- adVideoElement.addEventListener("play", function() {
1102
- if (currentAd && adVideoElement.currentTime > 0) {
1105
+ };
1106
+ var onPlay = function onPlay() {
1107
+ if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
1103
1108
  fireTrackingPixels(currentAd.trackingUrls.resume);
1104
1109
  }
1105
- });
1110
+ };
1111
+ adEventHandlers = [
1112
+ {
1113
+ type: "timeupdate",
1114
+ handler: onTimeUpdate
1115
+ },
1116
+ {
1117
+ type: "playing",
1118
+ handler: onPlaying
1119
+ },
1120
+ {
1121
+ type: "ended",
1122
+ handler: onEnded
1123
+ },
1124
+ {
1125
+ type: "error",
1126
+ handler: onError
1127
+ },
1128
+ {
1129
+ type: "volumechange",
1130
+ handler: onVolumeChange
1131
+ },
1132
+ {
1133
+ type: "pause",
1134
+ handler: onPause
1135
+ },
1136
+ {
1137
+ type: "play",
1138
+ handler: onPlay
1139
+ }
1140
+ ];
1141
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1142
+ try {
1143
+ for(var _iterator = adEventHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1144
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
1145
+ adVideoElement.addEventListener(type, handler);
1146
+ }
1147
+ } catch (err) {
1148
+ _didIteratorError = true;
1149
+ _iteratorError = err;
1150
+ } finally{
1151
+ try {
1152
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1153
+ _iterator.return();
1154
+ }
1155
+ } finally{
1156
+ if (_didIteratorError) {
1157
+ throw _iteratorError;
1158
+ }
1159
+ }
1160
+ }
1161
+ }
1162
+ function teardownAdEventListeners() {
1163
+ if (adVideoElement) {
1164
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1165
+ try {
1166
+ for(var _iterator = adEventHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1167
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
1168
+ adVideoElement.removeEventListener(type, handler);
1169
+ }
1170
+ } catch (err) {
1171
+ _didIteratorError = true;
1172
+ _iteratorError = err;
1173
+ } finally{
1174
+ try {
1175
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1176
+ _iterator.return();
1177
+ }
1178
+ } finally{
1179
+ if (_didIteratorError) {
1180
+ throw _iteratorError;
1181
+ }
1182
+ }
1183
+ }
1184
+ }
1185
+ adEventHandlers = [];
1106
1186
  }
1107
1187
  function setAdPlayingFlag(isPlaying) {
1108
1188
  if (isPlaying) {
@@ -1248,15 +1328,13 @@ function createHlsAdPlayer(contentVideo, options) {
1248
1328
  adHls = void 0;
1249
1329
  }
1250
1330
  if (adVideoElement) {
1251
- adVideoElement.pause();
1252
- adVideoElement.removeAttribute("src");
1253
1331
  try {
1332
+ adVideoElement.pause();
1333
+ adVideoElement.removeAttribute("src");
1254
1334
  adVideoElement.load();
1255
1335
  } catch (error) {
1256
- console.warn("[HlsAdPlayer] adVideoElement.load() threw after src removal:", error);
1336
+ console.warn("[HlsAdPlayer] Error releasing ad decoder:", error);
1257
1337
  }
1258
- adVideoElement.remove();
1259
- adVideoElement = void 0;
1260
1338
  }
1261
1339
  if (adContainerEl) {
1262
1340
  adContainerEl.style.display = "none";
@@ -1319,6 +1397,7 @@ function createHlsAdPlayer(contentVideo, options) {
1319
1397
  (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1320
1398
  adContainerEl = container;
1321
1399
  }
1400
+ contentVideo[AD_CONTAINER_PROP] = adContainerEl;
1322
1401
  },
1323
1402
  requestAds: function requestAds(vastTagUrl) {
1324
1403
  return _async_to_generator(function() {
@@ -1421,8 +1500,9 @@ function createHlsAdPlayer(contentVideo, options) {
1421
1500
  if (!adVideoElement) {
1422
1501
  adVideoElement = createAdVideoElement();
1423
1502
  adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.appendChild(adVideoElement);
1424
- setupAdEventListeners();
1503
+ contentVideo[AD_VIDEO_PROP] = adVideoElement;
1425
1504
  }
1505
+ setupAdEventListeners();
1426
1506
  resetQuartileTracking(true);
1427
1507
  contentVolume = contentVideo.volume;
1428
1508
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
@@ -1550,11 +1630,8 @@ function createHlsAdPlayer(contentVideo, options) {
1550
1630
  setAdPlayingFlag(false);
1551
1631
  contentVideo.muted = originalMutedState;
1552
1632
  contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
1633
+ teardownAdEventListeners();
1553
1634
  releaseAdDecoder();
1554
- if (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.parentElement) {
1555
- adContainerEl.parentElement.removeChild(adContainerEl);
1556
- }
1557
- adContainerEl = void 0;
1558
1635
  currentAd = void 0;
1559
1636
  podAds = [];
1560
1637
  podIndex = 0;
@@ -3967,6 +4044,11 @@ function detectBrowser() {
3967
4044
  chromeVersion: chromeVersionNum
3968
4045
  };
3969
4046
  }
4047
+ function requiresMediaPipelineResetAfterAds() {
4048
+ var _browser_tizenVersion;
4049
+ var browser = detectBrowser();
4050
+ return browser.name === "Samsung Tizen" && ((_browser_tizenVersion = browser.tizenVersion) !== null && _browser_tizenVersion !== void 0 ? _browser_tizenVersion : 0) >= 5;
4051
+ }
3970
4052
  function getBrowserConfigOverrides() {
3971
4053
  var browser = detectBrowser();
3972
4054
  var overrides = {};
@@ -6728,30 +6810,49 @@ var HlsEngine = /*#__PURE__*/ function() {
6728
6810
  {
6729
6811
  key: "reloadLiveStream",
6730
6812
  value: function reloadLiveStream() {
6813
+ var _this = this;
6731
6814
  var hls = this.hls;
6732
6815
  if (!hls) {
6733
6816
  return;
6734
6817
  }
6735
6818
  if (this.debug) {
6736
- console.log("[StormcloudVideoPlayer] Hard-reloading live stream (detach \u2192 reset video \u2192 re-attach)");
6819
+ console.log("[StormcloudVideoPlayer] Hard-reloading live stream (destroy hls \u2192 reset video \u2192 fresh setupHls)");
6737
6820
  }
6738
6821
  try {
6739
6822
  this.reloadingLiveStream = true;
6740
6823
  hls.stopLoad();
6741
6824
  hls.detachMedia();
6825
+ hls.destroy();
6826
+ this.hls = void 0;
6742
6827
  try {
6743
6828
  this.video.removeAttribute("src");
6744
6829
  this.video.load();
6745
6830
  } catch (error) {
6746
6831
  console.warn("[StormcloudVideoPlayer] video.load() threw after src removal:", error);
6747
6832
  }
6748
- hls.attachMedia(this.video);
6749
6833
  } catch (error) {
6750
6834
  this.reloadingLiveStream = false;
6835
+ this.hls = void 0;
6751
6836
  if (this.debug) {
6752
- console.warn("[StormcloudVideoPlayer] Failed to hard-reload live stream:", error);
6837
+ console.warn("[StormcloudVideoPlayer] Failed to tear down during hard-reload:", error);
6753
6838
  }
6839
+ return;
6754
6840
  }
6841
+ var recreateDelayMs = 600;
6842
+ window.setTimeout(function() {
6843
+ if (_this.hls) {
6844
+ _this.reloadingLiveStream = false;
6845
+ return;
6846
+ }
6847
+ try {
6848
+ _this.setupHls();
6849
+ } catch (error) {
6850
+ _this.reloadingLiveStream = false;
6851
+ if (_this.debug) {
6852
+ console.warn("[StormcloudVideoPlayer] Failed to rebuild pipeline during hard-reload:", error);
6853
+ }
6854
+ }
6855
+ }, recreateDelayMs);
6755
6856
  }
6756
6857
  },
6757
6858
  {
@@ -8064,6 +8165,14 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8064
8165
  this.host.video.style.visibility = "visible";
8065
8166
  this.host.video.style.opacity = "1";
8066
8167
  if (this.host.isLiveStream()) {
8168
+ if (this.host.requiresMediaPipelineResetAfterAds()) {
8169
+ if (this.debug) {
8170
+ console.log("[StormcloudVideoPlayer] Live break end \u2014 hard-reloading stream to reacquire decoder (single-decoder platform)");
8171
+ }
8172
+ this.host.reloadLiveStream();
8173
+ this.monitorLiveResumeStall(this.host.video.currentTime);
8174
+ return;
8175
+ }
8067
8176
  var liveSyncPos = this.host.getLiveSyncPosition();
8068
8177
  if (liveSyncPos != null && liveSyncPos > this.host.video.currentTime) {
8069
8178
  if (this.debug) {
@@ -8125,9 +8234,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8125
8234
  key: "monitorLiveResumeStall",
8126
8235
  value: function monitorLiveResumeStall(resumeBaseline) {
8127
8236
  var _this = this;
8237
+ var needsReset = this.host.requiresMediaPipelineResetAfterAds();
8128
8238
  var pollIntervalMs = 1e3;
8129
- var graceMs = 5e3;
8130
- var recoveryCooldownMs = 5e3;
8239
+ var graceMs = needsReset ? 8e3 : 5e3;
8240
+ var recoveryCooldownMs = needsReset ? 7e3 : 5e3;
8131
8241
  var maxRecoveries = 3;
8132
8242
  var maxMonitorMs = 45e3;
8133
8243
  var startTime = Date.now();
@@ -8241,7 +8351,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8241
8351
  if (canRecover) {
8242
8352
  recoveries++;
8243
8353
  lastRecoveryAt = Date.now();
8244
- if (recoveries === 1) {
8354
+ if (needsReset) {
8355
+ if (_this.debug) {
8356
+ console.warn("[StormcloudVideoPlayer] Content still wedged after ad break — hard-reloading live stream (recovery ".concat(recoveries, "/").concat(maxRecoveries, ") — ").concat(_this.describeVideoState()));
8357
+ }
8358
+ _this.host.reloadLiveStream();
8359
+ } else if (recoveries === 1) {
8245
8360
  if (_this.debug) {
8246
8361
  console.warn("[StormcloudVideoPlayer] Content wedged after ad break — calling recoverMediaError() (recovery ".concat(recoveries, "/").concat(maxRecoveries, ") — ").concat(_this.describeVideoState()));
8247
8362
  }
@@ -8454,6 +8569,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8454
8569
  recoverMediaError: function recoverMediaError() {
8455
8570
  return _this.hlsEngine.recoverMediaError();
8456
8571
  },
8572
+ requiresMediaPipelineResetAfterAds: function requiresMediaPipelineResetAfterAds1() {
8573
+ return requiresMediaPipelineResetAfterAds();
8574
+ },
8457
8575
  generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
8458
8576
  return _this.generatePodVastUrl(base, breakDurationMs);
8459
8577
  }