stormcloud-video-player 0.5.26 → 0.5.27

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.js CHANGED
@@ -4313,7 +4313,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4313
4313
  case 0:
4314
4314
  _this = this;
4315
4315
  durSec = (_marker_durationSeconds = marker.durationSeconds) !== null && _marker_durationSeconds !== void 0 ? _marker_durationSeconds : 60;
4316
- estimatedCount = Math.min(4, Math.max(1, Math.ceil(durSec / 30)));
4316
+ estimatedCount = Math.min(4, Math.max(1, Math.ceil(durSec / 20)));
4317
4317
  if (this.config.debugAdTiming) {
4318
4318
  console.log("[PREFETCH] Firing ".concat(estimatedCount, " parallel bid request(s) for ").concat(durSec, "s break"));
4319
4319
  }
@@ -4485,6 +4485,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4485
4485
  if (bids.length > 0) {
4486
4486
  _this.consecutiveFailures = 0;
4487
4487
  _this.pendingNextAdBids = bids;
4488
+ _this.totalAdsInBreak = Math.max(_this.totalAdsInBreak, _this.currentAdIndex + _this.preloadedTokens.length + 1);
4488
4489
  if (_this.config.debugAdTiming) {
4489
4490
  console.log("[CONTINUOUS-FETCH] Pre-fetched next ad stored as pending");
4490
4491
  }
@@ -4624,6 +4625,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4624
4625
  17
4625
4626
  ];
4626
4627
  _this.pendingNextAdBids = bids2;
4628
+ _this.totalAdsInBreak = Math.max(_this.totalAdsInBreak, _this.currentAdIndex + _this.preloadedTokens.length + 1);
4627
4629
  if (_this.config.debugAdTiming) {
4628
4630
  console.log("[CONTINUOUS-FETCH] Next ad response stored (ad currently playing or in transition)");
4629
4631
  }
@@ -4777,7 +4779,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4777
4779
  this.inAdBreak = true;
4778
4780
  this.currentAdBreakStartWallClockMs = Date.now();
4779
4781
  this.currentAdIndex = 0;
4780
- this.totalAdsInBreak = 1;
4782
+ this.totalAdsInBreak = Math.max(1, this.preloadedTokens.length);
4781
4783
  this.adPodQueue = [];
4782
4784
  if (!this.config.disableFiller) this.showAds = true;
4783
4785
  if (adBreakDurationMs != null) {
@@ -5002,6 +5004,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5002
5004
  3
5003
5005
  ];
5004
5006
  this.pendingNextAdBids = bids;
5007
+ this.totalAdsInBreak = Math.max(this.totalAdsInBreak, this.currentAdIndex + this.preloadedTokens.length);
5005
5008
  return [
5006
5009
  3,
5007
5010
  5
@@ -5782,7 +5785,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5782
5785
  return StormcloudVideoPlayer;
5783
5786
  }();
5784
5787
  // src/ui/StormcloudVideoPlayer.tsx
