stormcloud-video-player 0.8.44 → 0.8.46

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.js CHANGED
@@ -1226,16 +1226,34 @@ function createHlsAdPlayer(contentVideo, options) {
1226
1226
  }
1227
1227
  }, STALL_CHECK_INTERVAL_MS);
1228
1228
  }
1229
+ function releaseAdDecoder() {
1230
+ if (adHls) {
1231
+ adHls.destroy();
1232
+ adHls = void 0;
1233
+ }
1234
+ if (adVideoElement) {
1235
+ adVideoElement.pause();
1236
+ adVideoElement.removeAttribute("src");
1237
+ try {
1238
+ adVideoElement.load();
1239
+ } catch (error) {
1240
+ console.warn("[HlsAdPlayer] adVideoElement.load() threw after src removal:", error);
1241
+ }
1242
+ adVideoElement.remove();
1243
+ adVideoElement = void 0;
1244
+ }
1245
+ if (adContainerEl) {
1246
+ adContainerEl.style.display = "none";
1247
+ adContainerEl.style.pointerEvents = "none";
1248
+ }
1249
+ }
1229
1250
  function handleAdComplete() {
1230
1251
  console.log("[HlsAdPlayer] Handling ad completion");
1231
1252
  clearStallWatchdog();
1232
1253
  adPlaying = false;
1233
1254
  setAdPlayingFlag(false);
1234
1255
  contentVideo.muted = true;
1235
- if (adContainerEl) {
1236
- adContainerEl.style.display = "none";
1237
- adContainerEl.style.pointerEvents = "none";
1238
- }
1256
+ releaseAdDecoder();
1239
1257
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
1240
1258
  contentVideo.style.visibility = "visible";
1241
1259
  contentVideo.style.opacity = "1";
@@ -1243,7 +1261,9 @@ function createHlsAdPlayer(contentVideo, options) {
1243
1261
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
1244
1262
  if (contentVideo.paused) {
1245
1263
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback");
1246
- contentVideo.play().catch(function() {});
1264
+ contentVideo.play().catch(function(error) {
1265
+ console.error("[HlsAdPlayer] Error resuming content playback in live mode:", error);
1266
+ });
1247
1267
  } else {
1248
1268
  console.log("[HlsAdPlayer] Content video already playing in live mode");
1249
1269
  }
@@ -1256,10 +1276,7 @@ function createHlsAdPlayer(contentVideo, options) {
1256
1276
  adPlaying = false;
1257
1277
  setAdPlayingFlag(false);
1258
1278
  contentVideo.muted = true;
1259
- if (adContainerEl) {
1260
- adContainerEl.style.display = "none";
1261
- adContainerEl.style.pointerEvents = "none";
1262
- }
1279
+ releaseAdDecoder();
1263
1280
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
1264
1281
  contentVideo.style.visibility = "visible";
1265
1282
  contentVideo.style.opacity = "1";
@@ -1468,29 +1485,17 @@ function createHlsAdPlayer(contentVideo, options) {
1468
1485
  contentVideo.muted = originalMutedState;
1469
1486
  contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
1470
1487
  console.log("[HlsAdPlayer] Restored mute state on stop: ".concat(previousMutedState, " -> ").concat(originalMutedState, ", volume: ").concat(contentVideo.volume));
1471
- if (adContainerEl) {
1472
- adContainerEl.style.display = "none";
1473
- adContainerEl.style.pointerEvents = "none";
1474
- }
1488
+ releaseAdDecoder();
1475
1489
  contentVideo.style.visibility = "visible";
1476
1490
  contentVideo.style.opacity = "1";
1477
1491
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
1478
1492
  if (contentVideo.paused) {
1479
1493
  console.log("[HlsAdPlayer] Content video paused in live mode, resuming playback on stop");
1480
- contentVideo.play().catch(function() {});
1494
+ contentVideo.play().catch(function(error) {
1495
+ console.error("[HlsAdPlayer] Error resuming content playback in live mode on stop:", error);
1496
+ });
1481
1497
  }
1482
1498
  }
1483
- if (adHls) {
1484
- adHls.destroy();
1485
- adHls = void 0;
1486
- }
1487
- if (adVideoElement) {
1488
- adVideoElement.pause();
1489
- adVideoElement.removeAttribute("src");
1490
- try {
1491
- adVideoElement.load();
1492
- } catch (unused) {}
1493
- }
1494
1499
  currentAd = void 0;
1495
1500
  podAds = [];
1496
1501
  podIndex = 0;
@@ -1529,19 +1534,7 @@ function createHlsAdPlayer(contentVideo, options) {
1529
1534
  setAdPlayingFlag(false);
1530
1535
  contentVideo.muted = originalMutedState;
1531
1536
  contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
1532
- if (adHls) {
1533
- adHls.destroy();
1534
- adHls = void 0;
1535
- }
1536
- if (adVideoElement) {
1537
- adVideoElement.pause();
1538
- adVideoElement.removeAttribute("src");
1539
- try {
1540
- adVideoElement.load();
1541
- } catch (unused) {}
1542
- adVideoElement.remove();
1543
- adVideoElement = void 0;
1544
- }
1537
+ releaseAdDecoder();
1545
1538
  if (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.parentElement) {
1546
1539
  adContainerEl.parentElement.removeChild(adContainerEl);
1547
1540
  }
@@ -6753,6 +6746,21 @@ var HlsEngine = /*#__PURE__*/ function() {
6753
6746
  }
6754
6747
  }
6755
6748
  },
6749
+ {
6750
+ key: "recoverMediaError",
6751
+ value: function recoverMediaError() {
6752
+ if (!this.hls) {
6753
+ return;
6754
+ }
6755
+ try {
6756
+ this.hls.recoverMediaError();
6757
+ } catch (error) {
6758
+ if (this.debug) {
6759
+ console.warn("[StormcloudVideoPlayer] recoverMediaError() failed:", error);
6760
+ }
6761
+ }
6762
+ }
6763
+ },
6756
6764
  {
6757
6765
  key: "reloadLiveStream",
6758
6766
  value: function reloadLiveStream() {
@@ -6770,7 +6778,9 @@ var HlsEngine = /*#__PURE__*/ function() {
6770
6778
  try {
6771
6779
  this.video.removeAttribute("src");
6772
6780
  this.video.load();
6773
- } catch (unused) {}
6781
+ } catch (error) {
6782
+ console.warn("[StormcloudVideoPlayer] video.load() threw after src removal:", error);
6783
+ }
6774
6784
  hls.attachMedia(this.video);
6775
6785
  } catch (error) {
6776
6786
  this.reloadingLiveStream = false;
@@ -8155,8 +8165,8 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8155
8165
  var pollIntervalMs = 1e3;
8156
8166
  var graceMs = 5e3;
8157
8167
  var recoveryCooldownMs = 5e3;
8158
- var maxRecoveries = 2;
8159
- var maxMonitorMs = 3e4;
8168
+ var maxRecoveries = 3;
8169
+ var maxMonitorMs = 45e3;
8160
8170
  var startTime = Date.now();
8161
8171
  var baseline = resumeBaseline;
8162
8172
  var recoveries = 0;
@@ -8268,8 +8278,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8268
8278
  if (canRecover) {
8269
8279
  recoveries++;
8270
8280
  lastRecoveryAt = Date.now();
8271
- var isFinalAttempt = recoveries >= maxRecoveries;
8272
- if (!isFinalAttempt) {
8281
+ if (recoveries === 1) {
8282
+ if (_this.debug) {
8283
+ console.warn("[StormcloudVideoPlayer] Content wedged after ad break — calling recoverMediaError() (recovery ".concat(recoveries, "/").concat(maxRecoveries, ") — ").concat(_this.describeVideoState()));
8284
+ }
8285
+ _this.host.recoverMediaError();
8286
+ } else if (recoveries === 2) {
8273
8287
  var liveSyncPos = _this.host.getLiveSyncPosition();
8274
8288
  var reloadPos = liveSyncPos != null && liveSyncPos > currentTime ? liveSyncPos : currentTime;
8275
8289
  if (_this.debug) {
@@ -8301,17 +8315,41 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8301
8315
  value: function resumeContentPlayback() {
8302
8316
  var _this = this;
8303
8317
  var attempt = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 0;
8304
- var maxAttempts = 3;
8305
- if (!this.host.video.paused) {
8318
+ var maxAttempts = 5;
8319
+ var video = this.host.video;
8320
+ if (!video.paused) {
8306
8321
  if (this.debug && attempt === 0) {
8307
8322
  console.log("[StormcloudVideoPlayer] Content video already playing after ads");
8308
8323
  }
8309
8324
  return;
8310
8325
  }
8311
8326
  if (this.debug) {
8312
- console.log("[StormcloudVideoPlayer] Resuming content playback after ads (attempt ".concat(attempt + 1, "/").concat(maxAttempts, ")"));
8327
+ console.log("[StormcloudVideoPlayer] Resuming content playback after ads (attempt ".concat(attempt + 1, "/").concat(maxAttempts, ", readyState=").concat(video.readyState, ")"));
8313
8328
  }
8314
- var playResult = this.host.video.play();
8329
+ if (video.readyState < 3) {
8330
+ if (attempt + 1 >= maxAttempts) {
8331
+ var _video_play;
8332
+ if (this.debug) {
8333
+ console.warn("[StormcloudVideoPlayer] readyState never reached HAVE_FUTURE_DATA, forcing play()");
8334
+ }
8335
+ (_video_play = video.play()) === null || _video_play === void 0 ? void 0 : _video_play.catch(function() {});
8336
+ return;
8337
+ }
8338
+ var onReady = function onReady1() {
8339
+ video.removeEventListener("canplay", onReady);
8340
+ _this.resumeContentPlayback(attempt + 1);
8341
+ };
8342
+ video.addEventListener("canplay", onReady);
8343
+ var backoffMs = 500 * (attempt + 1);
8344
+ window.setTimeout(function() {
8345
+ video.removeEventListener("canplay", onReady);
8346
+ if (video.paused) {
8347
+ _this.resumeContentPlayback(attempt + 1);
8348
+ }
8349
+ }, backoffMs);
8350
+ return;
8351
+ }
8352
+ var playResult = video.play();
8315
8353
  if (playResult && typeof playResult.catch === "function") {
8316
8354
  playResult.catch(function(error) {
8317
8355
  if (attempt + 1 >= maxAttempts) {
@@ -8451,6 +8489,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8451
8489
  reloadLiveStream: function reloadLiveStream() {
8452
8490
  return _this.hlsEngine.reloadLiveStream();
8453
8491
  },
8492
+ recoverMediaError: function recoverMediaError() {
8493
+ return _this.hlsEngine.recoverMediaError();
8494
+ },
8454
8495
  generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
8455
8496
  return _this.generatePodVastUrl(base, breakDurationMs);
8456
8497
  }