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.
package/lib/index.cjs CHANGED
@@ -1703,7 +1703,10 @@ function createHlsAdPlayer(contentVideo, options) {
1703
1703
  }
1704
1704
  if (adVideoElement) {
1705
1705
  adVideoElement.pause();
1706
- adVideoElement.src = "";
1706
+ adVideoElement.removeAttribute("src");
1707
+ try {
1708
+ adVideoElement.load();
1709
+ } catch (unused) {}
1707
1710
  }
1708
1711
  currentAd = void 0;
1709
1712
  podAds = [];
@@ -1749,7 +1752,10 @@ function createHlsAdPlayer(contentVideo, options) {
1749
1752
  }
1750
1753
  if (adVideoElement) {
1751
1754
  adVideoElement.pause();
1752
- adVideoElement.src = "";
1755
+ adVideoElement.removeAttribute("src");
1756
+ try {
1757
+ adVideoElement.load();
1758
+ } catch (unused) {}
1753
1759
  adVideoElement.remove();
1754
1760
  adVideoElement = void 0;
1755
1761
  }
@@ -8273,51 +8279,88 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8273
8279
  this.host.restartHlsLoad(liveSyncPos);
8274
8280
  }
8275
8281
  this.resumeContentPlayback();
8276
- this.monitorLiveResumeStall(0, this.host.video.currentTime);
8282
+ this.monitorLiveResumeStall(this.host.video.currentTime);
8277
8283
  return;
8278
8284
  }
8279
8285
  this.resumeContentPlayback();
8280
8286
  }
8281
8287
  },
8288
+ {
8289
+ key: "getBufferedAhead",
8290
+ value: function getBufferedAhead() {
8291
+ var video = this.host.video;
8292
+ var t = video.currentTime;
8293
+ var ranges = video.buffered;
8294
+ for(var i = 0; i < ranges.length; i++){
8295
+ if (t >= ranges.start(i) - 0.5 && t <= ranges.end(i)) {
8296
+ return ranges.end(i) - t;
8297
+ }
8298
+ }
8299
+ return 0;
8300
+ }
8301
+ },
8282
8302
  {
8283
8303
  key: "monitorLiveResumeStall",
8284
- value: function monitorLiveResumeStall(attempt, lastTime) {
8304
+ value: function monitorLiveResumeStall(resumeBaseline) {
8285
8305
  var _this = this;
8286
- var maxAttempts = 3;
8287
- var checkDelayMs = 2500;
8288
- window.setTimeout(function() {
8306
+ var pollIntervalMs = 1e3;
8307
+ var graceMs = 5e3;
8308
+ var reloadCooldownMs = 5e3;
8309
+ var maxHardReloads = 2;
8310
+ var maxMonitorMs = 25e3;
8311
+ var startTime = Date.now();
8312
+ var baseline = resumeBaseline;
8313
+ var hardReloads = 0;
8314
+ var lastReloadAt = 0;
8315
+ var poll = function poll1() {
8289
8316
  if (_this.inAdBreak) {
8290
8317
  return;
8291
8318
  }
8292
- var currentTime = _this.host.video.currentTime;
8293
- var advanced = currentTime > lastTime + 0.25;
8294
- if (advanced && !_this.host.video.paused) {
8319
+ var video = _this.host.video;
8320
+ var currentTime = video.currentTime;
8321
+ var advanced = currentTime > baseline + 0.5;
8322
+ var playing = !video.paused && video.readyState >= 3;
8323
+ if (advanced && playing) {
8295
8324
  if (_this.debug) {
8296
8325
  console.log("[StormcloudVideoPlayer] Live stream resumed successfully after ad break");
8297
8326
  }
8298
8327
  return;
8299
8328
  }
8300
- if (attempt >= maxAttempts) {
8301
- if (_this.debug) {
8302
- console.warn("[StormcloudVideoPlayer] Live stream failed to resume after ".concat(maxAttempts, " recovery attempts (t=").concat(currentTime.toFixed(2), "s)"));
8329
+ if (video.paused) {
8330
+ var _video_play;
8331
+ (_video_play = video.play()) === null || _video_play === void 0 ? void 0 : _video_play.catch(function() {});
8332
+ }
8333
+ var elapsed = Date.now() - startTime;
8334
+ var bufferedAhead = _this.getBufferedAhead();
8335
+ var wedged = bufferedAhead < 0.5 && !advanced;
8336
+ if (elapsed >= maxMonitorMs) {
8337
+ if (_this.debug && !advanced) {
8338
+ 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)"));
8303
8339
  }
8304
8340
  return;
8305
8341
  }
8306
- if (_this.debug) {
8307
- 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, ")"));
8308
- }
8309
- var liveSyncPos = _this.host.getLiveSyncPosition();
8310
- var reloadPos = liveSyncPos != null && liveSyncPos > currentTime ? liveSyncPos : currentTime;
8311
- if (liveSyncPos != null && liveSyncPos > currentTime) {
8312
- _this.host.video.currentTime = liveSyncPos;
8313
- }
8314
- _this.host.restartHlsLoad(reloadPos);
8315
- if (_this.host.video.paused) {
8316
- var _this_host_video_play;
8317
- (_this_host_video_play = _this.host.video.play()) === null || _this_host_video_play === void 0 ? void 0 : _this_host_video_play.catch(function() {});
8342
+ var canHardReload = wedged && elapsed >= graceMs && Date.now() - lastReloadAt >= reloadCooldownMs && hardReloads < maxHardReloads;
8343
+ if (canHardReload) {
8344
+ hardReloads++;
8345
+ lastReloadAt = Date.now();
8346
+ var liveSyncPos = _this.host.getLiveSyncPosition();
8347
+ var reloadPos = liveSyncPos != null && liveSyncPos > currentTime ? liveSyncPos : currentTime;
8348
+ if (_this.debug) {
8349
+ 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, ")"));
8350
+ }
8351
+ if (liveSyncPos != null && liveSyncPos > currentTime) {
8352
+ video.currentTime = liveSyncPos;
8353
+ }
8354
+ _this.host.restartHlsLoad(reloadPos);
8355
+ baseline = video.currentTime;
8356
+ if (video.paused) {
8357
+ var _video_play1;
8358
+ (_video_play1 = video.play()) === null || _video_play1 === void 0 ? void 0 : _video_play1.catch(function() {});
8359
+ }
8318
8360
  }
8319
- _this.monitorLiveResumeStall(attempt + 1, _this.host.video.currentTime);
8320
- }, checkDelayMs);
8361
+ window.setTimeout(poll, pollIntervalMs);
8362
+ };
8363
+ window.setTimeout(poll, pollIntervalMs);
8321
8364
  }
8322
8365
  },
