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.
package/lib/index.cjs CHANGED
@@ -1104,7 +1104,7 @@ function resolveBidToVastAd(winner, logPrefix) {
1104
1104
  return Promise.resolve(null);
1105
1105
  }
1106
1106
  function createVastAdLayer(contentVideo, options) {
1107
- var _ref, _ref1, _ref2, _ref3;
1107
+ var _ref, _ref1, _ref2, _ref3, _ref4;
1108
1108
  var adPlaying = false;
1109
1109
  var originalMutedState = false;
1110
1110
  var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
@@ -1113,7 +1113,8 @@ function createVastAdLayer(contentVideo, options) {
1113
1113
  var continueLiveStreamDuringAds = (_ref = options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) !== null && _ref !== void 0 ? _ref : false;
1114
1114
  var smartTVMode = (_ref1 = options === null || options === void 0 ? void 0 : options.smartTVMode) !== null && _ref1 !== void 0 ? _ref1 : false;
1115
1115
  var singleElementMode = (_ref2 = options === null || options === void 0 ? void 0 : options.singleElementMode) !== null && _ref2 !== void 0 ? _ref2 : false;
1116
- var debug = (_ref3 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref3 !== void 0 ? _ref3 : false;
1116
+ var forceMP4Ads = (_ref3 = options === null || options === void 0 ? void 0 : options.forceMP4Ads) !== null && _ref3 !== void 0 ? _ref3 : smartTVMode || singleElementMode;
1117
+ var debug = (_ref4 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref4 !== void 0 ? _ref4 : false;
1117
1118
  var adVideoElement;
1118
1119
  var adHls;
1119
1120
  var adContainerEl;
@@ -1184,14 +1185,26 @@ function createVastAdLayer(contentVideo, options) {
1184
1185
  var _ref;
1185
1186
  var _scoredFiles_;
1186
1187
  if (mediaFiles.length === 0) throw new Error("No media files available");
1187
- var firstFile = mediaFiles[0];
1188
- if (mediaFiles.length === 1) return firstFile;
1188
+ var candidates = mediaFiles;
1189
+ if (forceMP4Ads) {
1190
+ var mp4Only = candidates.filter(function(f) {
1191
+ return !isHlsMediaFile(f);
1192
+ });
1193
+ if (mp4Only.length > 0) {
1194
+ candidates = mp4Only;
1195
+ if (debug) console.log("".concat(LOG, " forceMP4Ads: filtered to ").concat(mp4Only.length, " MP4-only file(s)"));
1196
+ } else if (debug) {
1197
+ console.warn("".concat(LOG, " forceMP4Ads: no MP4 files available, falling back to all media files"));
1198
+ }
1199
+ }
1200
+ var firstFile = candidates[0];
1201
+ if (candidates.length === 1) return firstFile;
1189
1202
  var mainQuality = getMainStreamQuality();
1190
1203
  if (!mainQuality) {
1191
1204
  if (debug) console.log("".concat(LOG, " No main stream quality info, using first media file"));
1192
1205
  return firstFile;
1193
1206
  }
1194
- var scoredFiles = mediaFiles.map(function(file) {
1207
+ var scoredFiles = candidates.map(function(file) {
1195
1208
  var widthDiff = Math.abs(file.width - mainQuality.width);
1196
1209
  var heightDiff = Math.abs(file.height - mainQuality.height);
1197
1210
  var resolutionDiff = widthDiff + heightDiff;
@@ -1408,6 +1421,16 @@ function createVastAdLayer(contentVideo, options) {
1408
1421
  }
1409
1422
  function startPlayback(mediaFile) {
1410
1423
  if (!adVideoElement) return;
1424
+ if (singleElementMode && isHlsMediaFile(mediaFile)) {
1425
+ var mp4Fallback = currentAd === null || currentAd === void 0 ? void 0 : currentAd.mediaFiles.find(function(f) {
1426
+ return !isHlsMediaFile(f);
1427
+ });
1428
+ if (mp4Fallback) {
1429
+ if (debug) console.log("".concat(LOG, " singleElementMode: HLS ad blocked, using MP4 fallback"));
1430
+ startNativePlayback(mp4Fallback);
1431
+ return;
1432
+ }
1433
+ }
1411
1434
  if (isHlsMediaFile(mediaFile)) {
1412
1435
  startHlsPlayback(mediaFile);
1413
1436
  } else {
@@ -3103,10 +3126,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3103
3126
  debug: !!config.debugAdTiming
3104
3127
  } : {});
3105
3128
  var browserForAdLayer = detectBrowser();
3129
+ var isSinglePipeline = browserForAdLayer.isSmartTV || !!this.config.singlePipelineMode;
3106
3130
  this.adLayer = createVastAdLayer(this.video, {
3107
3131
  continueLiveStreamDuringAds: false,
3108
- smartTVMode: browserForAdLayer.isSmartTV,
3109
- singleElementMode: browserForAdLayer.isSmartTV,
3132
+ smartTVMode: isSinglePipeline,
3133
+ singleElementMode: isSinglePipeline,
3134
+ forceMP4Ads: isSinglePipeline,
3110
3135
  debug: !!config.debugAdTiming
3111
3136
  });
3112
3137
  }
@@ -3752,6 +3777,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3752
3777
  if (_this.fillerVideo) {
3753
3778
  _this.fillerVideo.style.display = "none";
3754
3779
  }
3780
+ if (!_this.adLayer.isAdPlaying()) {
3781
+ if (_this.config.debugAdTiming) {
3782
+ console.log("[StormcloudVideoPlayer] Filler video failed \u2014 restoring main video");
3783
+ }
3784
+ _this.adLayer.hidePlaceholder();
3785
+ if (_this.video.paused && _this.video.readyState >= 2) {
3786
+ var _this_video_play;
3787
+ (_this_video_play = _this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
3788
+ }
3789
+ }
3755
3790
  });
3756
3791
  if (this.config.debugAdTiming) {
3757
3792
  console.log("[StormcloudVideoPlayer] Showing filler video layer");
@@ -4468,6 +4503,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4468
4503
  if (!this.isLiveStream) {
4469
4504
  return false;
4470
4505
  }
4506
+ if (this.config.singlePipelineMode) {
4507
+ return false;
4508
+ }
4471
4509
  var browser = detectBrowser();
4472
4510
  if (browser.isSmartTV) {
4473
4511
  return false;
@@ -5618,32 +5656,56 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5618
5656
  this.video.volume = restoredVolume;
5619
5657
  }
5620
5658
  var browser = detectBrowser();
5621
- var isSmartTV = browser.tizenVersion !== void 0 || browser.webOSVersion !== void 0;
5659
+ var isSmartTV = browser.tizenVersion !== void 0 || browser.webOSVersion !== void 0 || !!this.config.singlePipelineMode;
5622
5660
  if (isSmartTV && this.hls) {
5623
5661
  var hlsRef = this.hls;
5624
5662
  var savedMuted = restoredMuted;
5625
5663
  var savedVolume = restoredVolume;
5664
+ var videoRef = this.video;
5665
+ var debugEnabled = this.config.debugAdTiming;
5666
+ var tryPlay = function tryPlay1(attempt) {
5667
+ var _videoRef_play;
5668
+ if (_this.inAdBreak || _this.adLayer.isAdPlaying()) return;
5669
+ (_videoRef_play = videoRef.play()) === null || _videoRef_play === void 0 ? void 0 : _videoRef_play.catch(function() {
5670
+ if (attempt < 3) {
5671
+ if (debugEnabled) {
5672
+ console.log("[StormcloudVideoPlayer] Smart TV: play() retry ".concat(attempt + 1, "/3 in ").concat(500 * (attempt + 1), "ms"));
5673
+ }
5674
+ setTimeout(function() {
5675
+ return tryPlay(attempt + 1);
5676
+ }, 500 * (attempt + 1));
5677
+ }
5678
+ });
5679
+ };
5626
5680
  var onManifestParsedRestore = function onManifestParsedRestore1() {
5627
5681
  hlsRef.off(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5628
5682
  if (!_this.inAdBreak && !_this.adLayer.isAdPlaying()) {
5629
- var _this_video_play;
5630
- if (_this.video.muted !== savedMuted) _this.video.muted = savedMuted;
5631
- if (Math.abs(_this.video.volume - savedVolume) > 0.01) _this.video.volume = savedVolume;
5632
- if (_this.config.debugAdTiming) {
5683
+ if (videoRef.muted !== savedMuted) videoRef.muted = savedMuted;
5684
+ if (Math.abs(videoRef.volume - savedVolume) > 0.01) videoRef.volume = savedVolume;
5685
+ if (debugEnabled) {
5633
5686
  console.log("[StormcloudVideoPlayer] Smart TV: audio state restored on MANIFEST_PARSED after re-attach");
5634
5687
  }
5635
5688
  hlsRef.startLoad(-1);
5636
- (_this_video_play = _this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
5637
- if (_this.config.debugAdTiming) {
5689
+ tryPlay(0);
5690
+ if (debugEnabled) {
5638
5691
  console.log("[StormcloudVideoPlayer] Smart TV: seeking to live edge and resuming playback after re-attach");
5639
5692
  }
5640
5693
  }
5641
5694
  };
5642
5695
  hlsRef.on(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5643
- this.hls.attachMedia(this.video);
5644
- if (this.config.debugAdTiming) {
5645
- console.log("[StormcloudVideoPlayer] Smart TV: re-attached HLS to video element after ad break to restore media pipeline");
5696
+ var pipelineDelayMs = 300;
5697
+ if (debugEnabled) {
5698
+ console.log("[StormcloudVideoPlayer] Smart TV: waiting ".concat(pipelineDelayMs, "ms for hardware pipeline release before re-attach"));
5646
5699
  }
5700
+ setTimeout(function() {
5701
+ if (_this.inAdBreak || _this.adLayer.isAdPlaying()) return;
5702
+ if (_this.hls) {
5703
+ _this.hls.attachMedia(_this.video);
5704
+ if (debugEnabled) {
5705
+ console.log("[StormcloudVideoPlayer] Smart TV: re-attached HLS to video element after ad break to restore media pipeline");
5706
+ }
5707
+ }
5708
+ }, pipelineDelayMs);
5647
5709
  } else {
5648
5710
  if (this.shouldContinueLiveStreamDuringAds()) {
5649
5711
  var _this_video_play;
@@ -5717,6 +5779,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5717
5779
  }
5718
5780
  this.showPlaceholderLayer();
5719
5781
  this.adLayer.showPlaceholder();
5782
+ } else if (this.inAdBreak) {
5783
+ if (this.config.debugAdTiming) {
5784
+ console.log("[CONTINUOUS-FETCH] Ad failure with no filler \u2014 restoring main video temporarily");
5785
+ }
5786
+ this.adLayer.hidePlaceholder();
5787
+ if (!this.adLayer.isAdPlaying() && this.video.paused && this.video.readyState >= 2) {
5788
+ var _this_video_play;
5789
+ (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
5790
+ }
5720
5791
  }
5721
5792
  }
5722
5793
  },