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.
@@ -438,15 +438,19 @@ var import_react2 = require("react");
438
438
  var import_hls = __toESM(require("hls.js"), 1);
439
439
  var MAX_VAST_WRAPPER_DEPTH = 5;
440
440
  function createHlsAdPlayer(contentVideo, options) {
441
+ var _contentVideo_AD_VIDEO_PROP, _contentVideo_AD_CONTAINER_PROP;
441
442
  var adPlaying = false;
442
443
  var originalMutedState = false;
443
444
  var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
444
445
  var listeners = /* @__PURE__ */ new Map();
445
446
  var licenseKey = options === null || options === void 0 ? void 0 : options.licenseKey;
446
447
  var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
447
- var adVideoElement;
448
+ var AD_CONTAINER_PROP = "__stormcloudAdContainer";
449
+ var AD_VIDEO_PROP = "__stormcloudAdVideo";
450
+ var adVideoElement = (_contentVideo_AD_VIDEO_PROP = contentVideo[AD_VIDEO_PROP]) !== null && _contentVideo_AD_VIDEO_PROP !== void 0 ? _contentVideo_AD_VIDEO_PROP : void 0;
448
451
  var adHls;
449
- var adContainerEl;
452
+ var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
453
+ var adEventHandlers = [];
450
454
  var currentAd;
451
455
  var podAds = [];
452
456
  var podIndex = 0;
@@ -1090,7 +1094,8 @@ function createHlsAdPlayer(contentVideo, options) {
1090
1094
  }
1091
1095
  function setupAdEventListeners() {
1092
1096
  if (!adVideoElement || !currentAd) return;
1093
- adVideoElement.addEventListener("timeupdate", function() {
1097
+ if (adEventHandlers.length > 0) return;
1098
+ var onTimeUpdate = function onTimeUpdate() {
1094
1099
  if (!currentAd || !adVideoElement) return;
1095
1100
  noteAdProgress();
1096
1101
  var progress = adVideoElement.currentTime / currentAd.duration;
@@ -1106,15 +1111,15 @@ function createHlsAdPlayer(contentVideo, options) {
1106
1111
  trackingFired.thirdQuartile = true;
1107
1112
  fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
1108
1113
  }
1109
- });
1110
- adVideoElement.addEventListener("playing", function() {
1114
+ };
1115
+ var onPlaying = function onPlaying() {
1111
1116
  startStallWatchdog();
1112
1117
  if (!currentAd || trackingFired.start) return;
1113
1118
  trackingFired.start = true;
1114
1119
  fireTrackingPixels(currentAd.trackingUrls.start);
1115
1120
  console.log("[HlsAdPlayer] Ad started playing");
1116
- });
1117
- adVideoElement.addEventListener("ended", function() {
1121
+ };
1122
+ var onEnded = function onEnded() {
1118
1123
  if (!currentAd || trackingFired.complete) return;
1119
1124
  trackingFired.complete = true;
1120
1125
  fireTrackingPixels(currentAd.trackingUrls.complete);
@@ -1123,8 +1128,8 @@ function createHlsAdPlayer(contentVideo, options) {
1123
1128
  return;
1124
1129
  }
1125
1130
  handleAdComplete();
1126
- });
1127
- adVideoElement.addEventListener("error", function(e) {
1131
+ };
1132
+ var onError = function onError(e) {
1128
1133
  if (!adPlaying) return;
1129
1134
  console.error("[HlsAdPlayer] Ad video error:", e);
1130
1135
  if (currentAd) {
@@ -1134,25 +1139,100 @@ function createHlsAdPlayer(contentVideo, options) {
1134
1139
  return;
1135
1140
  }
1136
1141
  handleAdError();
1137
- });
1138
- adVideoElement.addEventListener("volumechange", function() {
1139
- if (!currentAd) return;
1142
+ };
1143
+ var onVolumeChange = function onVolumeChange() {
1144
+ if (!currentAd || !adVideoElement) return;
1140
1145
  if (adVideoElement.muted) {
1141
1146
  fireTrackingPixels(currentAd.trackingUrls.mute);
1142
1147
  } else {
1143
1148
  fireTrackingPixels(currentAd.trackingUrls.unmute);
1144
1149
  }
1145
- });
1146
- adVideoElement.addEventListener("pause", function() {
1147
- if (currentAd && !adVideoElement.ended) {
1150
+ };
1151
+ var onPause = function onPause() {
1152
+ if (currentAd && adVideoElement && !adVideoElement.ended) {
1148
1153
  fireTrackingPixels(currentAd.trackingUrls.pause);
1149
1154
  }
1150
- });
1151
- adVideoElement.addEventListener("play", function() {
1152
- if (currentAd && adVideoElement.currentTime > 0) {
1155
+ };
1156
+ var onPlay = function onPlay() {
1157
+ if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
1153
1158
  fireTrackingPixels(currentAd.trackingUrls.resume);
1154
1159
  }
1155
- });
1160
+ };
1161
+ adEventHandlers = [
1162
+ {
1163
+ type: "timeupdate",
1164
+ handler: onTimeUpdate
1165
+ },
1166
+ {
1167
+ type: "playing",
1168
+ handler: onPlaying
1169
+ },
1170
+ {
1171
+ type: "ended",
1172
+ handler: onEnded
1173
+ },
1174
+ {
1175
+ type: "error",
1176
+ handler: onError
1177
+ },
1178
+ {
1179
+ type: "volumechange",
1180
+ handler: onVolumeChange
1181
+ },
1182
+ {
1183
+ type: "pause",
1184
+ handler: onPause
1185
+ },
1186
+ {
1187
+ type: "play",
1188
+ handler: onPlay
1189
+ }
1190
+ ];
1191
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1192
+ try {
1193
+ for(var _iterator = adEventHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1194
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
1195
+ adVideoElement.addEventListener(type, handler);
1196
+ }
1197
+ } catch (err) {
1198
+ _didIteratorError = true;
1199
+ _iteratorError = err;
1200
+ } finally{
1201
+ try {
1202
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1203
+ _iterator.return();
1204
+ }
1205
+ } finally{
1206
+ if (_didIteratorError) {
1207
+ throw _iteratorError;
1208
+ }
1209
+ }
1210
+ }
1211
+ }
1212
+ function teardownAdEventListeners() {
1213
+ if (adVideoElement) {
1214
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1215
+ try {
1216
+ for(var _iterator = adEventHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1217
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
1218
+ adVideoElement.removeEventListener(type, handler);
1219
+ }
1220
+ } catch (err) {
1221
+ _didIteratorError = true;
1222
+ _iteratorError = err;
1223
+ } finally{
1224
+ try {
1225
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1226
+ _iterator.return();
1227
+ }
1228
+ } finally{
1229
+ if (_didIteratorError) {
1230
+ throw _iteratorError;
1231
+ }
1232
+ }
1233
+ }
1234
+ }
1235
+ adEventHandlers = [];
1156
1236
  }
1157
1237
  function setAdPlayingFlag(isPlaying) {
1158
1238
  if (isPlaying) {
@@ -1298,15 +1378,13 @@ function createHlsAdPlayer(contentVideo, options) {
1298
1378
  adHls = void 0;
1299
1379
  }
1300
1380
  if (adVideoElement) {
1301
- adVideoElement.pause();
1302
- adVideoElement.removeAttribute("src");
1303
1381
  try {
1382
+ adVideoElement.pause();
1383
+ adVideoElement.removeAttribute("src");
1304
1384
  adVideoElement.load();
1305
1385
  } catch (error) {
1306
- console.warn("[HlsAdPlayer] adVideoElement.load() threw after src removal:", error);
1386
+ console.warn("[HlsAdPlayer] Error releasing ad decoder:", error);
1307
1387
  }
1308
- adVideoElement.remove();
1309
- adVideoElement = void 0;
1310
1388
  }
1311
1389
  if (adContainerEl) {
1312
1390
  adContainerEl.style.display = "none";
@@ -1369,6 +1447,7 @@ function createHlsAdPlayer(contentVideo, options) {
1369
1447
  (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1370
1448
  adContainerEl = container;
1371
1449
  }
1450
+ contentVideo[AD_CONTAINER_PROP] = adContainerEl;
1372
1451
  },
1373
1452
  requestAds: function requestAds(vastTagUrl) {
1374
1453
  return _async_to_generator(function() {
@@ -1471,8 +1550,9 @@ function createHlsAdPlayer(contentVideo, options) {
1471
1550
  if (!adVideoElement) {
1472
1551
  adVideoElement = createAdVideoElement();
1473
1552
  adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.appendChild(adVideoElement);
1474
- setupAdEventListeners();
1553
+ contentVideo[AD_VIDEO_PROP] = adVideoElement;
1475
1554
  }
1555
+ setupAdEventListeners();
1476
1556
  resetQuartileTracking(true);
1477
1557
  contentVolume = contentVideo.volume;
1478
1558
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
@@ -1600,11 +1680,8 @@ function createHlsAdPlayer(contentVideo, options) {
1600
1680
  setAdPlayingFlag(false);
1601
1681
  contentVideo.muted = originalMutedState;
1602
1682
  contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
1683
+ teardownAdEventListeners();
1603
1684
  releaseAdDecoder();
1604
- if (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.parentElement) {
1605
- adContainerEl.parentElement.removeChild(adContainerEl);
1606
- }
1607
- adContainerEl = void 0;
1608
1685
  currentAd = void 0;
1609
1686
  podAds = [];
1610
1687
  podIndex = 0;
@@ -4017,6 +4094,11 @@ function detectBrowser() {
4017
4094
  chromeVersion: chromeVersionNum
4018
4095
  };
4019
4096
  }
4097
+ function requiresMediaPipelineResetAfterAds() {
4098
+ var _browser_tizenVersion;
4099
+ var browser = detectBrowser();
4100
+ return browser.name === "Samsung Tizen" && ((_browser_tizenVersion = browser.tizenVersion) !== null && _browser_tizenVersion !== void 0 ? _browser_tizenVersion : 0) >= 5;
4101
+ }
4020
4102
  function getBrowserConfigOverrides() {
4021
4103
  var browser = detectBrowser();
4022
4104
  var overrides = {};
@@ -6778,30 +6860,49 @@ var HlsEngine = /*#__PURE__*/ function() {
6778
6860
  {
6779
6861
  key: "reloadLiveStream",
6780
6862
  value: function reloadLiveStream() {
6863
+ var _this = this;
6781
6864
  var hls = this.hls;
6782
6865
  if (!hls) {
6783
6866
  return;
6784
6867
  }
6785
6868
  if (this.debug) {
6786
- console.log("[StormcloudVideoPlayer] Hard-reloading live stream (detach \u2192 reset video \u2192 re-attach)");
6869
+ console.log("[StormcloudVideoPlayer] Hard-reloading live stream (destroy hls \u2192 reset video \u2192 fresh setupHls)");
6787
6870
  }
6788
6871
  try {
6789
6872
  this.reloadingLiveStream = true;
6790
6873
  hls.stopLoad();
6791
6874
  hls.detachMedia();
6875
+ hls.destroy();
6876
+ this.hls = void 0;
6792
6877
  try {
6793
6878
  this.video.removeAttribute("src");
6794
6879
  this.video.load();
6795
6880
  } catch (error) {
6796
6881
  console.warn("[StormcloudVideoPlayer] video.load() threw after src removal:", error);
6797
6882
  }
6798
- hls.attachMedia(this.video);
6799
6883
  } catch (error) {
6800
6884
  this.reloadingLiveStream = false;
6885
+ this.hls = void 0;
6801
6886
  if (this.debug) {
6802
- console.warn("[StormcloudVideoPlayer] Failed to hard-reload live stream:", error);
6887
+ console.warn("[StormcloudVideoPlayer] Failed to tear down during hard-reload:", error);
6803
6888
  }
6889
+ return;
6804
6890
  }
6891
+ var recreateDelayMs = 600;
6892
+ window.setTimeout(function() {
6893
+ if (_this.hls) {
6894
+ _this.reloadingLiveStream = false;
6895
+ return;
6896
+ }
6897
+ try {
6898
+ _this.setupHls();
6899
+ } catch (error) {
6900
+ _this.reloadingLiveStream = false;
6901
+ if (_this.debug) {
6902
+ console.warn("[StormcloudVideoPlayer] Failed to rebuild pipeline during hard-reload:", error);
6903
+ }
6904
+ }
6905
+ }, recreateDelayMs);
6805
6906
  }
6806
6907
  },
6807
6908
  {
@@ -8114,6 +8215,14 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8114
8215
  this.host.video.style.visibility = "visible";
8115
8216
  this.host.video.style.opacity = "1";
8116
8217
  if (this.host.isLiveStream()) {
8218
+ if (this.host.requiresMediaPipelineResetAfterAds()) {
8219
+ if (this.debug) {
8220
+ console.log("[StormcloudVideoPlayer] Live break end \u2014 hard-reloading stream to reacquire decoder (single-decoder platform)");
8221
+ }
8222
+ this.host.reloadLiveStream();
8223
+ this.monitorLiveResumeStall(this.host.video.currentTime);
8224
+ return;
8225
+ }
8117
8226
  var liveSyncPos = this.host.getLiveSyncPosition();
8118
8227
  if (liveSyncPos != null && liveSyncPos > this.host.video.currentTime) {
8119
8228
  if (this.debug) {
@@ -8175,9 +8284,10 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8175
8284
  key: "monitorLiveResumeStall",
8176
8285
  value: function monitorLiveResumeStall(resumeBaseline) {
8177
8286
  var _this = this;
8287
+ var needsReset = this.host.requiresMediaPipelineResetAfterAds();
8178
8288
  var pollIntervalMs = 1e3;
8179
- var graceMs = 5e3;
8180
- var recoveryCooldownMs = 5e3;
8289
+ var graceMs = needsReset ? 8e3 : 5e3;
8290
+ var recoveryCooldownMs = needsReset ? 7e3 : 5e3;
8181
8291
  var maxRecoveries = 3;
8182
8292
  var maxMonitorMs = 45e3;
8183
8293
  var startTime = Date.now();
@@ -8291,7 +8401,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8291
8401
  if (canRecover) {
8292
8402
  recoveries++;
8293
8403
  lastRecoveryAt = Date.now();
8294
- if (recoveries === 1) {
8404
+ if (needsReset) {
8405
+ if (_this.debug) {
8406
+ console.warn("[StormcloudVideoPlayer] Content still wedged after ad break — hard-reloading live stream (recovery ".concat(recoveries, "/").concat(maxRecoveries, ") — ").concat(_this.describeVideoState()));
8407
+ }
8408
+ _this.host.reloadLiveStream();
8409
+ } else if (recoveries === 1) {
8295
8410
  if (_this.debug) {
8296
8411
  console.warn("[StormcloudVideoPlayer] Content wedged after ad break — calling recoverMediaError() (recovery ".concat(recoveries, "/").concat(maxRecoveries, ") — ").concat(_this.describeVideoState()));
8297
8412
  }
@@ -8504,6 +8619,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8504
8619
  recoverMediaError: function recoverMediaError() {
8505
8620
  return _this.hlsEngine.recoverMediaError();
8506
8621
  },
8622
+ requiresMediaPipelineResetAfterAds: function requiresMediaPipelineResetAfterAds1() {
8623
+ return requiresMediaPipelineResetAfterAds();
8624
+ },
8507
8625
  generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
8508
8626
  return _this.generatePodVastUrl(base, breakDurationMs);
8509
8627
  }