stormcloud-video-player 0.8.40 → 0.8.42

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.
@@ -1502,7 +1502,10 @@ function createHlsAdPlayer(contentVideo, options) {
1502
1502
  }
1503
1503
  if (adVideoElement) {
1504
1504
  adVideoElement.pause();
1505
- adVideoElement.src = "";
1505
+ adVideoElement.removeAttribute("src");
1506
+ try {
1507
+ adVideoElement.load();
1508
+ } catch (unused) {}
1506
1509
  }
1507
1510
  currentAd = void 0;
1508
1511
  podAds = [];
@@ -1548,7 +1551,10 @@ function createHlsAdPlayer(contentVideo, options) {
1548
1551
  }
1549
1552
  if (adVideoElement) {
1550
1553
  adVideoElement.pause();
1551
- adVideoElement.src = "";
1554
+ adVideoElement.removeAttribute("src");
1555
+ try {
1556
+ adVideoElement.load();
1557
+ } catch (unused) {}
1552
1558
  adVideoElement.remove();
1553
1559
  adVideoElement = void 0;
1554
1560
  }
@@ -8028,51 +8034,88 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8028
8034
  this.host.restartHlsLoad(liveSyncPos);
8029
8035
  }
8030
8036
  this.resumeContentPlayback();
8031
- this.monitorLiveResumeStall(0, this.host.video.currentTime);
8037
+ this.monitorLiveResumeStall(this.host.video.currentTime);
8032
8038
  return;
8033
8039
  }
8034
8040
  this.resumeContentPlayback();
8035
8041
  }
8036
8042
  },
