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.
@@ -402,15 +402,19 @@ var import_react = require("react");
402
402
  var import_hls = __toESM(require("hls.js"), 1);
403
403
  var MAX_VAST_WRAPPER_DEPTH = 5;
404
404
  function createHlsAdPlayer(contentVideo, options) {
405
+ var _contentVideo_AD_VIDEO_PROP, _contentVideo_AD_CONTAINER_PROP;
405
406
  var adPlaying = false;
406
407
  var originalMutedState = false;
407
408
  var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
408
409
  var listeners = /* @__PURE__ */ new Map();
409
410
  var licenseKey = options === null || options === void 0 ? void 0 : options.licenseKey;
410
411
  var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
411
- var adVideoElement;
412
+ var AD_CONTAINER_PROP = "__stormcloudAdContainer";
413
+ var AD_VIDEO_PROP = "__stormcloudAdVideo";
414
+ var adVideoElement = (_contentVideo_AD_VIDEO_PROP = contentVideo[AD_VIDEO_PROP]) !== null && _contentVideo_AD_VIDEO_PROP !== void 0 ? _contentVideo_AD_VIDEO_PROP : void 0;
412
415
  var adHls;
413
- var adContainerEl;
416
+ var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
417
+ var adEventHandlers = [];
414
418
  var currentAd;
415
419
  var podAds = [];
416
420
  var podIndex = 0;
@@ -1054,7 +1058,8 @@ function createHlsAdPlayer(contentVideo, options) {
1054
1058
  }
1055
1059
  function setupAdEventListeners() {
1056
1060
  if (!adVideoElement || !currentAd) return;
1057
- adVideoElement.addEventListener("timeupdate", function() {
1061
+ if (adEventHandlers.length > 0) return;
1062
+ var onTimeUpdate = function onTimeUpdate() {
1058
1063
  if (!currentAd || !adVideoElement) return;
1059
1064
  noteAdProgress();
1060
1065
  var progress = adVideoElement.currentTime / currentAd.duration;
@@ -1070,15 +1075,15 @@ function createHlsAdPlayer(contentVideo, options) {
1070
1075
  trackingFired.thirdQuartile = true;
1071
1076
  fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
1072
1077
  }
1073
- });
1074
- adVideoElement.addEventListener("playing", function() {
1078
+ };
1079
+ var onPlaying = function onPlaying() {
1075
1080
  startStallWatchdog();
1076
1081
  if (!currentAd || trackingFired.start) return;
1077
1082
  trackingFired.start = true;
1078
1083
  fireTrackingPixels(currentAd.trackingUrls.start);
1079
1084
  console.log("[HlsAdPlayer] Ad started playing");
1080
- });
1081
- adVideoElement.addEventListener("ended", function() {
1085
+ };
1086
+ var onEnded = function onEnded() {
1082
1087
  if (!currentAd || trackingFired.complete) return;
1083
1088
  trackingFired.complete = true;
1084
1089
  fireTrackingPixels(currentAd.trackingUrls.complete);
@@ -1087,8 +1092,8 @@ function createHlsAdPlayer(contentVideo, options) {
1087
1092
  return;
1088
1093
  }
1089
1094
  handleAdComplete();
1090
- });
1091
- adVideoElement.addEventListener("error", function(e) {
1095
+ };
1096
+ var onError = function onError(e) {
1092
1097
  if (!adPlaying) return;
1093
1098
  console.error("[HlsAdPlayer] Ad video error:", e);
1094
1099
  if (currentAd) {
@@ -1098,25 +1103,100 @@ function createHlsAdPlayer(contentVideo, options) {
1098
1103
  return;
1099
1104
  }
1100
1105
  handleAdError();
1101
- });
1102
- adVideoElement.addEventListener("volumechange", function() {
1103
- if (!currentAd) return;
1106
+ };
1107
+ var onVolumeChange = function onVolumeChange() {
1108
+ if (!currentAd || !adVideoElement) return;
1104
1109
  if (adVideoElement.muted) {
1105
1110
  fireTrackingPixels(currentAd.trackingUrls.mute);
1106
1111
  } else {
1107
1112
  fireTrackingPixels(currentAd.trackingUrls.unmute);
1108
1113
  }
1109
- });
1110
- adVideoElement.addEventListener("pause", function() {
1111
- if (currentAd && !adVideoElement.ended) {
1114
+ };
1115
+ var onPause = function onPause() {
1116
+ if (currentAd && adVideoElement && !adVideoElement.ended) {
1112
1117
  fireTrackingPixels(currentAd.trackingUrls.pause);
1113
1118
  }
1114
- });
1115
- adVideoElement.addEventListener("play", function() {
1116
- if (currentAd && adVideoElement.currentTime > 0) {
1119
+ };
1120
+ var onPlay = function onPlay() {
1121
+ if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
1117
1122
  fireTrackingPixels(currentAd.trackingUrls.resume);
1118
1123
  }
1119
- });
1124
+ };
1125
+ adEventHandlers = [
1126
+ {
1127
+ type: "timeupdate",
1128
+ handler: onTimeUpdate
1129
+ },
1130
+ {
1131
+ type: "playing",
1132
+ handler: onPlaying
1133
+ },
1134
+ {
1135
+ type: "ended",
1136
+ handler: onEnded
1137
+ },
1138
+ {
1139
+ type: "error",
1140
+ handler: onError
1141
+ },
1142
+ {
1143
+ type: "volumechange",
1144
+ handler: onVolumeChange
1145
+ },
1146
+ {
1147
+ type: "pause",
1148
+ handler: onPause
1149
+ },
1150
+ {
1151
+ type: "play",
1152
+ handler: onPlay
1153
+ }
1154
+ ];
1155
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1156
+ try {
1157
+ for(var _iterator = adEventHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1158
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
1159
+ adVideoElement.addEventListener(type, handler);
1160
+ }
1161
+ } catch (err) {
1162
+ _didIteratorError = true;
1163
+ _iteratorError = err;
1164
+ } finally{
1165
+ try {
1166
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1167
+ _iterator.return();
1168
+ }
1169
+ } finally{
1170
+ if (_didIteratorError) {
1171
+ throw _iteratorError;
1172
+ }
1173
+ }
1174
+ }
1175
+ }
1176
+ function teardownAdEventListeners() {
1177
+ if (adVideoElement) {
1178
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1179
+ try {
1180
+ for(var _iterator = adEventHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1181
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
1182
+ adVideoElement.removeEventListener(type, handler);
1183
+ }
1184
+ } catch (err) {
1185
+ _didIteratorError = true;
1186
+ _iteratorError = err;
1187
+ } finally{
1188
+ try {
1189
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1190
+ _iterator.return();
1191
+ }
1192
+ } finally{
1193
+ if (_didIteratorError) {
1194
+ throw _iteratorError;
1195
+ }
1196
+ }
1197
+ }
1198
+ }
1199
+ adEventHandlers = [];
1120
1200
  }
1121
1201
  function setAdPlayingFlag(isPlaying) {
1122
1202
  if (isPlaying) {
@@ -1262,15 +1342,13 @@ function createHlsAdPlayer(contentVideo, options) {
1262
1342
  adHls = void 0;
1263
1343
  }
1264
1344
  if (adVideoElement) {
1265
- adVideoElement.pause();
1266
- adVideoElement.removeAttribute("src");
1267
1345
  try {
1346
+ adVideoElement.pause();
1347
+ adVideoElement.removeAttribute("src");
1268
1348
  adVideoElement.load();
1269
1349
  } catch (error) {
1270
- console.warn("[HlsAdPlayer] adVideoElement.load() threw after src removal:", error);
1350
+ console.warn("[HlsAdPlayer] Error releasing ad decoder:", error);
1271
1351
  }
1272
- adVideoElement.remove();
1273
- adVideoElement = void 0;
1274
1352
  }
1275
1353
  if (adContainerEl) {
1276
1354
  adContainerEl.style.display = "none";
@@ -1333,6 +1411,7 @@ function createHlsAdPlayer(contentVideo, options) {
1333
1411
  (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1334
1412
  adContainerEl = container;
1335
1413
  }
1414
+ contentVideo[AD_CONTAINER_PROP] = adContainerEl;
1336
1415
  },
1337
1416
  requestAds: function requestAds(vastTagUrl) {
1338
1417
  return _async_to_generator(function() {
@@ -1435,8 +1514,9 @@ function createHlsAdPlayer(contentVideo, options) {
1435
1514
  if (!adVideoElement) {
1436
1515
  adVideoElement = createAdVideoElement();
1437
1516
  adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.appendChild(adVideoElement);
1438
- setupAdEventListeners();
1517
+ contentVideo[AD_VIDEO_PROP] = adVideoElement;
1439
1518
  }
1519
+ setupAdEventListeners();
1440
1520
  resetQuartileTracking(true);
1441
1521
  contentVolume = contentVideo.volume;
1442
1522
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
@@ -1564,11 +1644,8 @@ function createHlsAdPlayer(contentVideo, options) {
1564
1644
  setAdPlayingFlag(false);
1565
1645
  contentVideo.muted = originalMutedState;
1566
1646
  contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
1647
+ teardownAdEventListeners();
1567
1648
  releaseAdDecoder();
1568
- if (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.parentElement) {
1569
- adContainerEl.parentElement.removeChild(adContainerEl);
1570
- }
1571
- adContainerEl = void 0;
1572
1649
  currentAd = void 0;
1573
1650
  podAds = [];
1574
1651
  podIndex = 0;
@@ -3981,6 +4058,11 @@ function detectBrowser() {
3981
4058
  chromeVersion: chromeVersionNum
3982
4059
  };
3983
4060
  }
4061
+ function requiresMediaPipelineResetAfterAds() {
4062
+ var _browser_tizenVersion;
4063
+ var browser = detectBrowser();
4064
+ return browser.name === "Samsung Tizen" && ((_browser_tizenVersion = browser.tizenVersion) !== null && _browser_tizenVersion !== void 0 ? _browser_tizenVersion : 0) >= 5;
4065
+ }
3984
4066
  function getBrowserConfigOverrides() {
3985
4067
  var browser = detectBrowser();
3986
4068
  var overrides = {};
@@ -6742,30 +6824,49 @@ var HlsEngine = /*#__PURE__*/ function() {
6742
6824
  {
6743
6825
  key: "reloadLiveStream",
6744
6826
  value: function reloadLiveStream() {
6827
+ var _this = this;
6745
6828
  var hls = this.hls;
6746
6829
  if (!hls) {
6747
6830
  return;
6748
6831
  }
6749
6832
  if (this.debug) {
6750
- console.log("[StormcloudVideoPlayer] Hard-reloading live stream (detach \u2192 reset video \u2192 re-attach)");
6833
+ console.log("[StormcloudVideoPlayer] Hard-reloading live stream (destroy hls \u2192 reset video \u2192 fresh setupHls)");
6751
6834
  }
6752
6835
  try {
6753
6836
  this.reloadingLiveStream = true;
6754
6837
  hls.stopLoad();
6755
6838
  hls.detachMedia();
6839
+ hls.destroy();
6840
+ this.hls = void 0;
6756
6841
  try {
6757
6842
  this.video.removeAttribute("src");
6758
6843
  this.video.load();
6759
6844
  } catch (error) {
6760
6845
  console.warn("[StormcloudVideoPlayer] video.load() threw after src removal:", error);
6761
6846
  }
6762
- hls.attachMedia(this.video);
6763
6847
  } catch (error) {
6764
6848
  this.reloadingLiveStream = false;
6849
+ this.hls = void 0;
6765
6850
  if (this.debug) {
6766
- console.warn("[StormcloudVideoPlayer] Failed to hard-reload live stream:", error);
6851
+ console.warn("[StormcloudVideoPlayer] Failed to tear down during hard-reload:", error);
6767
6852
  }
6853
+ return;
6768
6854
  }
6855
+ var recreateDelayMs = 600;
6856
+ window.setTimeout(function() {
6857
+ if (_this.hls) {
6858
+ _this.reloadingLiveStream = false;
6859
+ return;
6860
+ }
6861
+ try {
6862
+ _this.setupHls();
6863
+ } catch (error) {
6864
+ _this.reloadingLiveStream = false;
6865
+ if (_this.debug) {
6866
+ console.warn("[StormcloudVideoPlayer] Failed to rebuild pipeline during hard-reload:", error);
6867
+ }
6868
+ }
6869
+ }, recreateDelayMs);
6769
6870
  }
6770
6871
  },
6771
6872
  {
@@ -8078,6 +8179,14 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8078
8179
  this.host.video.style.visibility = "visible";
8079
8180
  this.host.video.style.opacity = "1";
8080
8181
  if (this.host.isLiveStream()) {
8182
+ if (this.host.requiresMediaPipelineResetAfterAds()) {
8183
+ if (this.debug) {
8184
+ console.log("[StormcloudVideoPlayer] Live break end \u2014 hard-reloading stream to reacquire decoder (single-decoder platform)");
8185
+ }
8186
+ this.host.reloadLiveStream();
8187
+ this.monitorLiveResumeStall(this.host.video.currentTime);
8188
+ return;
8189
+ }
8081
8190
  var liveSyncPos = this.host.getLiveSyncPosition();
8082
8191
  if (liveSyncPos != null && liveSyncPos > this.host.video.currentTime) {
8083
8192
  if (this.debug) {
@@ -8139,9 +8248,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8139
8248
  key: "monitorLiveResumeStall",
8140
8249
  value: function monitorLiveResumeStall(resumeBaseline) {
8141
8250
  var _this = this;
8251
+ var needsReset = this.host.requiresMediaPipelineResetAfterAds();
8142
8252
  var pollIntervalMs = 1e3;
8143
- var graceMs = 5e3;
8144
- var recoveryCooldownMs = 5e3;
8253
+ var graceMs = needsReset ? 8e3 : 5e3;
8254
+ var recoveryCooldownMs = needsReset ? 7e3 : 5e3;
8145
8255
  var maxRecoveries = 3;
8146
8256
  var maxMonitorMs = 45e3;
8147
8257
  var startTime = Date.now();
@@ -8255,7 +8365,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8255
8365
  if (canRecover) {
8256
8366
  recoveries++;
8257
8367
  lastRecoveryAt = Date.now();
8258
- if (recoveries === 1) {
8368
+ if (needsReset) {
8369
+ if (_this.debug) {
8370
+ console.warn("[StormcloudVideoPlayer] Content still wedged after ad break — hard-reloading live stream (recovery ".concat(recoveries, "/").concat(maxRecoveries, ") — ").concat(_this.describeVideoState()));
8371
+ }
8372
+ _this.host.reloadLiveStream();
8373
+ } else if (recoveries === 1) {
8259
8374
  if (_this.debug) {
8260
8375
  console.warn("[StormcloudVideoPlayer] Content wedged after ad break — calling recoverMediaError() (recovery ".concat(recoveries, "/").concat(maxRecoveries, ") — ").concat(_this.describeVideoState()));
8261
8376
  }
@@ -8468,6 +8583,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8468
8583
  recoverMediaError: function recoverMediaError() {
8469
8584
  return _this.hlsEngine.recoverMediaError();
8470
8585
  },
8586
+ requiresMediaPipelineResetAfterAds: function requiresMediaPipelineResetAfterAds1() {
8587
+ return requiresMediaPipelineResetAfterAds();
8588
+ },
8471
8589
  generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
8472
8590
  return _this.generatePodVastUrl(base, breakDurationMs);
8473
8591
  }