stormcloud-video-player 0.8.45 → 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.
package/lib/index.d.cts CHANGED
@@ -4001,6 +4001,7 @@ interface BrowserInfo {
4001
4001
  chromeVersion?: number | undefined;
4002
4002
  }
4003
4003
  declare function detectBrowser(): BrowserInfo;
4004
+ declare function requiresMediaPipelineResetAfterAds(): boolean;
4004
4005
  declare function getBrowserConfigOverrides(): {
4005
4006
  allowNativeHls?: boolean;
4006
4007
  pauseContentDuringAds?: boolean;
@@ -4043,4 +4044,4 @@ interface PalNonceManager {
4043
4044
  }
4044
4045
  declare function createPalNonceManager(): PalNonceManager;
4045
4046
 
4046
- export { type AdBreak, type AdController, type AdControllerOptions, type AdDetectInfo, type AdImpressionInfo, type AdLoadedInfo, type AdSchedule, type BaseStormcloudPlayerProps, type BrowserInfo, type ClientInfo, DEFAULT_MQTT_CONFIG, type HeartbeatData, IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, type ImaController, type ImaControllerOptions, type LateJoinPolicy, type MQTTConfig, type MQTTStatus, MQTT_CA_CERT_FILE, type OnProgressProps, type PalNonceManager, type PalNonceOptions, type PlayerAnalyticsContext, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, type StormcloudVideoPlayerConfig, type StormcloudVideoPlayerProps, type TrackingData, applyMQTTConfig, buildAnalyticsContext, buildMQTTBrokerUrl, buildPlayerTopic, canPlay, configureMQTT, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, disconnectMQTT, ensureMQTTClient, getBrowserConfigOverrides, getBrowserID, getClientInfo, getMQTTStatus, initMQTTClient, initializePolyfills, isMQTTConfigured, isMQTTConnected, isMQTTEnabled, isMediaStream, lazy, logBrowserInfo, merge, mqttConfig, omit, parseQuery, players, publishMQTT, randomString, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode };
4047
+ export { type AdBreak, type AdController, type AdControllerOptions, type AdDetectInfo, type AdImpressionInfo, type AdLoadedInfo, type AdSchedule, type BaseStormcloudPlayerProps, type BrowserInfo, type ClientInfo, DEFAULT_MQTT_CONFIG, type HeartbeatData, IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, type ImaController, type ImaControllerOptions, type LateJoinPolicy, type MQTTConfig, type MQTTStatus, MQTT_CA_CERT_FILE, type OnProgressProps, type PalNonceManager, type PalNonceOptions, type PlayerAnalyticsContext, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, type StormcloudVideoPlayerConfig, type StormcloudVideoPlayerProps, type TrackingData, applyMQTTConfig, buildAnalyticsContext, buildMQTTBrokerUrl, buildPlayerTopic, canPlay, configureMQTT, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, disconnectMQTT, ensureMQTTClient, getBrowserConfigOverrides, getBrowserID, getClientInfo, getMQTTStatus, initMQTTClient, initializePolyfills, isMQTTConfigured, isMQTTConnected, isMQTTEnabled, isMediaStream, lazy, logBrowserInfo, merge, mqttConfig, omit, parseQuery, players, publishMQTT, randomString, requiresMediaPipelineResetAfterAds, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode };
package/lib/index.d.ts CHANGED
@@ -4001,6 +4001,7 @@ interface BrowserInfo {
4001
4001
  chromeVersion?: number | undefined;
4002
4002
  }
4003
4003
  declare function detectBrowser(): BrowserInfo;
4004
+ declare function requiresMediaPipelineResetAfterAds(): boolean;
4004
4005
  declare function getBrowserConfigOverrides(): {
4005
4006
  allowNativeHls?: boolean;
4006
4007
  pauseContentDuringAds?: boolean;
@@ -4043,4 +4044,4 @@ interface PalNonceManager {
4043
4044
  }
4044
4045
  declare function createPalNonceManager(): PalNonceManager;
4045
4046
 
4046
- export { type AdBreak, type AdController, type AdControllerOptions, type AdDetectInfo, type AdImpressionInfo, type AdLoadedInfo, type AdSchedule, type BaseStormcloudPlayerProps, type BrowserInfo, type ClientInfo, DEFAULT_MQTT_CONFIG, type HeartbeatData, IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, type ImaController, type ImaControllerOptions, type LateJoinPolicy, type MQTTConfig, type MQTTStatus, MQTT_CA_CERT_FILE, type OnProgressProps, type PalNonceManager, type PalNonceOptions, type PlayerAnalyticsContext, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, type StormcloudVideoPlayerConfig, type StormcloudVideoPlayerProps, type TrackingData, applyMQTTConfig, buildAnalyticsContext, buildMQTTBrokerUrl, buildPlayerTopic, canPlay, configureMQTT, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, disconnectMQTT, ensureMQTTClient, getBrowserConfigOverrides, getBrowserID, getClientInfo, getMQTTStatus, initMQTTClient, initializePolyfills, isMQTTConfigured, isMQTTConnected, isMQTTEnabled, isMediaStream, lazy, logBrowserInfo, merge, mqttConfig, omit, parseQuery, players, publishMQTT, randomString, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode };
4047
+ export { type AdBreak, type AdController, type AdControllerOptions, type AdDetectInfo, type AdImpressionInfo, type AdLoadedInfo, type AdSchedule, type BaseStormcloudPlayerProps, type BrowserInfo, type ClientInfo, DEFAULT_MQTT_CONFIG, type HeartbeatData, IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, type ImaController, type ImaControllerOptions, type LateJoinPolicy, type MQTTConfig, type MQTTStatus, MQTT_CA_CERT_FILE, type OnProgressProps, type PalNonceManager, type PalNonceOptions, type PlayerAnalyticsContext, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, type StormcloudVideoPlayerConfig, type StormcloudVideoPlayerProps, type TrackingData, applyMQTTConfig, buildAnalyticsContext, buildMQTTBrokerUrl, buildPlayerTopic, canPlay, configureMQTT, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, disconnectMQTT, ensureMQTTClient, getBrowserConfigOverrides, getBrowserID, getClientInfo, getMQTTStatus, initMQTTClient, initializePolyfills, isMQTTConfigured, isMQTTConnected, isMQTTEnabled, isMediaStream, lazy, logBrowserInfo, merge, mqttConfig, omit, parseQuery, players, publishMQTT, randomString, requiresMediaPipelineResetAfterAds, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode };
package/lib/index.js CHANGED
@@ -372,15 +372,19 @@ import React, { useEffect, useRef, useMemo, useCallback } from "react";
372
372
  import Hls from "hls.js";
373
373
  var MAX_VAST_WRAPPER_DEPTH = 5;
374
374
  function createHlsAdPlayer(contentVideo, options) {
375
+ var _contentVideo_AD_VIDEO_PROP, _contentVideo_AD_CONTAINER_PROP;
375
376
  var adPlaying = false;
376
377
  var originalMutedState = false;
377
378
  var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
378
379
  var listeners = /* @__PURE__ */ new Map();
379
380
  var licenseKey = options === null || options === void 0 ? void 0 : options.licenseKey;
380
381
  var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
381
- var adVideoElement;
382
+ var AD_CONTAINER_PROP = "__stormcloudAdContainer";
383
+ var AD_VIDEO_PROP = "__stormcloudAdVideo";
384
+ var adVideoElement = (_contentVideo_AD_VIDEO_PROP = contentVideo[AD_VIDEO_PROP]) !== null && _contentVideo_AD_VIDEO_PROP !== void 0 ? _contentVideo_AD_VIDEO_PROP : void 0;
382
385
  var adHls;
383
- var adContainerEl;
386
+ var adContainerEl = (_contentVideo_AD_CONTAINER_PROP = contentVideo[AD_CONTAINER_PROP]) !== null && _contentVideo_AD_CONTAINER_PROP !== void 0 ? _contentVideo_AD_CONTAINER_PROP : void 0;
387
+ var adEventHandlers = [];
384
388
  var currentAd;
385
389
  var podAds = [];
386
390
  var podIndex = 0;
@@ -1024,7 +1028,8 @@ function createHlsAdPlayer(contentVideo, options) {
1024
1028
  }
1025
1029
  function setupAdEventListeners() {
1026
1030
  if (!adVideoElement || !currentAd) return;
1027
- adVideoElement.addEventListener("timeupdate", function() {
1031
+ if (adEventHandlers.length > 0) return;
1032
+ var onTimeUpdate = function onTimeUpdate() {
1028
1033
  if (!currentAd || !adVideoElement) return;
1029
1034
  noteAdProgress();
1030
1035
  var progress = adVideoElement.currentTime / currentAd.duration;
@@ -1040,15 +1045,15 @@ function createHlsAdPlayer(contentVideo, options) {
1040
1045
  trackingFired.thirdQuartile = true;
1041
1046
  fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
1042
1047
  }
1043
- });
1044
- adVideoElement.addEventListener("playing", function() {
1048
+ };
1049
+ var onPlaying = function onPlaying() {
1045
1050
  startStallWatchdog();
1046
1051
  if (!currentAd || trackingFired.start) return;
1047
1052
  trackingFired.start = true;
1048
1053
  fireTrackingPixels(currentAd.trackingUrls.start);
1049
1054
  console.log("[HlsAdPlayer] Ad started playing");
1050
- });
1051
- adVideoElement.addEventListener("ended", function() {
1055
+ };
1056
+ var onEnded = function onEnded() {
1052
1057
  if (!currentAd || trackingFired.complete) return;
1053
1058
  trackingFired.complete = true;
1054
1059
  fireTrackingPixels(currentAd.trackingUrls.complete);
@@ -1057,8 +1062,8 @@ function createHlsAdPlayer(contentVideo, options) {
1057
1062
  return;
1058
1063
  }
1059
1064
  handleAdComplete();
1060
- });
1061
- adVideoElement.addEventListener("error", function(e) {
1065
+ };
1066
+ var onError = function onError(e) {
1062
1067
  if (!adPlaying) return;
1063
1068
  console.error("[HlsAdPlayer] Ad video error:", e);
1064
1069
  if (currentAd) {
@@ -1068,25 +1073,100 @@ function createHlsAdPlayer(contentVideo, options) {
1068
1073
  return;
1069
1074
  }
1070
1075
  handleAdError();
1071
- });
1072
- adVideoElement.addEventListener("volumechange", function() {
1073
- if (!currentAd) return;
1076
+ };
1077
+ var onVolumeChange = function onVolumeChange() {
1078
+ if (!currentAd || !adVideoElement) return;
1074
1079
  if (adVideoElement.muted) {
1075
1080
  fireTrackingPixels(currentAd.trackingUrls.mute);
1076
1081
  } else {
1077
1082
  fireTrackingPixels(currentAd.trackingUrls.unmute);
1078
1083
  }
1079
- });
1080
- adVideoElement.addEventListener("pause", function() {
1081
- if (currentAd && !adVideoElement.ended) {
1084
+ };
1085
+ var onPause = function onPause() {
1086
+ if (currentAd && adVideoElement && !adVideoElement.ended) {
1082
1087
  fireTrackingPixels(currentAd.trackingUrls.pause);
1083
1088
  }
1084
- });
1085
- adVideoElement.addEventListener("play", function() {
1086
- if (currentAd && adVideoElement.currentTime > 0) {
1089
+ };
1090
+ var onPlay = function onPlay() {
1091
+ if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
1087
1092
  fireTrackingPixels(currentAd.trackingUrls.resume);
1088
1093
  }
1089
- });
1094
+ };
1095
+ adEventHandlers = [
1096
+ {
1097
+ type: "timeupdate",
1098
+ handler: onTimeUpdate
1099
+ },
1100
+ {
1101
+ type: "playing",
1102
+ handler: onPlaying
1103
+ },
1104
+ {
1105
+ type: "ended",
1106
+ handler: onEnded
1107
+ },
1108
+ {
1109
+ type: "error",
1110
+ handler: onError
1111
+ },
1112
+ {
1113
+ type: "volumechange",
1114
+ handler: onVolumeChange
1115
+ },
1116
+ {
1117
+ type: "pause",
1118
+ handler: onPause
1119
+ },
1120
+ {
1121
+ type: "play",
1122
+ handler: onPlay
1123
+ }
1124
+ ];
1125
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1126
+ try {
1127
+ for(var _iterator = adEventHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1128
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
1129
+ adVideoElement.addEventListener(type, handler);
1130
+ }
1131
+ } catch (err) {
1132
+ _didIteratorError = true;
1133
+ _iteratorError = err;
1134
+ } finally{
1135
+ try {
1136
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1137
+ _iterator.return();
1138
+ }
1139
+ } finally{
1140
+ if (_didIteratorError) {
1141
+ throw _iteratorError;
1142
+ }
1143
+ }
1144
+ }
1145
+ }
1146
+ function teardownAdEventListeners() {
1147
+ if (adVideoElement) {
1148
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1149
+ try {
1150
+ for(var _iterator = adEventHandlers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1151
+ var _step_value = _step.value, type = _step_value.type, handler = _step_value.handler;
1152
+ adVideoElement.removeEventListener(type, handler);
1153
+ }
1154
+ } catch (err) {
1155
+ _didIteratorError = true;
1156
+ _iteratorError = err;
1157
+ } finally{
1158
+ try {
1159
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1160
+ _iterator.return();
1161
+ }
1162
+ } finally{
1163
+ if (_didIteratorError) {
1164
+ throw _iteratorError;
1165
+ }
1166
+ }
1167
+ }
1168
+ }
1169
+ adEventHandlers = [];
1090
1170
  }
1091
1171
  function setAdPlayingFlag(isPlaying) {
1092
1172
  if (isPlaying) {
@@ -1226,16 +1306,32 @@ function createHlsAdPlayer(contentVideo, options) {
1226
1306
  }
1227
1307
  }, STALL_CHECK_INTERVAL_MS);
1228
1308
  }
1309
+ function releaseAdDecoder() {
1310
+ if (adHls) {
1311
+ adHls.destroy();
1312
+ adHls = void 0;
1313
+ }
1314
+ if (adVideoElement) {
1315
+ try {
1316
+ adVideoElement.pause();
1317
+ adVideoElement.removeAttribute("src");
1318
+ adVideoElement.load();
1319
+ } catch (error) {
1320
+ console.warn("[HlsAdPlayer] Error releasing ad decoder:", error);
1321
+ }
1322
+ }
1323
+ if (adContainerEl) {
1324
+ adContainerEl.style.display = "none";
1325
+ adContainerEl.style.pointerEvents = "none";
1326
+ }
1327
+ }
1229
1328
  function handleAdComplete() {
1230
1329
  console.log("[HlsAdPlayer] Handling ad completion");
1231
1330
  clearStallWatchdog();
1232
1331
  adPlaying = false;
1233
1332
  setAdPlayingFlag(false);
1234
1333
  contentVideo.muted = true;
1235
- if (adContainerEl) {
1236
- adContainerEl.style.display = "none";
1237
- adContainerEl.style.pointerEvents = "none";
1238
- }
1334
+ releaseAdDecoder();
1239
1335
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
1240
1336
  contentVideo.style.visibility = "visible";
1241
1337
  contentVideo.style.opacity = "1";
@@ -1258,10 +1354,7 @@ function createHlsAdPlayer(contentVideo, options) {
1258
1354
  adPlaying = false;
1259
1355
  setAdPlayingFlag(false);
1260
1356
  contentVideo.muted = true;
1261
- if (adContainerEl) {
1262
- adContainerEl.style.display = "none";
1263
- adContainerEl.style.pointerEvents = "none";
1264
- }
1357
+ releaseAdDecoder();
1265
1358
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
1266
1359
  contentVideo.style.visibility = "visible";
1267
1360
  contentVideo.style.opacity = "1";
@@ -1288,6 +1381,7 @@ function createHlsAdPlayer(contentVideo, options) {
1288
1381
  (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1289
1382
  adContainerEl = container;
1290
1383
  }
1384
+ contentVideo[AD_CONTAINER_PROP] = adContainerEl;
1291
1385
  },
1292
1386
  requestAds: function requestAds(vastTagUrl) {
1293
1387
  return _async_to_generator(function() {
@@ -1390,8 +1484,9 @@ function createHlsAdPlayer(contentVideo, options) {
1390
1484
  if (!adVideoElement) {
1391
1485
  adVideoElement = createAdVideoElement();
1392
1486
  adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.appendChild(adVideoElement);
1393
- setupAdEventListeners();
1487
+ contentVideo[AD_VIDEO_PROP] = adVideoElement;
1394
1488
  }
1489
+ setupAdEventListeners();
1395
1490
  resetQuartileTracking(true);
1396
1491
  contentVolume = contentVideo.volume;
1397
1492
  originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
@@ -1470,10 +1565,7 @@ function createHlsAdPlayer(contentVideo, options) {
1470
1565
  contentVideo.muted = originalMutedState;
1471
1566
  contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
1472
1567
  console.log("[HlsAdPlayer] Restored mute state on stop: ".concat(previousMutedState, " -> ").concat(originalMutedState, ", volume: ").concat(contentVideo.volume));
1473
- if (adContainerEl) {
1474
- adContainerEl.style.display = "none";
1475
- adContainerEl.style.pointerEvents = "none";
1476
- }
1568
+ releaseAdDecoder();
1477
1569
  contentVideo.style.visibility = "visible";
1478
1570
  contentVideo.style.opacity = "1";
1479
1571
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
@@ -1484,17 +1576,6 @@ function createHlsAdPlayer(contentVideo, options) {
1484
1576
  });
1485
1577
  }
1486
1578
  }
1487
- if (adHls) {
1488
- adHls.destroy();
1489
- adHls = void 0;
1490
- }
1491
- if (adVideoElement) {
1492
- adVideoElement.pause();
1493
- adVideoElement.removeAttribute("src");
1494
- try {
1495
- adVideoElement.load();
1496
- } catch (unused) {}
1497
- }
1498
1579
  currentAd = void 0;
1499
1580
  podAds = [];
1500
1581
  podIndex = 0;
@@ -1533,23 +1614,8 @@ function createHlsAdPlayer(contentVideo, options) {
1533
1614
  setAdPlayingFlag(false);
1534
1615
  contentVideo.muted = originalMutedState;
1535
1616
  contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
1536
- if (adHls) {
1537
- adHls.destroy();
1538
- adHls = void 0;
1539
- }
1540
- if (adVideoElement) {
1541
- adVideoElement.pause();
1542
- adVideoElement.removeAttribute("src");
1543
- try {
1544
- adVideoElement.load();
1545
- } catch (unused) {}
1546
- adVideoElement.remove();
1547
- adVideoElement = void 0;
1548
- }
1549
- if (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.parentElement) {
1550
- adContainerEl.parentElement.removeChild(adContainerEl);
1551
- }
1552
- adContainerEl = void 0;
1617
+ teardownAdEventListeners();
1618
+ releaseAdDecoder();
1553
1619
  currentAd = void 0;
1554
1620
  podAds = [];
1555
1621
  podIndex = 0;
@@ -3985,6 +4051,11 @@ function detectBrowser() {
3985
4051
  chromeVersion: chromeVersionNum
3986
4052
  };
3987
4053
  }
4054
+ function requiresMediaPipelineResetAfterAds() {
4055
+ var _browser_tizenVersion;
4056
+ var browser = detectBrowser();
4057
+ return browser.name === "Samsung Tizen" && ((_browser_tizenVersion = browser.tizenVersion) !== null && _browser_tizenVersion !== void 0 ? _browser_tizenVersion : 0) >= 5;
4058
+ }
3988
4059
  function getBrowserConfigOverrides() {
3989
4060
  var browser = detectBrowser();
3990
4061
  var overrides = {};
@@ -6757,31 +6828,67 @@ var HlsEngine = /*#__PURE__*/ function() {
6757
6828
  }
6758
6829
  }
6759
6830
  },
6831
+ {
6832
+ key: "recoverMediaError",
6833
+ value: function recoverMediaError() {
6834
+ if (!this.hls) {
6835
+ return;
6836
+ }
6837
+ try {
6838
+ this.hls.recoverMediaError();
6839
+ } catch (error) {
6840
+ if (this.debug) {
6841
+ console.warn("[StormcloudVideoPlayer] recoverMediaError() failed:", error);
6842
+ }
6843
+ }
6844
+ }
6845
+ },
6760
6846
  {
6761
6847
  key: "reloadLiveStream",
6762
6848
  value: function reloadLiveStream() {
6849
+ var _this = this;
6763
6850
  var hls = this.hls;
6764
6851
  if (!hls) {
6765
6852
  return;
6766
6853
  }
6767
6854
  if (this.debug) {
6768
- console.log("[StormcloudVideoPlayer] Hard-reloading live stream (detach \u2192 reset video \u2192 re-attach)");
6855
+ console.log("[StormcloudVideoPlayer] Hard-reloading live stream (destroy hls \u2192 reset video \u2192 fresh setupHls)");
6769
6856
  }
6770
6857
  try {
6771
6858
  this.reloadingLiveStream = true;
6772
6859
  hls.stopLoad();
6773
6860
  hls.detachMedia();
6861
+ hls.destroy();
6862
+ this.hls = void 0;
6774
6863
  try {
6775
6864
  this.video.removeAttribute("src");
6776
6865
  this.video.load();
6777
- } catch (unused) {}
6778
- hls.attachMedia(this.video);
6866
+ } catch (error) {
6867
+ console.warn("[StormcloudVideoPlayer] video.load() threw after src removal:", error);
6868
+ }
6779
6869
  } catch (error) {
6780
6870
  this.reloadingLiveStream = false;
6871
+ this.hls = void 0;
6781
6872
  if (this.debug) {
6782
- console.warn("[StormcloudVideoPlayer] Failed to hard-reload live stream:", error);
6873
+ console.warn("[StormcloudVideoPlayer] Failed to tear down during hard-reload:", error);
6783
6874
  }
6875
+ return;
6784
6876
  }
6877
+ var recreateDelayMs = 600;
6878
+ window.setTimeout(function() {
6879
+ if (_this.hls) {
6880
+ _this.reloadingLiveStream = false;
6881
+ return;
6882
+ }
6883
+ try {
6884
+ _this.setupHls();
6885
+ } catch (error) {
6886
+ _this.reloadingLiveStream = false;
6887
+ if (_this.debug) {
6888
+ console.warn("[StormcloudVideoPlayer] Failed to rebuild pipeline during hard-reload:", error);
6889
+ }
6890
+ }
6891
+ }, recreateDelayMs);
6785
6892
  }
6786
6893
  },
6787
6894
  {
@@ -8095,6 +8202,14 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8095
8202
  this.host.video.style.visibility = "visible";
8096
8203
  this.host.video.style.opacity = "1";
8097
8204
  if (this.host.isLiveStream()) {
8205
+ if (this.host.requiresMediaPipelineResetAfterAds()) {
8206
+ if (this.debug) {
8207
+ console.log("[StormcloudVideoPlayer] Live break end \u2014 hard-reloading stream to reacquire decoder (single-decoder platform)");
8208
+ }
8209
+ this.host.reloadLiveStream();
8210
+ this.monitorLiveResumeStall(this.host.video.currentTime);
8211
+ return;
8212
+ }
8098
8213
  var liveSyncPos = this.host.getLiveSyncPosition();
8099
8214
  if (liveSyncPos != null && liveSyncPos > this.host.video.currentTime) {
8100
8215
  if (this.debug) {
@@ -8156,11 +8271,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8156
8271
  key: "monitorLiveResumeStall",
8157
8272
  value: function monitorLiveResumeStall(resumeBaseline) {
8158
8273
  var _this = this;
8274
+ var needsReset = this.host.requiresMediaPipelineResetAfterAds();
8159
8275
  var pollIntervalMs = 1e3;
8160
- var graceMs = 5e3;
8161
- var recoveryCooldownMs = 5e3;
8162
- var maxRecoveries = 2;
8163
- var maxMonitorMs = 3e4;
8276
+ var graceMs = needsReset ? 8e3 : 5e3;
8277
+ var recoveryCooldownMs = needsReset ? 7e3 : 5e3;
8278
+ var maxRecoveries = 3;
8279
+ var maxMonitorMs = 45e3;
8164
8280
  var startTime = Date.now();
8165
8281
  var baseline = resumeBaseline;
8166
8282
  var recoveries = 0;
@@ -8272,8 +8388,17 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8272
8388
  if (canRecover) {
8273
8389
  recoveries++;
8274
8390
  lastRecoveryAt = Date.now();
8275
- var isFinalAttempt = recoveries >= maxRecoveries;
8276
- if (!isFinalAttempt) {
8391
+ if (needsReset) {
8392
+ if (_this.debug) {
8393
+ console.warn("[StormcloudVideoPlayer] Content still wedged after ad break — hard-reloading live stream (recovery ".concat(recoveries, "/").concat(maxRecoveries, ") — ").concat(_this.describeVideoState()));
8394
+ }
8395
+ _this.host.reloadLiveStream();
8396
+ } else if (recoveries === 1) {
8397
+ if (_this.debug) {
8398
+ console.warn("[StormcloudVideoPlayer] Content wedged after ad break — calling recoverMediaError() (recovery ".concat(recoveries, "/").concat(maxRecoveries, ") — ").concat(_this.describeVideoState()));
8399
+ }
8400
+ _this.host.recoverMediaError();
8401
+ } else if (recoveries === 2) {
8277
8402
  var liveSyncPos = _this.host.getLiveSyncPosition();
8278
8403
  var reloadPos = liveSyncPos != null && liveSyncPos > currentTime ? liveSyncPos : currentTime;
8279
8404
  if (_this.debug) {
@@ -8305,17 +8430,41 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8305
8430
  value: function resumeContentPlayback() {
8306
8431
  var _this = this;
8307
8432
  var attempt = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 0;
8308
- var maxAttempts = 3;
8309
- if (!this.host.video.paused) {
8433
+ var maxAttempts = 5;
8434
+ var video = this.host.video;
8435
+ if (!video.paused) {
8310
8436
  if (this.debug && attempt === 0) {
8311
8437
  console.log("[StormcloudVideoPlayer] Content video already playing after ads");
8312
8438
  }
8313
8439
  return;
8314
8440
  }
8315
8441
  if (this.debug) {
8316
- console.log("[StormcloudVideoPlayer] Resuming content playback after ads (attempt ".concat(attempt + 1, "/").concat(maxAttempts, ")"));
8442
+ console.log("[StormcloudVideoPlayer] Resuming content playback after ads (attempt ".concat(attempt + 1, "/").concat(maxAttempts, ", readyState=").concat(video.readyState, ")"));
8317
8443
  }
8318
- var playResult = this.host.video.play();
8444
+ if (video.readyState < 3) {
8445
+ if (attempt + 1 >= maxAttempts) {
8446
+ var _video_play;
8447
+ if (this.debug) {
8448
+ console.warn("[StormcloudVideoPlayer] readyState never reached HAVE_FUTURE_DATA, forcing play()");
8449
+ }
8450
+ (_video_play = video.play()) === null || _video_play === void 0 ? void 0 : _video_play.catch(function() {});
8451
+ return;
8452
+ }
8453
+ var onReady = function onReady1() {
8454
+ video.removeEventListener("canplay", onReady);
8455
+ _this.resumeContentPlayback(attempt + 1);
8456
+ };
8457
+ video.addEventListener("canplay", onReady);
8458
+ var backoffMs = 500 * (attempt + 1);
8459
+ window.setTimeout(function() {
8460
+ video.removeEventListener("canplay", onReady);
8461
+ if (video.paused) {
8462
+ _this.resumeContentPlayback(attempt + 1);
8463
+ }
8464
+ }, backoffMs);
8465
+ return;
8466
+ }
8467
+ var playResult = video.play();
8319
8468
  if (playResult && typeof playResult.catch === "function") {
8320
8469
  playResult.catch(function(error) {
8321
8470
  if (attempt + 1 >= maxAttempts) {
@@ -8455,6 +8604,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8455
8604
  reloadLiveStream: function reloadLiveStream() {
8456
8605
  return _this.hlsEngine.reloadLiveStream();
8457
8606
  },
8607
+ recoverMediaError: function recoverMediaError() {
8608
+ return _this.hlsEngine.recoverMediaError();
8609
+ },
8610
+ requiresMediaPipelineResetAfterAds: function requiresMediaPipelineResetAfterAds1() {
8611
+ return requiresMediaPipelineResetAfterAds();
8612
+ },
8458
8613
  generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
8459
8614
  return _this.generatePodVastUrl(base, breakDurationMs);
8460
8615
  }
@@ -11767,5 +11922,5 @@ var createStormcloudPlayer = function createStormcloudPlayer(playerList, fallbac
11767
11922
  };
11768
11923
  var StormcloudPlayer = createStormcloudPlayer(players_default, players_default[players_default.length - 1]);
11769
11924
  var StormcloudPlayer_default = StormcloudPlayer;
11770
- export { DEFAULT_MQTT_CONFIG, IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, MQTT_CA_CERT_FILE, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer_default as StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, applyMQTTConfig, buildAnalyticsContext, buildMQTTBrokerUrl, buildPlayerTopic, canPlay, configureMQTT, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, disconnectMQTT, ensureMQTTClient, getBrowserConfigOverrides, getBrowserID, getClientInfo, getMQTTStatus, initMQTTClient, initializePolyfills, isMQTTConfigured, isMQTTConnected, isMQTTEnabled, isMediaStream, lazy, logBrowserInfo, merge, mqttConfig, omit, parseQuery, players_default as players, publishMQTT, randomString, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode };
11925
+ export { DEFAULT_MQTT_CONFIG, IS_BROWSER, IS_GLOBAL, IS_IOS, IS_SAFARI, MQTT_CA_CERT_FILE, SUPPORTS_DASH, SUPPORTS_HLS, StormcloudPlayer_default as StormcloudPlayer, StormcloudVideoPlayer, StormcloudVideoPlayerComponent, applyMQTTConfig, buildAnalyticsContext, buildMQTTBrokerUrl, buildPlayerTopic, canPlay, configureMQTT, createHlsAdPlayer, createPalNonceManager, createStormcloudPlayer, StormcloudVideoPlayerComponent as default, detectBrowser, disconnectMQTT, ensureMQTTClient, getBrowserConfigOverrides, getBrowserID, getClientInfo, getMQTTStatus, initMQTTClient, initializePolyfills, isMQTTConfigured, isMQTTConnected, isMQTTEnabled, isMediaStream, lazy, logBrowserInfo, merge, mqttConfig, omit, parseQuery, players_default as players, publishMQTT, randomString, requiresMediaPipelineResetAfterAds, sendAdDetectTracking, sendAdImpressionTracking, sendAdLoadedTracking, sendHeartbeat, sendInitialTracking, supportsFeature, supportsModernJS, supportsWebKitPresentationMode };
11771
11926
  //# sourceMappingURL=index.js.map