8043
+ {
8044
+ key: "getBufferedAhead",
8045
+ value: function getBufferedAhead() {
8046
+ var video = this.host.video;
8047
+ var t = video.currentTime;
8048
+ var ranges = video.buffered;
8049
+ for(var i = 0; i < ranges.length; i++){
8050
+ if (t >= ranges.start(i) - 0.5 && t <= ranges.end(i)) {
8051
+ return ranges.end(i) - t;
8052
+ }
8053
+ }
8054
+ return 0;
8055
+ }
8056
+ },
8037
8057
  {
8038
8058
  key: "monitorLiveResumeStall",
8039
- value: function monitorLiveResumeStall(attempt, lastTime) {
8059
+ value: function monitorLiveResumeStall(resumeBaseline) {
8040
8060
  var _this = this;
8041
- var maxAttempts = 3;
8042
- var checkDelayMs = 2500;
8043
- window.setTimeout(function() {
8061
+ var pollIntervalMs = 1e3;
8062
+ var graceMs = 5e3;
8063
+ var reloadCooldownMs = 5e3;
8064
+ var maxHardReloads = 2;
8065
+ var maxMonitorMs = 25e3;
8066
+ var startTime = Date.now();
8067
+ var baseline = resumeBaseline;
8068
+ var hardReloads = 0;
8069
+ var lastReloadAt = 0;
8070
+ var poll = function poll1() {
8044
8071
  if (_this.inAdBreak) {
8045
8072
  return;
8046
8073
  }
8047
- var currentTime = _this.host.video.currentTime;
8048
- var advanced = currentTime > lastTime + 0.25;
8049
- if (advanced && !_this.host.video.paused) {
8074
+ var video = _this.host.video;
8075
+ var currentTime = video.currentTime;
8076
+ var advanced = currentTime > baseline + 0.5;
8077
+ var playing = !video.paused && video.readyState >= 3;
8078
+ if (advanced && playing) {
8050
8079
  if (_this.debug) {
8051
8080
  console.log("[StormcloudVideoPlayer] Live stream resumed successfully after ad break");
8052
8081
  }
8053
8082
  return;
8054
8083
  }
8055
- if (attempt >= maxAttempts) {
8056
- if (_this.debug) {
8057
- console.warn("[StormcloudVideoPlayer] Live stream failed to resume after ".concat(maxAttempts, " recovery attempts (t=").concat(currentTime.toFixed(2), "s)"));
8084
+ if (video.paused) {
8085
+ var _video_play;
8086
+ (_video_play = video.play()) === null || _video_play === void 0 ? void 0 : _video_play.catch(function() {});
8087
+ }
8088
+ var elapsed = Date.now() - startTime;
8089
+ var bufferedAhead = _this.getBufferedAhead();
8090
+ var wedged = bufferedAhead < 0.5 && !advanced;
8091
+ if (elapsed >= maxMonitorMs) {
8092
+ if (_this.debug && !advanced) {
8093
+ console.warn("[StormcloudVideoPlayer] Live stream failed to resume after ".concat((maxMonitorMs / 1e3).toFixed(0), "s (t=").concat(currentTime.toFixed(2), "s, buffered=").concat(bufferedAhead.toFixed(2), "s)"));
8058
8094
  }
8059
8095
  return;
8060
8096
  }
8061
- if (_this.debug) {
8062
- console.warn("[StormcloudVideoPlayer] Content stalled after ad break (t=".concat(currentTime.toFixed(2), "s) — forcing HLS reload at live edge (attempt ").concat(attempt + 1, "/").concat(maxAttempts, ")"));
8063
- }
8064
- var liveSyncPos = _this.host.getLiveSyncPosition();
8065
- var reloadPos = liveSyncPos != null && liveSyncPos > currentTime ? liveSyncPos : currentTime;
8066
- if (liveSyncPos != null && liveSyncPos > currentTime) {
8067
- _this.host.video.currentTime = liveSyncPos;
8068
- }
8069
- _this.host.restartHlsLoad(reloadPos);
8070
- if (_this.host.video.paused) {
8071
- var _this_host_video_play;
8072
- (_this_host_video_play = _this.host.video.play()) === null || _this_host_video_play === void 0 ? void 0 : _this_host_video_play.catch(function() {});
8097
+ var canHardReload = wedged && elapsed >= graceMs && Date.now() - lastReloadAt >= reloadCooldownMs && hardReloads < maxHardReloads;
8098
+ if (canHardReload) {
8099
+ hardReloads++;
8100
+ lastReloadAt = Date.now();
8101
+ var liveSyncPos = _this.host.getLiveSyncPosition();
8102
+ var reloadPos = liveSyncPos != null && liveSyncPos > currentTime ? liveSyncPos : currentTime;
8103
+ if (_this.debug) {
8104
+ console.warn("[StormcloudVideoPlayer] Content wedged after ad break (t=".concat(currentTime.toFixed(2), "s, buffered=").concat(bufferedAhead.toFixed(2), "s) — forcing HLS reload at ").concat(reloadPos.toFixed(2), "s (hard reload ").concat(hardReloads, "/").concat(maxHardReloads, ")"));
8105
+ }
8106
+ if (liveSyncPos != null && liveSyncPos > currentTime) {
8107
+ video.currentTime = liveSyncPos;
8108
+ }
8109
+ _this.host.restartHlsLoad(reloadPos);
8110
+ baseline = video.currentTime;
8111
+ if (video.paused) {
8112
+ var _video_play1;
8113
+ (_video_play1 = video.play()) === null || _video_play1 === void 0 ? void 0 : _video_play1.catch(function() {});
8114
+ }
8073
8115
  }
8074
- _this.monitorLiveResumeStall(attempt + 1, _this.host.video.currentTime);
8075
- }, checkDelayMs);
8116
+ window.setTimeout(poll, pollIntervalMs);
8117
+ };
8118
+ window.setTimeout(poll, pollIntervalMs);
8076
8119
  }
8077
8120
  },
8078
8121
  {
@@ -8775,12 +8818,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8775
8818
  ];
8776
8819
  case 3:
8777
8820
  error = _state.sent();
8778
- this.adBreak.adPodQueue = [];
8779
- this.adBreak.inAdBreak = false;
8780
- this.adBreak.showAds = false;
8781
8821
  if (this.debug) {
8782
8822
  console.warn("[StormcloudVideoPlayer] VMAP ad request failed:", error);
8783
8823
  }
8824
+ this.adBreak.handleAdPodComplete();
8784
8825
  return [
8785
8826
  3,
8786
8827
  4
@@ -8950,6 +8991,64 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8950
8991
  // src/ui/StormcloudVideoPlayer.tsx
8951
8992
  var import_fa = require("react-icons/fa");
8952
8993
  var import_jsx_runtime = require("react/jsx-runtime");
8994
+ var ExpandIcon = function ExpandIcon(param) {
8995
+ var _param_size = param.size, size = _param_size === void 0 ? 18 : _param_size;
8996
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
8997
+ width: size,
8998
+ height: size,
8999
+ viewBox: "0 0 24 24",
9000
+ fill: "none",
9001
+ stroke: "currentColor",
9002
+ strokeWidth: 2,
9003
+ strokeLinecap: "round",
9004
+ strokeLinejoin: "round",
9005
+ "aria-hidden": "true",
9006
+ focusable: "false",
9007
+ children: [
9008
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9009
+ d: "M9 4H4v5"
9010
+ }),
9011
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9012
+ d: "M20 9V4h-5"
9013
+ }),
9014
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9015
+ d: "M15 20h5v-5"
9016
+ }),
9017
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9018
+ d: "M4 15v5h5"
9019
+ })
9020
+ ]
9021
+ });
9022
+ };
9023
+ var CompressIcon = function CompressIcon(param) {
9024
+ var _param_size = param.size, size = _param_size === void 0 ? 18 : _param_size;
9025
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
9026
+ width: size,
9027
+ height: size,
9028
+ viewBox: "0 0 24 24",
9029
+ fill: "none",
9030
+ stroke: "currentColor",
9031
+ strokeWidth: 2,
9032
+ strokeLinecap: "round",
9033
+ strokeLinejoin: "round",
9034
+ "aria-hidden": "true",
9035
+ focusable: "false",
9036
+ children: [
9037
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9038
+ d: "M4 9h5V4"
9039
+ }),
9040
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9041
+ d: "M15 4v5h5"
9042
+ }),
9043
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9044
+ d: "M20 15h-5v5"
9045
+ }),
9046
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9047
+ d: "M9 20v-5H4"
9048
+ })
9049
+ ]
9050
+ });
9051
+ };
8953
9052
  var CRITICAL_PROPS = [
8954
9053
  "src",
8955
9054
  "allowNativeHls",
@@ -9987,9 +10086,9 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
9987
10086
  minHeight: "".concat(36 * responsiveScale, "px")
9988
10087
  },
9989
10088
  title: isFullscreen2 ? "Exit Fullscreen" : "Enter Fullscreen",
9990
- children: isFullscreen2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaCompress, {
10089
+ children: isFullscreen2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompressIcon, {
9991
10090
  size: Math.max(14, 18 * responsiveScale)
9992
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, {
10091
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ExpandIcon, {
9993
10092
  size: Math.max(14, 18 * responsiveScale)
9994
10093
  })
9995
10094
  })
@@ -10188,9 +10287,9 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
10188
10287
  background: "rgba(0, 0, 0, 0.6)"
10189
10288
  },
10190
10289
  title: isFullscreen2 ? "Exit Fullscreen" : "Enter Fullscreen",
10191
- children: isFullscreen2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaCompress, {
10290
+ children: isFullscreen2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompressIcon, {
10192
10291
  size: Math.max(14, 18 * responsiveScale)
10193
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, {
10292
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ExpandIcon, {
10194
10293
  size: Math.max(14, 18 * responsiveScale)
10195
10294
  })
10196
10295
  })