stormcloud-video-player 0.8.45 → 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.
@@ -1242,16 +1242,34 @@ function createHlsAdPlayer(contentVideo, options) {
1242
1242
  }
1243
1243
  }, STALL_CHECK_INTERVAL_MS);
1244
1244
  }
1245
+ function releaseAdDecoder() {
1246
+ if (adHls) {
1247
+ adHls.destroy();
1248
+ adHls = void 0;
1249
+ }
1250
+ if (adVideoElement) {
1251
+ adVideoElement.pause();
1252
+ adVideoElement.removeAttribute("src");
1253
+ try {
1254
+ adVideoElement.load();
1255
+ } catch (error) {
1256
+ console.warn("[HlsAdPlayer] adVideoElement.load() threw after src removal:", error);
1257
+ }
1258
+ adVideoElement.remove();
1259
+ adVideoElement = void 0;
1260
+ }
1261
+ if (adContainerEl) {
1262
+ adContainerEl.style.display = "none";
1263
+ adContainerEl.style.pointerEvents = "none";
1264
+ }
1265
+ }
1245
1266
  function handleAdComplete() {
1246
1267
  console.log("[HlsAdPlayer] Handling ad completion");
1247
1268
  clearStallWatchdog();
1248
1269
  adPlaying = false;
1249
1270
  setAdPlayingFlag(false);
1250
1271
  contentVideo.muted = true;
1251
- if (adContainerEl) {
1252
- adContainerEl.style.display = "none";
1253
- adContainerEl.style.pointerEvents = "none";
1254
- }
1272
+ releaseAdDecoder();
1255
1273
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
1256
1274
  contentVideo.style.visibility = "visible";
1257
1275
  contentVideo.style.opacity = "1";
@@ -1274,10 +1292,7 @@ function createHlsAdPlayer(contentVideo, options) {
1274
1292
  adPlaying = false;
1275
1293
  setAdPlayingFlag(false);
1276
1294
  contentVideo.muted = true;
1277
- if (adContainerEl) {
1278
- adContainerEl.style.display = "none";
1279
- adContainerEl.style.pointerEvents = "none";
1280
- }
1295
+ releaseAdDecoder();
1281
1296
  if (!(options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds)) {
1282
1297
  contentVideo.style.visibility = "visible";
1283
1298
  contentVideo.style.opacity = "1";
@@ -1486,10 +1501,7 @@ function createHlsAdPlayer(contentVideo, options) {
1486
1501
  contentVideo.muted = originalMutedState;
1487
1502
  contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
1488
1503
  console.log("[HlsAdPlayer] Restored mute state on stop: ".concat(previousMutedState, " -> ").concat(originalMutedState, ", volume: ").concat(contentVideo.volume));
1489
- if (adContainerEl) {
1490
- adContainerEl.style.display = "none";
1491
- adContainerEl.style.pointerEvents = "none";
1492
- }
1504
+ releaseAdDecoder();
1493
1505
  contentVideo.style.visibility = "visible";
1494
1506
  contentVideo.style.opacity = "1";
1495
1507
  if (options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) {
@@ -1500,17 +1512,6 @@ function createHlsAdPlayer(contentVideo, options) {
1500
1512
  });
1501
1513
  }
1502
1514
  }
1503
- if (adHls) {
1504
- adHls.destroy();
1505
- adHls = void 0;
1506
- }
1507
- if (adVideoElement) {
1508
- adVideoElement.pause();
1509
- adVideoElement.removeAttribute("src");
1510
- try {
1511
- adVideoElement.load();
1512
- } catch (unused) {}
1513
- }
1514
1515
  currentAd = void 0;
1515
1516
  podAds = [];
1516
1517
  podIndex = 0;
@@ -1549,19 +1550,7 @@ function createHlsAdPlayer(contentVideo, options) {
1549
1550
  setAdPlayingFlag(false);
1550
1551
  contentVideo.muted = originalMutedState;
1551
1552
  contentVideo.volume = Math.max(0, Math.min(1, originalVolume));
1552
- if (adHls) {
1553
- adHls.destroy();
1554
- adHls = void 0;
1555
- }
1556
- if (adVideoElement) {
1557
- adVideoElement.pause();
1558
- adVideoElement.removeAttribute("src");
1559
- try {
1560
- adVideoElement.load();
1561
- } catch (unused) {}
1562
- adVideoElement.remove();
1563
- adVideoElement = void 0;
1564
- }
1553
+ releaseAdDecoder();
1565
1554
  if (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.parentElement) {
1566
1555
  adContainerEl.parentElement.removeChild(adContainerEl);
1567
1556
  }
@@ -6721,6 +6710,21 @@ var HlsEngine = /*#__PURE__*/ function() {
6721
6710
  }
6722
6711
  }
6723
6712
  },
6713
+ {
6714
+ key: "recoverMediaError",
6715
+ value: function recoverMediaError() {
6716
+ if (!this.hls) {
6717
+ return;
6718
+ }
6719
+ try {
6720
+ this.hls.recoverMediaError();
6721
+ } catch (error) {
6722
+ if (this.debug) {
6723
+ console.warn("[StormcloudVideoPlayer] recoverMediaError() failed:", error);
6724
+ }
6725
+ }
6726
+ }
6727
+ },
6724
6728
  {
6725
6729
  key: "reloadLiveStream",
6726
6730
  value: function reloadLiveStream() {
@@ -6738,7 +6742,9 @@ var HlsEngine = /*#__PURE__*/ function() {
6738
6742
  try {
6739
6743
  this.video.removeAttribute("src");
6740
6744
  this.video.load();
6741
- } catch (unused) {}
6745
+ } catch (error) {
6746
+ console.warn("[StormcloudVideoPlayer] video.load() threw after src removal:", error);
6747
+ }
6742
6748
  hls.attachMedia(this.video);
6743
6749
  } catch (error) {
6744
6750
  this.reloadingLiveStream = false;
@@ -8122,8 +8128,8 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8122
8128
  var pollIntervalMs = 1e3;
8123
8129
  var graceMs = 5e3;
8124
8130
  var recoveryCooldownMs = 5e3;
8125
- var maxRecoveries = 2;
8126
- var maxMonitorMs = 3e4;
8131
+ var maxRecoveries = 3;
8132
+ var maxMonitorMs = 45e3;
8127
8133
  var startTime = Date.now();
8128
8134
  var baseline = resumeBaseline;
8129
8135
  var recoveries = 0;
@@ -8235,8 +8241,12 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8235
8241
  if (canRecover) {
8236
8242
  recoveries++;
8237
8243
  lastRecoveryAt = Date.now();
8238
- var isFinalAttempt = recoveries >= maxRecoveries;
8239
- if (!isFinalAttempt) {
8244
+ if (recoveries === 1) {
8245
+ if (_this.debug) {
8246
+ console.warn("[StormcloudVideoPlayer] Content wedged after ad break — calling recoverMediaError() (recovery ".concat(recoveries, "/").concat(maxRecoveries, ") — ").concat(_this.describeVideoState()));
8247
+ }
8248
+ _this.host.recoverMediaError();
8249
+ } else if (recoveries === 2) {
8240
8250
  var liveSyncPos = _this.host.getLiveSyncPosition();
8241
8251
  var reloadPos = liveSyncPos != null && liveSyncPos > currentTime ? liveSyncPos : currentTime;
8242
8252
  if (_this.debug) {
@@ -8268,17 +8278,41 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
8268
8278
  value: function resumeContentPlayback() {
8269
8279
  var _this = this;
8270
8280
  var attempt = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 0;
8271
- var maxAttempts = 3;
8272
- if (!this.host.video.paused) {
8281
+ var maxAttempts = 5;
8282
+ var video = this.host.video;
8283
+ if (!video.paused) {
8273
8284
  if (this.debug && attempt === 0) {
8274
8285
  console.log("[StormcloudVideoPlayer] Content video already playing after ads");
8275
8286
  }
8276
8287
  return;
8277
8288
  }
8278
8289
  if (this.debug) {
8279
- console.log("[StormcloudVideoPlayer] Resuming content playback after ads (attempt ".concat(attempt + 1, "/").concat(maxAttempts, ")"));
8290
+ console.log("[StormcloudVideoPlayer] Resuming content playback after ads (attempt ".concat(attempt + 1, "/").concat(maxAttempts, ", readyState=").concat(video.readyState, ")"));
8280
8291
  }
8281
- var playResult = this.host.video.play();
8292
+ if (video.readyState < 3) {
8293
+ if (attempt + 1 >= maxAttempts) {
8294
+ var _video_play;
8295
+ if (this.debug) {
8296
+ console.warn("[StormcloudVideoPlayer] readyState never reached HAVE_FUTURE_DATA, forcing play()");
8297
+ }
8298
+ (_video_play = video.play()) === null || _video_play === void 0 ? void 0 : _video_play.catch(function() {});
8299
+ return;
8300
+ }
8301
+ var onReady = function onReady1() {
8302
+ video.removeEventListener("canplay", onReady);
8303
+ _this.resumeContentPlayback(attempt + 1);
8304
+ };
8305
+ video.addEventListener("canplay", onReady);
8306
+ var backoffMs = 500 * (attempt + 1);
8307
+ window.setTimeout(function() {
8308
+ video.removeEventListener("canplay", onReady);
8309
+ if (video.paused) {
8310
+ _this.resumeContentPlayback(attempt + 1);
8311
+ }
8312
+ }, backoffMs);
8313
+ return;
8314
+ }
8315
+ var playResult = video.play();
8282
8316
  if (playResult && typeof playResult.catch === "function") {
8283
8317
  playResult.catch(function(error) {
8284
8318
  if (attempt + 1 >= maxAttempts) {
@@ -8417,6 +8451,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8417
8451
  reloadLiveStream: function reloadLiveStream() {
8418
8452
  return _this.hlsEngine.reloadLiveStream();
8419
8453
  },
8454
+ recoverMediaError: function recoverMediaError() {
8455
+ return _this.hlsEngine.recoverMediaError();
8456
+ },
8420
8457
  generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
8421
8458
  return _this.generatePodVastUrl(base, breakDurationMs);
8422
8459
  }