5785
- import { FaPlay, FaPause, FaVolumeUp, FaVolumeMute, FaVolumeDown, FaExpand, FaCompress, FaSpinner } from "react-icons/fa";
5788
+ import { FaPlay, FaPause, FaVolumeUp, FaVolumeMute, FaVolumeDown, FaExpand, FaCompress } from "react-icons/fa";
5786
5789
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5787
5790
  var CRITICAL_PROPS = [
5788
5791
  "src",
@@ -5792,6 +5795,7 @@ var CRITICAL_PROPS = [
5792
5795
  "driftToleranceMs"
5793
5796
  ];
5794
5797
  var CONTROLS_HIDE_DELAY = 3e3;
5798
+ var DEFAULT_PLAYER_ASPECT_RATIO = 16 / 9;
5795
5799
  var StormcloudVideoPlayerComponent = React.memo(function(props) {
5796
5800
  var src = props.src, autoplay = props.autoplay, muted = props.muted, lowLatencyMode = props.lowLatencyMode, allowNativeHls = props.allowNativeHls, driftToleranceMs = props.driftToleranceMs, immediateManifestAds = props.immediateManifestAds, debugAdTiming = props.debugAdTiming, showCustomControls = props.showCustomControls, hideLoadingIndicator = props.hideLoadingIndicator, onVolumeToggle = props.onVolumeToggle, onFullscreenToggle = props.onFullscreenToggle, onControlClick = props.onControlClick, onReady = props.onReady, wrapperClassName = props.wrapperClassName, wrapperStyle = props.wrapperStyle, className = props.className, style = props.style, controls = props.controls, playsInline = props.playsInline, preload = props.preload, poster = props.poster, children = props.children, licenseKey = props.licenseKey, minSegmentsBeforePlay = props.minSegmentsBeforePlay, disablePrebid = props.disablePrebid, disableFiller = props.disableFiller, restVideoAttrs = _object_without_properties(props, [
5797
5801
  "src",
@@ -5849,6 +5853,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
5849
5853
  var _React_useState15 = _sliced_to_array(React.useState(true), 2), controlsVisible = _React_useState15[0], setControlsVisible = _React_useState15[1];
5850
5854
  var _React_useState16 = _sliced_to_array(React.useState(typeof window !== "undefined" ? window.innerWidth : 1920), 2), viewportWidth = _React_useState16[0], setViewportWidth = _React_useState16[1];
5851
5855
  var _React_useState17 = _sliced_to_array(React.useState(typeof window !== "undefined" ? window.innerHeight > window.innerWidth : false), 2), isPortrait = _React_useState17[0], setIsPortrait = _React_useState17[1];
5856
+ var _React_useState18 = _sliced_to_array(React.useState(DEFAULT_PLAYER_ASPECT_RATIO), 2), playerAspectRatio = _React_useState18[0], setPlayerAspectRatio = _React_useState18[1];
5852
5857
  var getResponsiveScale = function getResponsiveScale() {
5853
5858
  if (viewportWidth < 480) return 0.7;
5854
5859
  if (viewportWidth < 768) return 0.8;
@@ -6090,6 +6095,13 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6090
6095
  }, []);
6091
6096
  useEffect(function() {
6092
6097
  if (!videoRef.current) return;
6098
+ var handleLoadedMetadata = function handleLoadedMetadata() {
6099
+ var video2 = videoRef.current;
6100
+ if (!video2) return;
6101
+ if (video2.videoWidth > 0 && video2.videoHeight > 0) {
6102
+ setPlayerAspectRatio(video2.videoWidth / video2.videoHeight);
6103
+ }
6104
+ };
6093
6105
  var handleCanPlay = function handleCanPlay() {
6094
6106
  setIsLoading(false);
6095
6107
  if (bufferingTimeoutRef.current) {
@@ -6136,6 +6148,8 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6136
6148
  setShowCenterPlay(true);
6137
6149
  };
6138
6150
  var video = videoRef.current;
6151
+ handleLoadedMetadata();
6152
+ video.addEventListener("loadedmetadata", handleLoadedMetadata);
6139
6153
  video.addEventListener("canplay", handleCanPlay);
6140
6154
  video.addEventListener("canplaythrough", handleCanPlayThrough);
6141
6155
  video.addEventListener("waiting", handleWaiting);
@@ -6150,6 +6164,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6150
6164
  clearTimeout(bufferingTimeoutRef.current);
6151
6165
  bufferingTimeoutRef.current = null;
6152
6166
  }
6167
+ video.removeEventListener("loadedmetadata", handleLoadedMetadata);
6153
6168
  video.removeEventListener("canplay", handleCanPlay);
6154
6169
  video.removeEventListener("canplaythrough", handleCanPlayThrough);
6155
6170
  video.removeEventListener("waiting", handleWaiting);
@@ -6160,6 +6175,11 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6160
6175
  }, [
6161
6176
  debugAdTiming
6162
6177
  ]);
6178
+ useEffect(function() {
6179
+ setPlayerAspectRatio(DEFAULT_PLAYER_ASPECT_RATIO);
6180
+ }, [
6181
+ src
6182
+ ]);
6163
6183
  useEffect(function() {
6164
6184
  return function() {
6165
6185
  if (controlsTimerRef.current) {
@@ -6185,7 +6205,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6185
6205
  return /* @__PURE__ */ jsxs(Fragment, {
6186
6206
  children: [
6187
6207
  /* @__PURE__ */ jsx("style", {
6188
- children: "\n @keyframes sc-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n @keyframes sc-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.6; }\n }\n @keyframes sc-fade-in {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n .sc-wrapper:fullscreen,\n .sc-wrapper:has(*:fullscreen) {\n border-radius: 0 !important;\n box-shadow: none !important;\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n .sc-ctrl-btn {\n background: none;\n border: none;\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n padding: 8px;\n transition: background 0.15s ease, opacity 0.15s ease;\n opacity: 0.9;\n }\n .sc-ctrl-btn:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n .sc-ctrl-btn:active {\n opacity: 0.7;\n }\n .sc-controls-bar {\n transition: opacity 0.35s ease, transform 0.35s ease;\n }\n .sc-progress-track:hover .sc-progress-thumb {\n transform: translate(-50%, -50%) scale(1) !important;\n }\n .sc-loading-hidden .sc-loading-indicator {\n display: none !important;\n }\n "
6208
+ children: "\n @keyframes sc-spin {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n }\n @keyframes sc-loading-glow {\n 0%, 100% { opacity: 0.85; transform: scale(1); }\n 50% { opacity: 1; transform: scale(1.05); }\n }\n @keyframes sc-pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.6; }\n }\n @keyframes sc-fade-in {\n from { opacity: 0; transform: translateY(8px); }\n to { opacity: 1; transform: translateY(0); }\n }\n .sc-wrapper:fullscreen,\n .sc-wrapper:has(*:fullscreen) {\n border-radius: 0 !important;\n box-shadow: none !important;\n width: 100vw !important;\n height: 100vh !important;\n max-width: 100vw !important;\n max-height: 100vh !important;\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n z-index: 999999 !important;\n background: #000 !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n .sc-ctrl-btn {\n background: none;\n border: none;\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n padding: 8px;\n transition: background 0.15s ease, opacity 0.15s ease;\n opacity: 0.9;\n }\n .sc-ctrl-btn:hover {\n opacity: 1;\n background: rgba(255, 255, 255, 0.1);\n }\n .sc-ctrl-btn:active {\n opacity: 0.7;\n }\n .sc-controls-bar {\n transition: opacity 0.35s ease, transform 0.35s ease;\n }\n .sc-progress-track:hover .sc-progress-thumb {\n transform: translate(-50%, -50%) scale(1) !important;\n }\n .sc-loading-hidden .sc-loading-indicator {\n display: none !important;\n }\n "
6189
6209
  }),
6190
6210
  /* @__PURE__ */ jsxs("div", {
6191
6211
  ref: wrapperRef,
@@ -6203,6 +6223,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6203
6223
  width: isFullscreen ? "100vw" : "100%",
6204
6224
  height: isFullscreen ? "100vh" : "auto",
6205
6225
  minHeight: isFullscreen ? "100vh" : "auto",
6226
+ aspectRatio: isFullscreen ? void 0 : playerAspectRatio,
6206
6227
  maxWidth: isFullscreen ? "100vw" : "100%",
6207
6228
  maxHeight: isFullscreen ? "100vh" : "none",
6208
6229
  zIndex: isFullscreen ? 999999 : void 0,
@@ -6217,7 +6238,7 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6217
6238
  style: _object_spread({
6218
6239
  display: "block",
6219
6240
  width: "100%",
6220
- height: isFullscreen ? "100%" : "auto",
6241
+ height: "100%",
6221
6242
  maxWidth: "100%",
6222
6243
  maxHeight: isFullscreen ? "100%" : "none",
6223
6244
  objectFit: isFullscreen ? "cover" : "contain",
@@ -6231,18 +6252,44 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6231
6252
  }, restVideoAttrs), {
6232
6253
  children: children
6233
6254
  })),
6234
- (isLoading || isBuffering) && !hideLoadingIndicator && /* @__PURE__ */ jsx(FaSpinner, {
6255
+ (isLoading || isBuffering) && !hideLoadingIndicator && /* @__PURE__ */ jsxs("div", {
6235
6256
  className: "sc-loading-indicator",
6236
- size: 40,
6237
- color: "rgba(255, 255, 255, 0.85)",
6238
6257
  style: {
6239
6258
  position: "absolute",
6240
- top: "calc(50% - 20px)",
6241
- left: "calc(50% - 20px)",
6259
+ top: "50%",
6260
+ left: "50%",
6261
+ transform: "translate(-50%, -50%)",
6242
6262
  zIndex: 20,
6243
- animation: "sc-spin 0.9s linear infinite",
6244
- filter: "drop-shadow(0 2px 8px rgba(0, 0, 0, 0.6))"
6245
- }
6263
+ width: "".concat(Math.max(34, 38 * responsiveScale), "px"),
6264
+ height: "".concat(Math.max(34, 38 * responsiveScale), "px"),
6265
+ display: "flex",
6266
+ alignItems: "center",
6267
+ justifyContent: "center",
6268
+ animation: "sc-loading-glow 1.4s ease-in-out infinite",
6269
+ filter: "drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55))"
6270
+ },
6271
+ children: [
6272
+ /* @__PURE__ */ jsx("div", {
6273
+ style: {
6274
+ position: "absolute",
6275
+ inset: 0,
6276
+ borderRadius: "50%",
6277
+ border: "3px solid rgba(255, 255, 255, 0.25)",
6278
+ borderTopColor: "#ff0000",
6279
+ borderRightColor: "rgba(255, 255, 255, 0.85)",
6280
+ animation: "sc-spin 0.8s linear infinite"
6281
+ }
6282
+ }),
6283
+ /* @__PURE__ */ jsx("div", {
6284
+ style: {
6285
+ width: "7px",
6286
+ height: "7px",
6287
+ borderRadius: "50%",
6288
+ background: "#ff0000",
6289
+ boxShadow: "0 0 10px rgba(255, 0, 0, 0.65)"
6290
+ }
6291
+ })
6292
+ ]
6246
6293
  }),
6247
6294
  showLicenseWarning && /* @__PURE__ */ jsxs("div", {
6248
6295
  style: {
@@ -6478,7 +6525,8 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6478
6525
  /* @__PURE__ */ jsxs("div", {
6479
6526
  style: {
6480
6527
  display: "flex",
6481
- alignItems: "center"
6528
+ alignItems: "center",
6529
+ paddingRight: "".concat(6 * responsiveScale, "px")
6482
6530
  },
6483
6531
  onMouseEnter: function onMouseEnter() {
6484
6532
  return setShowVolumeSlider(true);
@@ -6509,13 +6557,13 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6509
6557
  }),
6510
6558
  /* @__PURE__ */ jsx("div", {
6511
6559
  style: {
6512
- width: showVolumeSlider ? "".concat(62 * responsiveScale, "px") : "0px",
6560
+ width: showVolumeSlider ? "".concat(68 * responsiveScale, "px") : "0px",
6513
6561
  overflow: "hidden",
6514
6562
  transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
6515
6563
  display: "flex",
6516
6564
  alignItems: "center",
6517
- paddingLeft: showVolumeSlider ? "2px" : "0",
6518
- paddingRight: showVolumeSlider ? "4px" : "0"
6565
+ paddingLeft: showVolumeSlider ? "".concat(3 * responsiveScale, "px") : "0",
6566
+ paddingRight: showVolumeSlider ? "".concat(8 * responsiveScale, "px") : "0"
6519
6567
  },
6520
6568
  children: /* @__PURE__ */ jsxs("div", {
6521
6569
  style: {
@@ -6762,7 +6810,8 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6762
6810
  alignItems: "center",
6763
6811
  background: "rgba(0, 0, 0, 0.6)",
6764
6812
  borderRadius: "".concat(18 * responsiveScale, "px"),
6765
- padding: "2px"
6813
+ padding: "2px",
6814
+ paddingRight: "".concat(8 * responsiveScale, "px")
6766
6815
  },
6767
6816
  onMouseEnter: function onMouseEnter() {
6768
6817
  return setShowVolumeSlider(true);
@@ -6791,13 +6840,13 @@ var StormcloudVideoPlayerComponent = React.memo(function(props) {
6791
6840
  }),
6792
6841
  /* @__PURE__ */ jsx("div", {
6793
6842
  style: {
6794
- width: showVolumeSlider ? "".concat(62 * responsiveScale, "px") : "0px",
6843
+ width: showVolumeSlider ? "".concat(68 * responsiveScale, "px") : "0px",
6795
6844
  overflow: "hidden",
6796
6845
  transition: "width 0.2s cubic-bezier(0.4, 0, 0.2, 1)",
6797
6846
  display: "flex",
6798
6847
  alignItems: "center",
6799
- paddingLeft: showVolumeSlider ? "2px" : "0",
6800
- paddingRight: showVolumeSlider ? "6px" : "0"
6848
+ paddingLeft: showVolumeSlider ? "".concat(3 * responsiveScale, "px") : "0",
6849
+ paddingRight: showVolumeSlider ? "".concat(10 * responsiveScale, "px") : "0"
6801
6850
  },
6802
6851
  children: /* @__PURE__ */ jsxs("div", {
6803
6852
  style: {