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.
@@ -922,7 +922,7 @@ function resolveBidToVastAd(winner, logPrefix) {
922
922
  return Promise.resolve(null);
923
923
  }
924
924
  function createVastAdLayer(contentVideo, options) {
925
- var _ref, _ref1, _ref2, _ref3;
925
+ var _ref, _ref1, _ref2, _ref3, _ref4;
926
926
  var adPlaying = false;
927
927
  var originalMutedState = false;
928
928
  var originalVolume = Math.max(0, Math.min(1, contentVideo.volume || 1));
@@ -931,7 +931,8 @@ function createVastAdLayer(contentVideo, options) {
931
931
  var continueLiveStreamDuringAds = (_ref = options === null || options === void 0 ? void 0 : options.continueLiveStreamDuringAds) !== null && _ref !== void 0 ? _ref : false;
932
932
  var smartTVMode = (_ref1 = options === null || options === void 0 ? void 0 : options.smartTVMode) !== null && _ref1 !== void 0 ? _ref1 : false;
933
933
  var singleElementMode = (_ref2 = options === null || options === void 0 ? void 0 : options.singleElementMode) !== null && _ref2 !== void 0 ? _ref2 : false;
934
- var debug = (_ref3 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref3 !== void 0 ? _ref3 : false;
934
+ var forceMP4Ads = (_ref3 = options === null || options === void 0 ? void 0 : options.forceMP4Ads) !== null && _ref3 !== void 0 ? _ref3 : smartTVMode || singleElementMode;
935
+ var debug = (_ref4 = options === null || options === void 0 ? void 0 : options.debug) !== null && _ref4 !== void 0 ? _ref4 : false;
935
936
  var adVideoElement;
936
937
  var adHls;
937
938
  var adContainerEl;
@@ -1002,14 +1003,26 @@ function createVastAdLayer(contentVideo, options) {
1002
1003
  var _ref;
1003
1004
  var _scoredFiles_;
1004
1005
  if (mediaFiles.length === 0) throw new Error("No media files available");
1005
- var firstFile = mediaFiles[0];
1006
- if (mediaFiles.length === 1) return firstFile;
1006
+ var candidates = mediaFiles;
1007
+ if (forceMP4Ads) {
1008
+ var mp4Only = candidates.filter(function(f) {
1009
+ return !isHlsMediaFile(f);
1010
+ });
1011
+ if (mp4Only.length > 0) {
1012
+ candidates = mp4Only;
1013
+ if (debug) console.log("".concat(LOG, " forceMP4Ads: filtered to ").concat(mp4Only.length, " MP4-only file(s)"));
1014
+ } else if (debug) {
1015
+ console.warn("".concat(LOG, " forceMP4Ads: no MP4 files available, falling back to all media files"));
1016
+ }
1017
+ }
1018
+ var firstFile = candidates[0];
1019
+ if (candidates.length === 1) return firstFile;
1007
1020
  var mainQuality = getMainStreamQuality();
1008
1021
  if (!mainQuality) {
1009
1022
  if (debug) console.log("".concat(LOG, " No main stream quality info, using first media file"));
1010
1023
  return firstFile;
1011
1024
  }
1012
- var scoredFiles = mediaFiles.map(function(file) {
1025
+ var scoredFiles = candidates.map(function(file) {
1013
1026
  var widthDiff = Math.abs(file.width - mainQuality.width);
1014
1027
  var heightDiff = Math.abs(file.height - mainQuality.height);
1015
1028
  var resolutionDiff = widthDiff + heightDiff;
@@ -1226,6 +1239,16 @@ function createVastAdLayer(contentVideo, options) {
1226
1239
  }
1227
1240
  function startPlayback(mediaFile) {
1228
1241
  if (!adVideoElement) return;
1242
+ if (singleElementMode && isHlsMediaFile(mediaFile)) {
1243
+ var mp4Fallback = currentAd === null || currentAd === void 0 ? void 0 : currentAd.mediaFiles.find(function(f) {
1244
+ return !isHlsMediaFile(f);
1245
+ });
1246
+ if (mp4Fallback) {
1247
+ if (debug) console.log("".concat(LOG, " singleElementMode: HLS ad blocked, using MP4 fallback"));
1248
+ startNativePlayback(mp4Fallback);
1249
+ return;
1250
+ }
1251
+ }
1229
1252
  if (isHlsMediaFile(mediaFile)) {
1230
1253
  startHlsPlayback(mediaFile);
1231
1254
  } else {
@@ -2896,10 +2919,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2896
2919
  debug: !!config.debugAdTiming
2897
2920
  } : {});
2898
2921
  var browserForAdLayer = detectBrowser();
2922
+ var isSinglePipeline = browserForAdLayer.isSmartTV || !!this.config.singlePipelineMode;
2899
2923
  this.adLayer = createVastAdLayer(this.video, {
2900
2924
  continueLiveStreamDuringAds: false,
2901
- smartTVMode: browserForAdLayer.isSmartTV,
2902
- singleElementMode: browserForAdLayer.isSmartTV,
2925
+ smartTVMode: isSinglePipeline,
2926
+ singleElementMode: isSinglePipeline,
2927
+ forceMP4Ads: isSinglePipeline,
2903
2928
  debug: !!config.debugAdTiming
2904
2929
  });
2905
2930
  }
@@ -3545,6 +3570,16 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
3545
3570
  if (_this.fillerVideo) {
3546
3571
  _this.fillerVideo.style.display = "none";
3547
3572
  }
3573
+ if (!_this.adLayer.isAdPlaying()) {
3574
+ if (_this.config.debugAdTiming) {
3575
+ console.log("[StormcloudVideoPlayer] Filler video failed \u2014 restoring main video");
3576
+ }
3577
+ _this.adLayer.hidePlaceholder();
3578
+ if (_this.video.paused && _this.video.readyState >= 2) {
3579
+ var _this_video_play;
3580
+ (_this_video_play = _this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
3581
+ }
3582
+ }
3548
3583
  });
3549
3584
  if (this.config.debugAdTiming) {
3550
3585
  console.log("[StormcloudVideoPlayer] Showing filler video layer");
@@ -4261,6 +4296,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4261
4296
  if (!this.isLiveStream) {
4262
4297
  return false;
4263
4298
  }
4299
+ if (this.config.singlePipelineMode) {
4300
+ return false;
4301
+ }
4264
4302
  var browser = detectBrowser();
4265
4303
  if (browser.isSmartTV) {
4266
4304
  return false;
@@ -5411,32 +5449,56 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5411
5449
  this.video.volume = restoredVolume;
5412
5450
  }
5413
5451
  var browser = detectBrowser();
5414
- var isSmartTV = browser.tizenVersion !== void 0 || browser.webOSVersion !== void 0;
5452
+ var isSmartTV = browser.tizenVersion !== void 0 || browser.webOSVersion !== void 0 || !!this.config.singlePipelineMode;
5415
5453
  if (isSmartTV && this.hls) {
5416
5454
  var hlsRef = this.hls;
5417
5455
  var savedMuted = restoredMuted;
5418
5456
  var savedVolume = restoredVolume;
5457
+ var videoRef = this.video;
5458
+ var debugEnabled = this.config.debugAdTiming;
5459
+ var tryPlay = function tryPlay1(attempt) {
5460
+ var _videoRef_play;
5461
+ if (_this.inAdBreak || _this.adLayer.isAdPlaying()) return;
5462
+ (_videoRef_play = videoRef.play()) === null || _videoRef_play === void 0 ? void 0 : _videoRef_play.catch(function() {
5463
+ if (attempt < 3) {
5464
+ if (debugEnabled) {
5465
+ console.log("[StormcloudVideoPlayer] Smart TV: play() retry ".concat(attempt + 1, "/3 in ").concat(500 * (attempt + 1), "ms"));
5466
+ }
5467
+ setTimeout(function() {
5468
+ return tryPlay(attempt + 1);
5469
+ }, 500 * (attempt + 1));
5470
+ }
5471
+ });
5472
+ };
5419
5473
  var onManifestParsedRestore = function onManifestParsedRestore1() {
5420
5474
  hlsRef.off(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5421
5475
  if (!_this.inAdBreak && !_this.adLayer.isAdPlaying()) {
5422
- var _this_video_play;
5423
- if (_this.video.muted !== savedMuted) _this.video.muted = savedMuted;
5424
- if (Math.abs(_this.video.volume - savedVolume) > 0.01) _this.video.volume = savedVolume;
5425
- if (_this.config.debugAdTiming) {
5476
+ if (videoRef.muted !== savedMuted) videoRef.muted = savedMuted;
5477
+ if (Math.abs(videoRef.volume - savedVolume) > 0.01) videoRef.volume = savedVolume;
5478
+ if (debugEnabled) {
5426
5479
  console.log("[StormcloudVideoPlayer] Smart TV: audio state restored on MANIFEST_PARSED after re-attach");
5427
5480
  }
5428
5481
  hlsRef.startLoad(-1);
5429
- (_this_video_play = _this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
5430
- if (_this.config.debugAdTiming) {
5482
+ tryPlay(0);
5483
+ if (debugEnabled) {
5431
5484
  console.log("[StormcloudVideoPlayer] Smart TV: seeking to live edge and resuming playback after re-attach");
5432
5485
  }
5433
5486
  }
5434
5487
  };
5435
5488
  hlsRef.on(import_hls2.default.Events.MANIFEST_PARSED, onManifestParsedRestore);
5436
- this.hls.attachMedia(this.video);
5437
- if (this.config.debugAdTiming) {
5438
- console.log("[StormcloudVideoPlayer] Smart TV: re-attached HLS to video element after ad break to restore media pipeline");
5489
+ var pipelineDelayMs = 300;
5490
+ if (debugEnabled) {
5491
+ console.log("[StormcloudVideoPlayer] Smart TV: waiting ".concat(pipelineDelayMs, "ms for hardware pipeline release before re-attach"));
5439
5492
  }
5493
+ setTimeout(function() {
5494
+ if (_this.inAdBreak || _this.adLayer.isAdPlaying()) return;
5495
+ if (_this.hls) {
5496
+ _this.hls.attachMedia(_this.video);
5497
+ if (debugEnabled) {
5498
+ console.log("[StormcloudVideoPlayer] Smart TV: re-attached HLS to video element after ad break to restore media pipeline");
5499
+ }
5500
+ }
5501
+ }, pipelineDelayMs);
5440
5502
  } else {
5441
5503
  if (this.shouldContinueLiveStreamDuringAds()) {
5442
5504
  var _this_video_play;
@@ -5510,6 +5572,15 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5510
5572
  }
5511
5573
  this.showPlaceholderLayer();
5512
5574
  this.adLayer.showPlaceholder();
5575
+ } else if (this.inAdBreak) {
5576
+ if (this.config.debugAdTiming) {
5577
+ console.log("[CONTINUOUS-FETCH] Ad failure with no filler \u2014 restoring main video temporarily");
5578
+ }
5579
+ this.adLayer.hidePlaceholder();
5580
+ if (!this.adLayer.isAdPlaying() && this.video.paused && this.video.readyState >= 2) {
5581
+ var _this_video_play;
5582
+ (_this_video_play = this.video.play()) === null || _this_video_play === void 0 ? void 0 : _this_video_play.catch(function() {});
5583
+ }
5513
5584
  }
5514
5585
  }
5515
5586
  },