stormcloud-video-player 0.6.0 → 0.6.1

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.
@@ -974,14 +974,16 @@ function resolveBidToVastAd(winner, logPrefix) {
974
974
  return Promise.resolve(null);
975
975
  }
976
976
  function createVastAdLayer(contentVideo, options) {
977
- var _ref, _ref1;
977
+ var _ref, _ref1, _ref2, _ref3;
978
978
  var adPlaying = false;
979
979
  var originalMutedState = false;
980
980
  var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
981
981
  var listeners = /* @__PURE__ */ new Map();
982
982
  var mainHlsInstance = options === null || options === void 0 ? void 0 : options.mainHlsInstance;
983
983
  var continueLiveStreamDuringAds = (_ref = options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) !== null && _ref !== void 0 ? _ref : false;
984
- var debug = (_ref1 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref1 !== void 0 ? _ref1 : false;
984
+ var smartTVMode = (_ref1 = options === null || options === void 0 ? void 0 : options.smartTVMode) !== null && _ref1 !== void 0 ? _ref1 : false;
985
+ var singleElementMode = (_ref2 = options === null || options === void 0 ? void 0 : options.singleElementMode) !== null && _ref2 !== void 0 ? _ref2 : false;
986
+ var debug = (_ref3 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref3 !== void 0 ? _ref3 : false;
985
987
  var adVideoElement;
986
988
  var adHls;
987
989
  var adContainerEl;
@@ -990,6 +992,7 @@ function createVastAdLayer(contentVideo, options) {
990
992
  var destroyed = false;
991
993
  var tornDown = false;
992
994
  var trackingFired = createEmptyTrackingState();
995
+ var currentAdEventHandlers;
993
996
  var preloadSlots = /* @__PURE__ */ new Map();
994
997
  function emit(event, payload) {
995
998
  var set = listeners.get(event);
@@ -1092,63 +1095,86 @@ function createVastAdLayer(contentVideo, options) {
1092
1095
  video.volume = 1;
1093
1096
  return video;
1094
1097
  }
1098
+ function removeAdEventListeners() {
1099
+ if (!currentAdEventHandlers || !adVideoElement) return;
1100
+ var el = adVideoElement;
1101
+ el.removeEventListener("timeupdate", currentAdEventHandlers.timeupdate);
1102
+ el.removeEventListener("playing", currentAdEventHandlers.playing);
1103
+ el.removeEventListener("ended", currentAdEventHandlers.ended);
1104
+ el.removeEventListener("error", currentAdEventHandlers.error);
1105
+ el.removeEventListener("volumechange", currentAdEventHandlers.volumechange);
1106
+ el.removeEventListener("pause", currentAdEventHandlers.pause);
1107
+ el.removeEventListener("play", currentAdEventHandlers.play);
1108
+ currentAdEventHandlers = void 0;
1109
+ }
1095
1110
  function setupAdEventListeners() {
1096
1111
  if (!adVideoElement) return;
1097
- adVideoElement.addEventListener("timeupdate", function() {
1098
- var ad = currentAd;
1099
- if (!ad || !adVideoElement) return;
1100
- var progress = adVideoElement.currentTime / ad.duration;
1101
- if (progress >= 0.25 && !trackingFired.firstQuartile) {
1102
- trackingFired.firstQuartile = true;
1103
- fireTrackingPixels2(ad.trackingUrls.firstQuartile);
1104
- }
1105
- if (progress >= 0.5 && !trackingFired.midpoint) {
1106
- trackingFired.midpoint = true;
1107
- fireTrackingPixels2(ad.trackingUrls.midpoint);
1108
- }
1109
- if (progress >= 0.75 && !trackingFired.thirdQuartile) {
1110
- trackingFired.thirdQuartile = true;
1111
- fireTrackingPixels2(ad.trackingUrls.thirdQuartile);
1112
- }
1113
- });
1114
- adVideoElement.addEventListener("playing", function() {
1115
- var ad = currentAd;
1116
- if (!ad || trackingFired.start) return;
1117
- trackingFired.start = true;
1118
- fireTrackingPixels2(ad.trackingUrls.start);
1119
- if (debug) console.log("".concat(LOG, " Ad started playing"));
1120
- });
1121
- adVideoElement.addEventListener("ended", function() {
1122
- if (tornDown || !currentAd || trackingFired.complete) return;
1123
- trackingFired.complete = true;
1124
- fireTrackingPixels2(currentAd.trackingUrls.complete);
1125
- if (debug) console.log("".concat(LOG, " Ad completed"));
1126
- handleAdComplete();
1127
- });
1128
- adVideoElement.addEventListener("error", function(e) {
1129
- if (tornDown) return;
1130
- console.error("".concat(LOG, " Ad video error:"), e);
1131
- if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);
1132
- handleAdError();
1133
- });
1134
- adVideoElement.addEventListener("volumechange", function() {
1135
- if (!currentAd || !adVideoElement) return;
1136
- if (adVideoElement.muted) {
1137
- fireTrackingPixels2(currentAd.trackingUrls.mute);
1138
- } else {
1139
- fireTrackingPixels2(currentAd.trackingUrls.unmute);
1140
- }
1141
- });
1142
- adVideoElement.addEventListener("pause", function() {
1143
- if (currentAd && adVideoElement && !adVideoElement.ended) {
1144
- fireTrackingPixels2(currentAd.trackingUrls.pause);
1145
- }
1146
- });
1147
- adVideoElement.addEventListener("play", function() {
1148
- if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
1149
- fireTrackingPixels2(currentAd.trackingUrls.resume);
1112
+ removeAdEventListeners();
1113
+ var handlers = {
1114
+ timeupdate: function timeupdate() {
1115
+ var ad = currentAd;
1116
+ if (!ad || !adVideoElement) return;
1117
+ var progress = adVideoElement.currentTime / ad.duration;
1118
+ if (progress >= 0.25 && !trackingFired.firstQuartile) {
1119
+ trackingFired.firstQuartile = true;
1120
+ fireTrackingPixels2(ad.trackingUrls.firstQuartile);
1121
+ }
1122
+ if (progress >= 0.5 && !trackingFired.midpoint) {
1123
+ trackingFired.midpoint = true;
1124
+ fireTrackingPixels2(ad.trackingUrls.midpoint);
1125
+ }
1126
+ if (progress >= 0.75 && !trackingFired.thirdQuartile) {
1127
+ trackingFired.thirdQuartile = true;
1128
+ fireTrackingPixels2(ad.trackingUrls.thirdQuartile);
1129
+ }
1130
+ },
1131
+ playing: function playing() {
1132
+ var ad = currentAd;
1133
+ if (!ad || trackingFired.start) return;
1134
+ trackingFired.start = true;
1135
+ fireTrackingPixels2(ad.trackingUrls.start);
1136
+ if (debug) console.log("".concat(LOG, " Ad started playing"));
1137
+ },
1138
+ ended: function ended() {
1139
+ if (tornDown || !currentAd || trackingFired.complete) return;
1140
+ trackingFired.complete = true;
1141
+ fireTrackingPixels2(currentAd.trackingUrls.complete);
1142
+ if (debug) console.log("".concat(LOG, " Ad completed"));
1143
+ handleAdComplete();
1144
+ },
1145
+ error: function error(e) {
1146
+ if (tornDown) return;
1147
+ console.error("".concat(LOG, " Ad video error:"), e);
1148
+ if (currentAd) fireTrackingPixels2(currentAd.trackingUrls.error);
1149
+ handleAdError();
1150
+ },
1151
+ volumechange: function volumechange() {
1152
+ if (!currentAd || !adVideoElement) return;
1153
+ if (adVideoElement.muted) {
1154
+ fireTrackingPixels2(currentAd.trackingUrls.mute);
1155
+ } else {
1156
+ fireTrackingPixels2(currentAd.trackingUrls.unmute);
1157
+ }
1158
+ },
1159
+ pause: function pause() {
1160
+ if (currentAd && adVideoElement && !adVideoElement.ended) {
1161
+ fireTrackingPixels2(currentAd.trackingUrls.pause);
1162
+ }
1163
+ },
1164
+ play: function play() {
1165
+ if (currentAd && adVideoElement && adVideoElement.currentTime > 0) {
1166
+ fireTrackingPixels2(currentAd.trackingUrls.resume);
1167
+ }
1150
1168
  }
1151
- });
1169
+ };
1170
+ adVideoElement.addEventListener("timeupdate", handlers.timeupdate);
1171
+ adVideoElement.addEventListener("playing", handlers.playing);
1172
+ adVideoElement.addEventListener("ended", handlers.ended);
1173
+ adVideoElement.addEventListener("error", handlers.error);
1174
+ adVideoElement.addEventListener("volumechange", handlers.volumechange);
1175
+ adVideoElement.addEventListener("pause", handlers.pause);
1176
+ adVideoElement.addEventListener("play", handlers.play);
1177
+ currentAdEventHandlers = handlers;
1152
1178
  }
1153
1179
  function setAdPlayingFlag(isPlaying) {
1154
1180
  if (isPlaying) {
@@ -1171,6 +1197,7 @@ function createVastAdLayer(contentVideo, options) {
1171
1197
  }
1172
1198
  function handleAdError() {
1173
1199
  if (tornDown) return;
1200
+ if (!adPlaying) return;
1174
1201
  if (debug) console.log("".concat(LOG, " Handling ad error"));
1175
1202
  adPlaying = false;
1176
1203
  setAdPlayingFlag(false);
@@ -1181,14 +1208,19 @@ function createVastAdLayer(contentVideo, options) {
1181
1208
  emit("ad_error");
1182
1209
  }
1183
1210
  function teardownCurrentPlayback() {
1211
+ removeAdEventListeners();
1184
1212
  if (adHls) {
1185
1213
  adHls.destroy();
1186
1214
  adHls = void 0;
1187
1215
  }
1188
1216
  if (adVideoElement) {
1189
- adVideoElement.pause();
1190
- adVideoElement.removeAttribute("src");
1191
- adVideoElement.load();
1217
+ if (singleElementMode && adVideoElement === contentVideo) {
1218
+ contentVideo.pause();
1219
+ } else {
1220
+ adVideoElement.pause();
1221
+ adVideoElement.removeAttribute("src");
1222
+ adVideoElement.load();
1223
+ }
1192
1224
  }
1193
1225
  }
1194
1226
  function startNativePlayback(mediaFile) {
@@ -1221,8 +1253,17 @@ function createVastAdLayer(contentVideo, options) {
1221
1253
  handleAdError();
1222
1254
  });
1223
1255
  });
1256
+ var nonFatalNetworkErrors = 0;
1224
1257
  adHls.on(import_hls.default.Events.ERROR, function(_event, data) {
1225
- if (data.fatal) handleAdError();
1258
+ if (data.fatal) {
1259
+ handleAdError();
1260
+ } else if (data.type === import_hls.default.ErrorTypes.NETWORK_ERROR) {
1261
+ nonFatalNetworkErrors++;
1262
+ if (nonFatalNetworkErrors >= 3) {
1263
+ if (debug) console.warn("".concat(LOG, " Too many non-fatal HLS network errors (").concat(nonFatalNetworkErrors, "), treating as fatal"));
1264
+ handleAdError();
1265
+ }
1266
+ }
1226
1267
  });
1227
1268
  } else if (adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
1228
1269
  adVideoElement.src = mediaFile.url;
@@ -1245,7 +1286,7 @@ function createVastAdLayer(contentVideo, options) {
1245
1286
  }
1246
1287
  function playAd(bids) {
1247
1288
  return _async_to_generator(function() {
1248
- var winner, ad, _contentVideo_parentElement, container, contentVolume, adVolume, mediaFile;
1289
+ var winner, ad, contentVolume, _contentVideo_parentElement, container, adVolume, mediaFile;
1249
1290
  return _ts_generator(this, function(_state) {
1250
1291
  switch(_state.label){
1251
1292
  case 0:
@@ -1287,32 +1328,40 @@ function createVastAdLayer(contentVideo, options) {
1287
1328
  trackingFired = _object_spread({}, createEmptyTrackingState());
1288
1329
  fireTrackingPixels2(ad.trackingUrls.impression);
1289
1330
  trackingFired.impression = true;
1290
- if (!adContainerEl) {
1291
- ;
1292
- container = document.createElement("div");
1293
- container.style.position = "absolute";
1294
- container.style.left = "0";
1295
- container.style.top = "0";
1296
- container.style.right = "0";
1297
- container.style.bottom = "0";
1298
- container.style.display = "none";
1299
- container.style.alignItems = "center";
1300
- container.style.justifyContent = "center";
1301
- container.style.pointerEvents = "none";
1302
- container.style.zIndex = "10";
1303
- container.style.backgroundColor = "#000";
1304
- (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1305
- adContainerEl = container;
1306
- }
1307
- if (!adVideoElement) {
1308
- adVideoElement = createAdVideoElement();
1309
- adContainerEl.appendChild(adVideoElement);
1331
+ contentVolume = contentVideo.volume;
1332
+ originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1333
+ if (singleElementMode) {
1334
+ mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.detachMedia();
1335
+ teardownCurrentPlayback();
1336
+ adVideoElement = contentVideo;
1337
+ adHls = void 0;
1310
1338
  setupAdEventListeners();
1311
1339
  } else {
1312
- teardownCurrentPlayback();
1340
+ if (!adContainerEl) {
1341
+ ;
1342
+ container = document.createElement("div");
1343
+ container.style.position = "absolute";
1344
+ container.style.left = "0";
1345
+ container.style.top = "0";
1346
+ container.style.right = "0";
1347
+ container.style.bottom = "0";
1348
+ container.style.display = "none";
1349
+ container.style.alignItems = "center";
1350
+ container.style.justifyContent = "center";
1351
+ container.style.pointerEvents = "none";
1352
+ container.style.zIndex = "10";
1353
+ container.style.backgroundColor = "#000";
1354
+ (_contentVideo_parentElement = contentVideo.parentElement) === null || _contentVideo_parentElement === void 0 ? void 0 : _contentVideo_parentElement.appendChild(container);
1355
+ adContainerEl = container;
1356
+ }
1357
+ if (!adVideoElement) {
1358
+ adVideoElement = createAdVideoElement();
1359
+ adContainerEl.appendChild(adVideoElement);
1360
+ setupAdEventListeners();
1361
+ } else {
1362
+ teardownCurrentPlayback();
1363
+ }
1313
1364
  }
1314
- contentVolume = contentVideo.volume;
1315
- originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1316
1365
  if (!continueLiveStreamDuringAds) {
1317
1366
  contentVideo.pause();
1318
1367
  }
@@ -1323,7 +1372,7 @@ function createVastAdLayer(contentVideo, options) {
1323
1372
  adVolume = originalMutedState ? 1 : originalVolume;
1324
1373
  adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
1325
1374
  adVideoElement.muted = false;
1326
- if (adContainerEl) {
1375
+ if (!singleElementMode && adContainerEl) {
1327
1376
  adContainerEl.style.display = "flex";
1328
1377
  adContainerEl.style.pointerEvents = "auto";
1329
1378
  }
@@ -1360,7 +1409,7 @@ function createVastAdLayer(contentVideo, options) {
1360
1409
  }
1361
1410
  function preloadAd(bids, token) {
1362
1411
  return _async_to_generator(function() {
1363
- var winner, ad, mediaFile, videoEl, container, hls, slot, slot1;
1412
+ var winner, ad, mediaFile, slot, videoEl, container, hls, slot1, slot2;
1364
1413
  return _ts_generator(this, function(_state) {
1365
1414
  switch(_state.label){
1366
1415
  case 0:
@@ -1385,6 +1434,20 @@ function createVastAdLayer(contentVideo, options) {
1385
1434
  if (!mediaFile) return [
1386
1435
  2
1387
1436
  ];
1437
+ if (smartTVMode || singleElementMode) {
1438
+ slot = {
1439
+ bids: bids,
1440
+ ad: ad,
1441
+ mediaFile: mediaFile,
1442
+ videoEl: null,
1443
+ ready: true
1444
+ };
1445
+ preloadSlots.set(token, slot);
1446
+ if (debug) console.log("".concat(LOG, " [preload] Metadata-only preload (smartTV/singleElement), token=").concat(token, ", url=").concat(mediaFile.url));
1447
+ return [
1448
+ 2
1449
+ ];
1450
+ }
1388
1451
  videoEl = createAdVideoElement();
1389
1452
  videoEl.style.visibility = "hidden";
1390
1453
  videoEl.style.pointerEvents = "none";
@@ -1398,7 +1461,7 @@ function createVastAdLayer(contentVideo, options) {
1398
1461
  });
1399
1462
  hls.loadSource(mediaFile.url);
1400
1463
  hls.attachMedia(videoEl);
1401
- slot = {
1464
+ slot1 = {
1402
1465
  bids: bids,
1403
1466
  ad: ad,
1404
1467
  mediaFile: mediaFile,
@@ -1406,7 +1469,7 @@ function createVastAdLayer(contentVideo, options) {
1406
1469
  hlsInstance: hls,
1407
1470
  ready: false
1408
1471
  };
1409
- preloadSlots.set(token, slot);
1472
+ preloadSlots.set(token, slot1);
1410
1473
  hls.on(import_hls.default.Events.MANIFEST_PARSED, function() {
1411
1474
  var s = preloadSlots.get(token);
1412
1475
  if (s) s.ready = true;
@@ -1423,14 +1486,14 @@ function createVastAdLayer(contentVideo, options) {
1423
1486
  } else {
1424
1487
  videoEl.src = mediaFile.url;
1425
1488
  videoEl.load();
1426
- slot1 = {
1489
+ slot2 = {
1427
1490
  bids: bids,
1428
1491
  ad: ad,
1429
1492
  mediaFile: mediaFile,
1430
1493
  videoEl: videoEl,
1431
1494
  ready: false
1432
1495
  };
1433
- preloadSlots.set(token, slot1);
1496
+ preloadSlots.set(token, slot2);
1434
1497
  videoEl.addEventListener("canplay", function() {
1435
1498
  var s = preloadSlots.get(token);
1436
1499
  if (s) s.ready = true;
@@ -1449,7 +1512,7 @@ function createVastAdLayer(contentVideo, options) {
1449
1512
  }
1450
1513
  function playPreloaded(token) {
1451
1514
  return _async_to_generator(function() {
1452
- var slot, contentVolume, adVolume, container;
1515
+ var slot, contentVolume, adVolume2, videoEl, container2, adVolume21, adVolume, container;
1453
1516
  return _ts_generator(this, function(_state) {
1454
1517
  if (destroyed) return [
1455
1518
  2,
@@ -1464,6 +1527,68 @@ function createVastAdLayer(contentVideo, options) {
1464
1527
  }
1465
1528
  preloadSlots.delete(token);
1466
1529
  if (debug) console.log("".concat(LOG, " [preload] Playing preloaded ad, token=").concat(token, ", ready=").concat(slot.ready));
1530
+ contentVolume = contentVideo.volume;
1531
+ originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1532
+ sessionId = generateSessionId();
1533
+ currentAd = slot.ad;
1534
+ trackingFired = _object_spread({}, createEmptyTrackingState());
1535
+ fireTrackingPixels2(slot.ad.trackingUrls.impression);
1536
+ trackingFired.impression = true;
1537
+ if (singleElementMode) {
1538
+ mainHlsInstance === null || mainHlsInstance === void 0 ? void 0 : mainHlsInstance.detachMedia();
1539
+ teardownCurrentPlayback();
1540
+ adVideoElement = contentVideo;
1541
+ adHls = void 0;
1542
+ setupAdEventListeners();
1543
+ if (!continueLiveStreamDuringAds) {
1544
+ contentVideo.pause();
1545
+ }
1546
+ contentVideo.muted = true;
1547
+ contentVideo.volume = 0;
1548
+ adPlaying = true;
1549
+ setAdPlayingFlag(true);
1550
+ adVolume2 = originalMutedState ? 1 : originalVolume;
1551
+ contentVideo.volume = Math.max(0, Math.min(1, adVolume2));
1552
+ contentVideo.muted = false;
1553
+ emit("content_pause");
1554
+ if (debug) console.log("".concat(LOG, " [preload] singleElementMode: attaching ad to contentVideo, url=").concat(slot.mediaFile.url));
1555
+ startPlayback(slot.mediaFile);
1556
+ return [
1557
+ 2
1558
+ ];
1559
+ }
1560
+ if (smartTVMode && !slot.videoEl) {
1561
+ teardownCurrentPlayback();
1562
+ if (adVideoElement) {
1563
+ adVideoElement.remove();
1564
+ adVideoElement = void 0;
1565
+ }
1566
+ videoEl = createAdVideoElement();
1567
+ videoEl.style.visibility = "visible";
1568
+ videoEl.style.pointerEvents = "none";
1569
+ container2 = ensureAdContainer();
1570
+ container2.appendChild(videoEl);
1571
+ adVideoElement = videoEl;
1572
+ setupAdEventListeners();
1573
+ if (!continueLiveStreamDuringAds) {
1574
+ contentVideo.pause();
1575
+ }
1576
+ contentVideo.muted = true;
1577
+ contentVideo.volume = 0;
1578
+ adPlaying = true;
1579
+ setAdPlayingFlag(true);
1580
+ adVolume21 = originalMutedState ? 1 : originalVolume;
1581
+ adVideoElement.volume = Math.max(0, Math.min(1, adVolume21));
1582
+ adVideoElement.muted = false;
1583
+ container2.style.display = "flex";
1584
+ container2.style.pointerEvents = "auto";
1585
+ emit("content_pause");
1586
+ if (debug) console.log("".concat(LOG, " [preload] smartTVMode deferred: creating video element and loading, url=").concat(slot.mediaFile.url));
1587
+ startPlayback(slot.mediaFile);
1588
+ return [
1589
+ 2
1590
+ ];
1591
+ }
1467
1592
  teardownCurrentPlayback();
1468
1593
  if (adVideoElement && adVideoElement !== slot.videoEl) {
1469
1594
  adVideoElement.remove();
@@ -1473,13 +1598,6 @@ function createVastAdLayer(contentVideo, options) {
1473
1598
  adVideoElement = slot.videoEl;
1474
1599
  adHls = slot.hlsInstance;
1475
1600
  setupAdEventListeners();
1476
- sessionId = generateSessionId();
1477
- currentAd = slot.ad;
1478
- trackingFired = _object_spread({}, createEmptyTrackingState());
1479
- fireTrackingPixels2(slot.ad.trackingUrls.impression);
1480
- trackingFired.impression = true;
1481
- contentVolume = contentVideo.volume;
1482
- originalVolume = Math.max(0, Math.min(1, contentVolume || originalVolume));
1483
1601
  if (!continueLiveStreamDuringAds) {
1484
1602
  contentVideo.pause();
1485
1603
  }
@@ -1494,17 +1612,10 @@ function createVastAdLayer(contentVideo, options) {
1494
1612
  container.style.display = "flex";
1495
1613
  container.style.pointerEvents = "auto";
1496
1614
  emit("content_pause");
1497
- if (slot.hlsInstance) {
1498
- adVideoElement.play().catch(function(error) {
1499
- console.error("".concat(LOG, " [preload] Error playing preloaded HLS ad:"), error);
1500
- handleAdError();
1501
- });
1502
- } else {
1503
- adVideoElement.play().catch(function(error) {
1504
- console.error("".concat(LOG, " [preload] Error playing preloaded ad:"), error);
1505
- handleAdError();
1506
- });
1507
- }
1615
+ adVideoElement.play().catch(function(error) {
1616
+ console.error("".concat(LOG, " [preload] Error playing preloaded ad:"), error);
1617
+ handleAdError();
1618
+ });
1508
1619
  return [
1509
1620
  2
1510
1621
  ];
@@ -1518,10 +1629,12 @@ function createVastAdLayer(contentVideo, options) {
1518
1629
  if (slot.hlsInstance) {
1519
1630
  slot.hlsInstance.destroy();
1520
1631
  }
1521
- slot.videoEl.pause();
1522
- slot.videoEl.removeAttribute("src");
1523
- slot.videoEl.load();
1524
- slot.videoEl.remove();
1632
+ if (slot.videoEl) {
1633
+ slot.videoEl.pause();
1634
+ slot.videoEl.removeAttribute("src");
1635
+ slot.videoEl.load();
1636
+ slot.videoEl.remove();
1637
+ }
1525
1638
  if (debug) console.log("".concat(LOG, " [preload] Cancelled and cleaned up token=").concat(token));
1526
1639
  }
1527
1640
  return {
@@ -1569,20 +1682,27 @@ function createVastAdLayer(contentVideo, options) {
1569
1682
  setAdPlayingFlag(false);
1570
1683
  contentVideo.muted = originalMutedState;
1571
1684
  contentVideo.volume = originalMutedState ? 0 : originalVolume;
1572
- if (adContainerEl) {
1573
- adContainerEl.style.display = "none";
1574
- adContainerEl.style.pointerEvents = "none";
1575
- }
1576
1685
  contentVideo.style.visibility = "visible";
1577
1686
  contentVideo.style.opacity = "1";
1578
- if (continueLiveStreamDuringAds) {
1579
- contentVideo.play().catch(function() {});
1580
- }
1581
- teardownCurrentPlayback();
1582
- if (adVideoElement) {
1583
- adVideoElement.pause();
1584
- adVideoElement.removeAttribute("src");
1585
- adVideoElement.load();
1687
+ if (singleElementMode) {
1688
+ teardownCurrentPlayback();
1689
+ contentVideo.removeAttribute("src");
1690
+ contentVideo.load();
1691
+ adVideoElement = void 0;
1692
+ } else {
1693
+ if (adContainerEl) {
1694
+ adContainerEl.style.display = "none";
1695
+ adContainerEl.style.pointerEvents = "none";
1696
+ }
1697
+ if (continueLiveStreamDuringAds) {
1698
+ contentVideo.play().catch(function() {});
1699
+ }
1700
+ teardownCurrentPlayback();
1701
+ if (adVideoElement) {
1702
+ adVideoElement.pause();
1703
+ adVideoElement.removeAttribute("src");
1704
+ adVideoElement.load();
1705
+ }
1586
1706
  }
1587
1707
  currentAd = void 0;
1588
1708
  tornDown = false;
@@ -1622,9 +1742,14 @@ function createVastAdLayer(contentVideo, options) {
1622
1742
  }
1623
1743
  teardownCurrentPlayback();
1624
1744
  if (adVideoElement) {
1625
- adVideoElement.pause();
1626
- adVideoElement.removeAttribute("src");
1627
- adVideoElement.remove();
1745
+ if (singleElementMode && adVideoElement === contentVideo) {
1746
+ contentVideo.removeAttribute("src");
1747
+ contentVideo.load();
1748
+ } else {
1749
+ adVideoElement.pause();
1750
+ adVideoElement.removeAttribute("src");
1751
+ adVideoElement.remove();
1752
+ }
1628
1753
  adVideoElement = void 0;
1629
1754
  }
1630
1755
  if (adContainerEl === null || adContainerEl === void 0 ? void 0 : adContainerEl.parentElement) {
@@ -2822,8 +2947,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2822
2947
  this.vastManager = createVastManager(config.debugAdTiming !== void 0 ? {
2823
2948
  debug: !!config.debugAdTiming
2824
2949
  } : {});
2950
+ var browserForAdLayer = detectBrowser();
2825
2951
  this.adLayer = createVastAdLayer(this.video, {
2826
2952
  continueLiveStreamDuringAds: false,
2953
+ smartTVMode: browserForAdLayer.isSmartTV,
2954
+ singleElementMode: browserForAdLayer.isSmartTV,
2827
2955
  debug: !!config.debugAdTiming
2828
2956
  });
2829
2957
  }
@@ -4185,6 +4313,10 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4185
4313
  if (!this.isLiveStream) {
4186
4314
  return false;
4187
4315
  }
4316
+ var browser = detectBrowser();
4317
+ if (browser.isSmartTV) {
4318
+ return false;
4319
+ }
4188
4320
  return true;
4189
4321
  }
4190
4322
  },
@@ -4392,7 +4524,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4392
4524
  switch(_state.label){
4393
4525
  case 0:
4394
4526
  _loop = function() {
4395
- var remaining, prefetchContext, bids, err, bids1, remainingNow, delay, elapsed, remaining1, context, bids2, remainingNow1, err1;
4527
+ var remaining, prefetchContext, bids, err, bids1, remainingNow, urgentNeedAd, delay, elapsed, remaining1, context, bids2, remainingNow1, err1, sleepMs;
4396
4528
  return _ts_generator(this, function(_state) {
4397
4529
  switch(_state.label){
4398
4530
  case 0:
@@ -4528,7 +4660,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4528
4660
  "continue"
4529
4661
  ];
4530
4662
  case 12:
4531
- delay = _this.lastAdRequestTime ? _this.minAdRequestIntervalMs + (_this.consecutiveFailures > 0 ? backoffMs() : 0) : 0;
4663
+ urgentNeedAd = _this.inAdBreak && !_this.adLayer.isAdPlaying();
4664
+ delay = _this.lastAdRequestTime ? _this.minAdRequestIntervalMs + (!urgentNeedAd && _this.consecutiveFailures > 0 ? backoffMs() : 0) : 0;
4532
4665
  elapsed = Date.now() - _this.lastAdRequestTime;
4533
4666
  if (!(elapsed < delay && _this.lastAdRequestTime > 0)) return [
4534
4667
  3,
@@ -4647,10 +4780,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4647
4780
  24
4648
4781
  ];
4649
4782
  case 24:
4783
+ sleepMs = _this.inAdBreak && !_this.adLayer.isAdPlaying() ? 0 : backoffMs();
4650
4784
  return [
4651
4785
  4,
4652
4786
  new Promise(function(r) {
4653
- return setTimeout(r, backoffMs());
4787
+ return setTimeout(r, sleepMs);
4654
4788
  })
4655
4789
  ];
4656
4790
  case 25:
@@ -5331,40 +5465,45 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5331
5465
  var browser = detectBrowser();
5332
5466
  var isSmartTV = browser.tizenVersion !== void 0 || browser.webOSVersion !== void 0;
5333
5467
  if (isSmartTV && this.hls) {
5334
- if (!restoredMuted) {
5335
- var hlsRef = this.hls;
5336
- var savedMuted = restoredMuted;
5337
- var savedVolume = restoredVolume;
5338
- var onManifestParsedRestore = function onManifestParsedRestore1() {
5339
- hlsRef.off(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5340
- if (!_this.inAdBreak && !_this.adLayer.isAdPlaying()) {
5341
- if (_this.video.muted !== savedMuted) _this.video.muted = savedMuted;
5342
- if (Math.abs(_this.video.volume - savedVolume) > 0.01) _this.video.volume = savedVolume;
5343
- if (_this.config.debugAdTiming) {
5344
- console.log("[StormcloudVideoPlayer] Smart TV: audio state restored on MANIFEST_PARSED after re-attach");
5345
- }
5468
+ var hlsRef = this.hls;
5469
+ var savedMuted = restoredMuted;
5470
+ var savedVolume = restoredVolume;
5471
+ var onManifestParsedRestore = function onManifestParsedRestore1() {
5472
+ hlsRef.off(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5473
+ if (!_this.inAdBreak && !_this.adLayer.isAdPlaying()) {
5474
+ var _this_video_play;
5475
+ if (_this.video.muted !== savedMuted) _this.video.muted = savedMuted;
5476
+ if (Math.abs(_this.video.volume - savedVolume) > 0.01) _this.video.volume = savedVolume;
5477
+ if (_this.config.debugAdTiming) {
5478
+ console.log("[StormcloudVideoPlayer] Smart TV: audio state restored on MANIFEST_PARSED after re-attach");
5346
5479
  }
5347
- };
5348
- hlsRef.on(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5349
- }
5480
+ hlsRef.startLoad(-1);
5481
+ (_this_video_play = _this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
5482
+ if (_this.config.debugAdTiming) {
5483
+ console.log("[StormcloudVideoPlayer] Smart TV: seeking to live edge and resuming playback after re-attach");
5484
+ }
5485
+ }
5486
+ };
5487
+ hlsRef.on(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5350
5488
  this.hls.attachMedia(this.video);
5351
5489
  if (this.config.debugAdTiming) {
5352
5490
  console.log("[StormcloudVideoPlayer] Smart TV: re-attached HLS to video element after ad break to restore media pipeline");
5353
5491
  }
5354
- }
5355
- if (this.shouldContinueLiveStreamDuringAds()) {
5356
- var _this_video_play;
5357
- if (this.config.debugAdTiming) {
5358
- if (this.video.paused) {
5359
- console.log("[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback");
5360
- } else {
5361
- console.log("[StormcloudVideoPlayer] Content video already playing in live mode after ads");
5492
+ } else {
5493
+ if (this.shouldContinueLiveStreamDuringAds()) {
5494
+ var _this_video_play;
5495
+ if (this.config.debugAdTiming) {
5496
+ if (this.video.paused) {
5497
+ console.log("[StormcloudVideoPlayer] Content video paused in live mode after ads, resuming playback");
5498
+ } else {
5499
+ console.log("[StormcloudVideoPlayer] Content video already playing in live mode after ads");
5500
+ }
5362
5501
  }
5502
+ (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
5503
+ } else if (this.video.paused) {
5504
+ var _this_video_play1;
5505
+ (_this_video_play1 = this.video.play()) === null || _this_video_play1 === void 0 ? void 0 : _this_video_play1.catch(function() {});
5363
5506
  }
5364
- (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
5365
- } else if (this.video.paused) {
5366
- var _this_video_play1;
5367
- (_this_video_play1 = this.video.play()) === null || _this_video_play1 === void 0 ? void 0 : _this_video_play1.catch(function() {});
5368
5507
  }
5369
5508
  this.syncMainContentAudioWhenVisible();
5370
5509
  if (!restoredMuted) {
@@ -5415,6 +5554,14 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5415
5554
  console.log("[CONTINUOUS-FETCH] \uD83D\uDED1 Max consecutive failures reached (".concat(this.consecutiveFailures, "), ending ad break gracefully"));
5416
5555
  }
5417
5556
  this.handleAdPodComplete();
5557
+ return;
5558
+ }
5559
+ if (this.inAdBreak && !this.config.disableFiller) {
5560
+ if (this.config.debugAdTiming) {
5561
+ console.log("[CONTINUOUS-FETCH] Ad failure in active break \u2014 showing filler while awaiting next ad");
5562
+ }
5563
+ this.showPlaceholderLayer();
5564
+ this.adLayer.showPlaceholder();
5418
5565
  }
5419
5566
  }
5420
5567
  },