stormcloud-video-player 0.6.1 → 0.6.2

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.
@@ -1,4 +1,4 @@
1
- import { V as VastBidResponse } from '../types-CwDRIvJm.cjs';
1
+ import { V as VastBidResponse } from '../types-BYwfSJb5.cjs';
2
2
  import Hls from 'hls.js';
3
3
 
4
4
  interface VastAdLayerOptions {
@@ -6,6 +6,7 @@ interface VastAdLayerOptions {
6
6
  mainHlsInstance?: Hls;
7
7
  smartTVMode?: boolean;
8
8
  singleElementMode?: boolean;
9
+ forceMP4Ads?: boolean;
9
10
  debug?: boolean;
10
11
  }
11
12
  interface VastAdLayerOptionsUpdate {
@@ -1,4 +1,4 @@
1
- import { a as VastManager } from '../types-CwDRIvJm.cjs';
1
+ import { a as VastManager } from '../types-BYwfSJb5.cjs';
2
2
 
3
3
  interface VastManagerOptions {
4
4
  debug?: boolean;
@@ -21,6 +21,7 @@ interface StormcloudVideoPlayerConfig {
21
21
  disableAds?: boolean;
22
22
  disableFiller?: boolean;
23
23
  adTransitionGapMs?: number;
24
+ singlePipelineMode?: boolean;
24
25
  }
25
26
  interface ClientInfo {
26
27
  brand: string;
@@ -960,7 +960,7 @@ function resolveBidToVastAd(winner, logPrefix) {
960
960
  return Promise.resolve(null);
961
961
  }
962
962
  function createVastAdLayer(contentVideo, options) {
963
- var _ref, _ref1, _ref2, _ref3;
963
+ var _ref, _ref1, _ref2, _ref3, _ref4;
964
964
  var adPlaying = false;
965
965
  var originalMutedState = false;
966
966
  var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
@@ -969,7 +969,8 @@ function createVastAdLayer(contentVideo, options) {
969
969
  var continueLiveStreamDuringAds = (_ref = options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) !== null && _ref !== void 0 ? _ref : false;
970
970
  var smartTVMode = (_ref1 = options === null || options === void 0 ? void 0 : options.smartTVMode) !== null && _ref1 !== void 0 ? _ref1 : false;
971
971
  var singleElementMode = (_ref2 = options === null || options === void 0 ? void 0 : options.singleElementMode) !== null && _ref2 !== void 0 ? _ref2 : false;
972
- var debug = (_ref3 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref3 !== void 0 ? _ref3 : false;
972
+ var forceMP4Ads = (_ref3 = options === null || options === void 0 ? void 0 : options.forceMP4Ads) !== null && _ref3 !== void 0 ? _ref3 : smartTVMode || singleElementMode;
973
+ var debug = (_ref4 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref4 !== void 0 ? _ref4 : false;
973
974
  var adVideoElement;
974
975
  var adHls;
975
976
  var adContainerEl;
@@ -1040,14 +1041,26 @@ function createVastAdLayer(contentVideo, options) {
1040
1041
  var _ref;
1041
1042
  var _scoredFiles_;
1042
1043
  if (mediaFiles.length === 0) throw new Error("No media files available");
1043
- var firstFile = mediaFiles[0];
1044
- if (mediaFiles.length === 1) return firstFile;
1044
+ var candidates = mediaFiles;
1045
+ if (forceMP4Ads) {
1046
+ var mp4Only = candidates.filter(function(f) {
1047
+ return !isHlsMediaFile(f);
1048
+ });
1049
+ if (mp4Only.length > 0) {
1050
+ candidates = mp4Only;
1051
+ if (debug) console.log("".concat(LOG, " forceMP4Ads: filtered to ").concat(mp4Only.length, " MP4-only file(s)"));
1052
+ } else if (debug) {
1053
+ console.warn("".concat(LOG, " forceMP4Ads: no MP4 files available, falling back to all media files"));
1054
+ }
1055
+ }
1056
+ var firstFile = candidates[0];
1057
+ if (candidates.length === 1) return firstFile;
1045
1058
  var mainQuality = getMainStreamQuality();
1046
1059
  if (!mainQuality) {
1047
1060
  if (debug) console.log("".concat(LOG, " No main stream quality info, using first media file"));
1048
1061
  return firstFile;
1049
1062
  }
1050
- var scoredFiles = mediaFiles.map(function(file) {
1063
+ var scoredFiles = candidates.map(function(file) {
1051
1064
  var widthDiff = Math.abs(file.width - mainQuality.width);
1052
1065
  var heightDiff = Math.abs(file.height - mainQuality.height);
1053
1066
  var resolutionDiff = widthDiff + heightDiff;
@@ -1264,6 +1277,16 @@ function createVastAdLayer(contentVideo, options) {
1264
1277
  }
1265
1278
  function startPlayback(mediaFile) {
1266
1279
  if (!adVideoElement) return;
1280
+ if (singleElementMode && isHlsMediaFile(mediaFile)) {
1281
+ var mp4Fallback = currentAd === null || currentAd === void 0 ? void 0 : currentAd.mediaFiles.find(function(f) {
1282
+ return !isHlsMediaFile(f);
1283
+ });
1284
+ if (mp4Fallback) {
1285
+ if (debug) console.log("".concat(LOG, " singleElementMode: HLS ad blocked, using MP4 fallback"));
1286
+ startNativePlayback(mp4Fallback);
1287
+ return;
1288
+ }
1289
+ }
1267
1290
  if (isHlsMediaFile(mediaFile)) {
1268
1291
  startHlsPlayback(mediaFile);
1269
1292
  } else {
@@ -2934,10 +2957,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2934
2957
  debug: !!config.debugAdTiming
2935
2958
  } : {});
2936
2959
  var browserForAdLayer = detectBrowser();
2960
+ var isSinglePipeline = browserForAdLayer.isSmartTV || !!this.config.singlePipelineMode;
2937
2961
  this.adLayer = createVastAdLayer(this.video, {
2938
2962
  continueLiveStreamDuringAds: false,
2939
- smartTVMode: browserForAdLayer.isSmartTV,
2940
- singleElementMode: browserForAdLayer.isSmartTV,
2963
+ smartTVMode: isSinglePipeline,
2964
+ singleElementMode: isSinglePipeline,
2965
+ forceMP4Ads: isSinglePipeline,
2941
2966
  debug: !!config.debugAdTiming
2942
2967
  });
2943
2968
  }
@@ -3583,6 +3608,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3583
3608
  if (_this.fillerVideo) {
3584
3609
  _this.fillerVideo.style.display = "none";
3585
3610
  }
3611
+ if (!_this.adLayer.isAdPlaying()) {
3612
+ if (_this.config.debugAdTiming) {
3613
+ console.log("[StormcloudVideoPlayer] Filler video failed \u2014 restoring main video");
3614
+ }
3615
+ _this.adLayer.hidePlaceholder();
3616
+ if (_this.video.paused && _this.video.readyState >= 2) {
3617
+ var _this_video_play;
3618
+ (_this_video_play = _this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
3619
+ }
3620
+ }
3586
3621
  });
3587
3622
  if (this.config.debugAdTiming) {
3588
3623
  console.log("[StormcloudVideoPlayer] Showing filler video layer");
@@ -4299,6 +4334,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4299
4334
  if (!this.isLiveStream) {
4300
4335
  return false;
4301
4336
  }
4337
+ if (this.config.singlePipelineMode) {
4338
+ return false;
4339
+ }
4302
4340
  var browser = detectBrowser();
4303
4341
  if (browser.isSmartTV) {
4304
4342
  return false;
@@ -5449,32 +5487,56 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5449
5487
  this.video.volume = restoredVolume;
5450
5488
  }
5451
5489
  var browser = detectBrowser();
5452
- var isSmartTV = browser.tizenVersion !== void 0 || browser.webOSVersion !== void 0;
5490
+ var isSmartTV = browser.tizenVersion !== void 0 || browser.webOSVersion !== void 0 || !!this.config.singlePipelineMode;
5453
5491
  if (isSmartTV && this.hls) {
5454
5492
  var hlsRef = this.hls;
5455
5493
  var savedMuted = restoredMuted;
5456
5494
  var savedVolume = restoredVolume;
5495
+ var videoRef = this.video;
5496
+ var debugEnabled = this.config.debugAdTiming;
5497
+ var tryPlay = function tryPlay1(attempt) {
5498
+ var _videoRef_play;
5499
+ if (_this.inAdBreak || _this.adLayer.isAdPlaying()) return;
5500
+ (_videoRef_play = videoRef.play()) === null || _videoRef_play === void 0 ? void 0 : _videoRef_play.catch(function() {
5501
+ if (attempt < 3) {
5502
+ if (debugEnabled) {
5503
+ console.log("[StormcloudVideoPlayer] Smart TV: play() retry ".concat(attempt + 1, "/3 in ").concat(500 * (attempt + 1), "ms"));
5504
+ }
5505
+ setTimeout(function() {
5506
+ return tryPlay(attempt + 1);
5507
+ }, 500 * (attempt + 1));
5508
+ }
5509
+ });
5510
+ };
5457
5511
  var onManifestParsedRestore = function onManifestParsedRestore1() {
5458
5512
  hlsRef.off(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5459
5513
  if (!_this.inAdBreak && !_this.adLayer.isAdPlaying()) {
5460
- var _this_video_play;
5461
- if (_this.video.muted !== savedMuted) _this.video.muted = savedMuted;
5462
- if (Math.abs(_this.video.volume - savedVolume) > 0.01) _this.video.volume = savedVolume;
5463
- if (_this.config.debugAdTiming) {
5514
+ if (videoRef.muted !== savedMuted) videoRef.muted = savedMuted;
5515
+ if (Math.abs(videoRef.volume - savedVolume) > 0.01) videoRef.volume = savedVolume;
5516
+ if (debugEnabled) {
5464
5517
  console.log("[StormcloudVideoPlayer] Smart TV: audio state restored on MANIFEST_PARSED after re-attach");
5465
5518
  }
5466
5519
  hlsRef.startLoad(-1);
5467
- (_this_video_play = _this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
5468
- if (_this.config.debugAdTiming) {
5520
+ tryPlay(0);
5521
+ if (debugEnabled) {
5469
5522
  console.log("[StormcloudVideoPlayer] Smart TV: seeking to live edge and resuming playback after re-attach");
5470
5523
  }
5471
5524
  }
5472
5525
  };
5473
5526
  hlsRef.on(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5474
- this.hls.attachMedia(this.video);
5475
- if (this.config.debugAdTiming) {
5476
- console.log("[StormcloudVideoPlayer] Smart TV: re-attached HLS to video element after ad break to restore media pipeline");
5527
+ var pipelineDelayMs = 300;
5528
+ if (debugEnabled) {
5529
+ console.log("[StormcloudVideoPlayer] Smart TV: waiting ".concat(pipelineDelayMs, "ms for hardware pipeline release before re-attach"));
5477
5530
  }
5531
+ setTimeout(function() {
5532
+ if (_this.inAdBreak || _this.adLayer.isAdPlaying()) return;
5533
+ if (_this.hls) {
5534
+ _this.hls.attachMedia(_this.video);
5535
+ if (debugEnabled) {
5536
+ console.log("[StormcloudVideoPlayer] Smart TV: re-attached HLS to video element after ad break to restore media pipeline");
5537
+ }
5538
+ }
5539
+ }, pipelineDelayMs);
5478
5540
  } else {
5479
5541
  if (this.shouldContinueLiveStreamDuringAds()) {
5480
5542
  var _this_video_play;
@@ -5548,6 +5610,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5548
5610
  }
5549
5611
  this.showPlaceholderLayer();
5550
5612
  this.adLayer.showPlaceholder();
5613
+ } else if (this.inAdBreak) {
5614
+ if (this.config.debugAdTiming) {
5615
+ console.log("[CONTINUOUS-FETCH] Ad failure with no filler \u2014 restoring main video temporarily");
5616
+ }
5617
+ this.adLayer.hidePlaceholder();
5618
+ if (!this.adLayer.isAdPlaying() && this.video.paused && this.video.readyState >= 2) {
5619
+ var _this_video_play;
5620
+ (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
5621
+ }
5551
5622
  }
5552
5623
  }
5553
5624
  },