stormcloud-video-player 0.2.15 → 0.2.17

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.
@@ -326,6 +326,14 @@ function createImaController(video, options) {
326
326
  function makeAdsRequest(google, vastTagUrl) {
327
327
  const adsRequest = new google.ima.AdsRequest();
328
328
  adsRequest.adTagUrl = vastTagUrl;
329
+ const videoWidth = video.offsetWidth || video.clientWidth || 640;
330
+ const videoHeight = video.offsetHeight || video.clientHeight || 360;
331
+ adsRequest.linearAdSlotWidth = videoWidth;
332
+ adsRequest.linearAdSlotHeight = videoHeight;
333
+ adsRequest.nonLinearAdSlotWidth = videoWidth;
334
+ adsRequest.nonLinearAdSlotHeight = videoHeight;
335
+ adsRequest.vastLoadTimeout = 5e3;
336
+ console.log(`[IMA] Ads request dimensions: ${videoWidth}x${videoHeight}`);
329
337
  adsLoader.requestAds(adsRequest);
330
338
  }
331
339
  function destroyAdsManager() {
@@ -372,6 +380,18 @@ function createImaController(video, options) {
372
380
  },
373
381
  async requestAds(vastTagUrl) {
374
382
  console.log("[IMA] Requesting ads:", vastTagUrl);
383
+ if (!vastTagUrl || vastTagUrl.trim() === "") {
384
+ const error = new Error("VAST tag URL is empty or undefined");
385
+ console.warn("[IMA]", error.message);
386
+ return Promise.reject(error);
387
+ }
388
+ try {
389
+ new URL(vastTagUrl);
390
+ } catch (e) {
391
+ const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);
392
+ console.warn("[IMA]", error.message);
393
+ return Promise.reject(error);
394
+ }
375
395
  if (adPlaying) {
376
396
  console.warn(
377
397
  "[IMA] Cannot request new ads while an ad is playing. Call stop() first."
@@ -433,6 +453,18 @@ function createImaController(video, options) {
433
453
  );
434
454
  }
435
455
  }
456
+ const videoWidth = video.offsetWidth || video.clientWidth;
457
+ const videoHeight = video.offsetHeight || video.clientHeight;
458
+ if (!videoWidth || !videoHeight || videoWidth === 0 || videoHeight === 0) {
459
+ const error = new Error(
460
+ `Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`
461
+ );
462
+ console.warn("[IMA]", error.message);
463
+ currentReject == null ? void 0 : currentReject(error);
464
+ adsLoadedReject = void 0;
465
+ adsLoadedResolve = void 0;
466
+ return Promise.reject(error);
467
+ }
436
468
  if (!adsLoader) {
437
469
  console.log("[IMA] Creating ads loader");
438
470
  const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);
@@ -481,7 +513,9 @@ function createImaController(video, options) {
481
513
  emit("ad_error");
482
514
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
483
515
  if (video.paused) {
484
- console.log("[IMA] Resuming paused video after ad error");
516
+ console.log(
517
+ "[IMA] Resuming paused video after ad error"
518
+ );
485
519
  (_a = video.play()) == null ? void 0 : _a.catch(() => {
486
520
  });
487
521
  }
@@ -583,7 +617,9 @@ function createImaController(video, options) {
583
617
  }
584
618
  if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
585
619
  if (video.paused) {
586
- console.log("[IMA] Resuming paused video after setup error");
620
+ console.log(
621
+ "[IMA] Resuming paused video after setup error"
622
+ );
587
623
  video.play().catch(() => {
588
624
  });
589
625
  }
@@ -1778,6 +1814,8 @@ var StormcloudVideoPlayer = class {
1778
1814
  this.totalAdsInBreak = 0;
1779
1815
  this.showAds = false;
1780
1816
  this.isLiveStream = false;
1817
+ this.nativeHlsMode = false;
1818
+ this.videoSrcProtection = null;
1781
1819
  initializePolyfills();
1782
1820
  const browserOverrides = getBrowserConfigOverrides();
1783
1821
  this.config = { ...config, ...browserOverrides };
@@ -1798,7 +1836,9 @@ var StormcloudVideoPlayer = class {
1798
1836
  }
1799
1837
  if (adPlayerType === "hls") {
1800
1838
  if (this.config.debugAdTiming) {
1801
- console.log("[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)");
1839
+ console.log(
1840
+ "[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)"
1841
+ );
1802
1842
  }
1803
1843
  return createHlsAdPlayer(this.video, {
1804
1844
  continueLiveStreamDuringAds,
@@ -1807,7 +1847,9 @@ var StormcloudVideoPlayer = class {
1807
1847
  });
1808
1848
  } else {
1809
1849
  if (this.config.debugAdTiming) {
1810
- console.log("[StormcloudVideoPlayer] Creating Google IMA ad player (Default mode)");
1850
+ console.log(
1851
+ "[StormcloudVideoPlayer] Creating Google IMA ad player (Default mode)"
1852
+ );
1811
1853
  }
1812
1854
  return createImaController(this.video, {
1813
1855
  continueLiveStreamDuringAds
@@ -1831,11 +1873,13 @@ var StormcloudVideoPlayer = class {
1831
1873
  }
1832
1874
  this.initializeTracking();
1833
1875
  if (this.shouldUseNativeHls()) {
1876
+ this.nativeHlsMode = true;
1877
+ this.videoSrcProtection = this.config.src;
1834
1878
  this.video.src = this.config.src;
1835
1879
  this.isLiveStream = (_a = this.config.lowLatencyMode) != null ? _a : false;
1836
1880
  if (this.config.debugAdTiming) {
1837
1881
  console.log(
1838
- "[StormcloudVideoPlayer] allowNativeHls: true - VOD mode detected:",
1882
+ "[StormcloudVideoPlayer] Using native HLS playback - VOD mode:",
1839
1883
  {
1840
1884
  isLive: this.isLiveStream,
1841
1885
  allowNativeHls: this.config.allowNativeHls,
@@ -1983,7 +2027,9 @@ var StormcloudVideoPlayer = class {
1983
2027
  this.ima.initialize();
1984
2028
  this.ima.on("all_ads_completed", () => {
1985
2029
  if (this.config.debugAdTiming) {
1986
- console.log("[StormcloudVideoPlayer] IMA all_ads_completed event received");
2030
+ console.log(
2031
+ "[StormcloudVideoPlayer] IMA all_ads_completed event received"
2032
+ );
1987
2033
  }
1988
2034
  });
1989
2035
  this.ima.on("ad_error", () => {
@@ -2048,13 +2094,31 @@ var StormcloudVideoPlayer = class {
2048
2094
  this.video.addEventListener("timeupdate", () => {
2049
2095
  this.onTimeUpdate(this.video.currentTime);
2050
2096
  });
2097
+ this.video.addEventListener("emptied", () => {
2098
+ if (this.nativeHlsMode && this.videoSrcProtection && !this.ima.isAdPlaying()) {
2099
+ if (this.config.debugAdTiming) {
2100
+ console.log(
2101
+ "[StormcloudVideoPlayer] Video src was cleared, restoring:",
2102
+ this.videoSrcProtection
2103
+ );
2104
+ }
2105
+ const currentTime = this.video.currentTime;
2106
+ const wasPaused = this.video.paused;
2107
+ this.video.src = this.videoSrcProtection;
2108
+ this.video.currentTime = currentTime;
2109
+ if (!wasPaused) {
2110
+ this.video.play().catch(() => {
2111
+ });
2112
+ }
2113
+ }
2114
+ });
2051
2115
  }
2052
2116
  shouldUseNativeHls() {
2053
2117
  const streamType = this.getStreamType();
2054
2118
  if (streamType === "other") {
2055
2119
  return true;
2056
2120
  }
2057
- const canNative = this.video.canPlayType("application/vnd.apple.mpegURL");
2121
+ const canNative = this.video.canPlayType("application/vnd.apple.mpegurl");
2058
2122
  return !!(this.config.allowNativeHls && canNative);
2059
2123
  }
2060
2124
  onId3Tag(tag) {
@@ -2481,10 +2545,7 @@ var StormcloudVideoPlayer = class {
2481
2545
  var _a, _b, _c;
2482
2546
  const vastMode = this.config.vastMode || "default";
2483
2547
  if (this.config.debugAdTiming) {
2484
- console.log(
2485
- "[StormcloudVideoPlayer] VAST mode:",
2486
- vastMode
2487
- );
2548
+ console.log("[StormcloudVideoPlayer] VAST mode:", vastMode);
2488
2549
  }
2489
2550
  if (vastMode === "adstorm") {
2490
2551
  if (!this.config.licenseKey) {
@@ -2602,10 +2663,7 @@ var StormcloudVideoPlayer = class {
2602
2663
  this.currentAdIndex = 0;
2603
2664
  this.totalAdsInBreak = 1;
2604
2665
  if (this.config.debugAdTiming) {
2605
- console.log(
2606
- "[StormcloudVideoPlayer] Using VAST endpoint:",
2607
- vastTagUrl
2608
- );
2666
+ console.log("[StormcloudVideoPlayer] Using VAST endpoint:", vastTagUrl);
2609
2667
  }
2610
2668
  } else if (tags && tags.length > 0) {
2611
2669
  vastTagUrl = tags[0];
@@ -2757,15 +2815,21 @@ var StormcloudVideoPlayer = class {
2757
2815
  await this.ima.requestAds(vastTagUrl);
2758
2816
  try {
2759
2817
  if (this.config.debugAdTiming) {
2760
- console.log("[StormcloudVideoPlayer] Ad request completed, attempting playback");
2818
+ console.log(
2819
+ "[StormcloudVideoPlayer] Ad request completed, attempting playback"
2820
+ );
2761
2821
  }
2762
2822
  await this.ima.play();
2763
2823
  if (this.config.debugAdTiming) {
2764
- console.log("[StormcloudVideoPlayer] Ad playback started successfully");
2824
+ console.log(
2825
+ "[StormcloudVideoPlayer] Ad playback started successfully"
2826
+ );
2765
2827
  }
2766
2828
  } catch (playError) {
2767
2829
  if (this.config.debugAdTiming) {
2768
- console.log("[StormcloudVideoPlayer] No ads available, skipping playback");
2830
+ console.log(
2831
+ "[StormcloudVideoPlayer] No ads available, skipping playback"
2832
+ );
2769
2833
  }
2770
2834
  this.handleAdFailure();
2771
2835
  return;
@@ -2821,7 +2885,9 @@ var StormcloudVideoPlayer = class {
2821
2885
  });
2822
2886
  } else {
2823
2887
  if (this.config.debugAdTiming) {
2824
- console.log("[StormcloudVideoPlayer] Video is already playing, no resume needed");
2888
+ console.log(
2889
+ "[StormcloudVideoPlayer] Video is already playing, no resume needed"
2890
+ );
2825
2891
  }
2826
2892
  }
2827
2893
  }
@@ -2840,7 +2906,11 @@ var StormcloudVideoPlayer = class {
2840
2906
  if (this.config.debugAdTiming) {
2841
2907
  console.warn(
2842
2908
  "[StormcloudVideoPlayer] Failsafe timer triggered - forcing video resume",
2843
- { paused: this.video.paused, showAds: this.showAds, adPlaying: this.ima.isAdPlaying() }
2909
+ {
2910
+ paused: this.video.paused,
2911
+ showAds: this.showAds,
2912
+ adPlaying: this.ima.isAdPlaying()
2913
+ }
2844
2914
  );
2845
2915
  }
2846
2916
  this.handleAdFailure();
@@ -3033,10 +3103,20 @@ var HlsPlayer = class extends import_react2.Component {
3033
3103
  }
3034
3104
  };
3035
3105
  this.play = () => {
3036
- var _a, _b;
3106
+ var _a, _b, _c;
3037
3107
  if (this.props.videoElement) {
3038
- this.props.videoElement.play();
3039
- (_b = (_a = this.props).onPlay) == null ? void 0 : _b.call(_a);
3108
+ const video = this.props.videoElement;
3109
+ const hasValidSource = video.src || video.currentSrc && video.currentSrc !== "" || video.readyState >= 1;
3110
+ if (hasValidSource) {
3111
+ (_a = video.play()) == null ? void 0 : _a.catch((error) => {
3112
+ var _a2, _b2;
3113
+ console.error("[HlsPlayer] Failed to play:", error);
3114
+ (_b2 = (_a2 = this.props).onError) == null ? void 0 : _b2.call(_a2, error);
3115
+ });
3116
+ (_c = (_b = this.props).onPlay) == null ? void 0 : _c.call(_b);
3117
+ } else {
3118
+ console.warn("[HlsPlayer] Cannot play: video has no valid source");
3119
+ }
3040
3120
  }
3041
3121
  };
3042
3122
  this.pause = () => {
@@ -3205,8 +3285,19 @@ var FilePlayer = class extends import_react3.Component {
3205
3285
  };
3206
3286
  };
3207
3287
  this.play = () => {
3288
+ var _a;
3208
3289
  if (this.props.videoElement) {
3209
- this.props.videoElement.play();
3290
+ const video = this.props.videoElement;
3291
+ const hasValidSource = video.src || video.currentSrc && video.currentSrc !== "" || video.readyState >= 1;
3292
+ if (hasValidSource) {
3293
+ (_a = video.play()) == null ? void 0 : _a.catch((error) => {
3294
+ var _a2, _b;
3295
+ console.error("[FilePlayer] Failed to play:", error);
3296
+ (_b = (_a2 = this.props).onError) == null ? void 0 : _b.call(_a2, error);
3297
+ });
3298
+ } else {
3299
+ console.warn("[FilePlayer] Cannot play: video has no valid source");
3300
+ }
3210
3301
  }
3211
3302
  };
3212
3303
  this.pause = () => {