8323
8366
  {
@@ -9020,12 +9063,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9020
9063
  ];
9021
9064
  case 3:
9022
9065
  error = _state.sent();
9023
- this.adBreak.adPodQueue = [];
9024
- this.adBreak.inAdBreak = false;
9025
- this.adBreak.showAds = false;
9026
9066
  if (this.debug) {
9027
9067
  console.warn("[StormcloudVideoPlayer] VMAP ad request failed:", error);
9028
9068
  }
9069
+ this.adBreak.handleAdPodComplete();
9029
9070
  return [
9030
9071
  3,
9031
9072
  4
@@ -9195,6 +9236,64 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
9195
9236
  // src/ui/StormcloudVideoPlayer.tsx
9196
9237
  var import_fa = require("react-icons/fa");
9197
9238
  var import_jsx_runtime = require("react/jsx-runtime");
9239
+ var ExpandIcon = function ExpandIcon(param) {
9240
+ var _param_size = param.size, size = _param_size === void 0 ? 18 : _param_size;
9241
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
9242
+ width: size,
9243
+ height: size,
9244
+ viewBox: "0 0 24 24",
9245
+ fill: "none",
9246
+ stroke: "currentColor",
9247
+ strokeWidth: 2,
9248
+ strokeLinecap: "round",
9249
+ strokeLinejoin: "round",
9250
+ "aria-hidden": "true",
9251
+ focusable: "false",
9252
+ children: [
9253
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9254
+ d: "M9 4H4v5"
9255
+ }),
9256
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9257
+ d: "M20 9V4h-5"
9258
+ }),
9259
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9260
+ d: "M15 20h5v-5"
9261
+ }),
9262
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9263
+ d: "M4 15v5h5"
9264
+ })
9265
+ ]
9266
+ });
9267
+ };
9268
+ var CompressIcon = function CompressIcon(param) {
9269
+ var _param_size = param.size, size = _param_size === void 0 ? 18 : _param_size;
9270
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", {
9271
+ width: size,
9272
+ height: size,
9273
+ viewBox: "0 0 24 24",
9274
+ fill: "none",
9275
+ stroke: "currentColor",
9276
+ strokeWidth: 2,
9277
+ strokeLinecap: "round",
9278
+ strokeLinejoin: "round",
9279
+ "aria-hidden": "true",
9280
+ focusable: "false",
9281
+ children: [
9282
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9283
+ d: "M4 9h5V4"
9284
+ }),
9285
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9286
+ d: "M15 4v5h5"
9287
+ }),
9288
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9289
+ d: "M20 15h-5v5"
9290
+ }),
9291
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", {
9292
+ d: "M9 20v-5H4"
9293
+ })
9294
+ ]
9295
+ });
9296
+ };
9198
9297
  var CRITICAL_PROPS = [
9199
9298
  "src",
9200
9299
  "allowNativeHls",
@@ -10232,9 +10331,9 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
10232
10331
  minHeight: "".concat(36 * responsiveScale, "px")
10233
10332
  },
10234
10333
  title: isFullscreen2 ? "Exit Fullscreen" : "Enter Fullscreen",
10235
- children: isFullscreen2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaCompress, {
10334
+ children: isFullscreen2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompressIcon, {
10236
10335
  size: Math.max(14, 18 * responsiveScale)
10237
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, {
10336
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ExpandIcon, {
10238
10337
  size: Math.max(14, 18 * responsiveScale)
10239
10338
  })
10240
10339
  })
@@ -10433,9 +10532,9 @@ var StormcloudVideoPlayerComponent = import_react.default.memo(function(props) {
10433
10532
  background: "rgba(0, 0, 0, 0.6)"
10434
10533
  },
10435
10534
  title: isFullscreen2 ? "Exit Fullscreen" : "Enter Fullscreen",
10436
- children: isFullscreen2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaCompress, {
10535
+ children: isFullscreen2 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompressIcon, {
10437
10536
  size: Math.max(14, 18 * responsiveScale)
10438
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_fa.FaExpand, {
10537
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ExpandIcon, {
10439
10538
  size: Math.max(14, 18 * responsiveScale)
10440
10539
  })
10441
10540
  })