stormcloud-video-player 0.7.13 → 0.7.16
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/dist/stormcloud-vp.min.js +1 -1
- package/lib/index.cjs +371 -49
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +12 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.js +372 -50
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +38 -10
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +4 -0
- package/lib/players/FilePlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.cjs +38 -10
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +38 -10
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/adstormPlayer.cjs.map +1 -1
- package/lib/sdk/vastParser.cjs.map +1 -1
- package/lib/ui/OverlayRenderer.cjs +408 -37
- package/lib/ui/OverlayRenderer.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +371 -49
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/utils/browserCompat.cjs.map +1 -1
- package/lib/utils/overlays.d.cts +8 -0
- package/lib/utils/polyfills.cjs.map +1 -1
- package/lib/utils/tracking.cjs.map +1 -1
- package/package.json +1 -1
|
@@ -45,6 +45,7 @@ declare class StormcloudVideoPlayer {
|
|
|
45
45
|
private pendingAdBreak;
|
|
46
46
|
private prefetchTimerId;
|
|
47
47
|
private savedMutedStateBeforeAd;
|
|
48
|
+
private adLayerInitialized;
|
|
48
49
|
private consecutiveFailures;
|
|
49
50
|
private readonly maxConsecutiveFailures;
|
|
50
51
|
private lastAdRequestTime;
|
|
@@ -80,6 +81,8 @@ declare class StormcloudVideoPlayer {
|
|
|
80
81
|
getRemainingAdSeconds(): number;
|
|
81
82
|
isAdPlaying(): boolean;
|
|
82
83
|
isShowingAds(): boolean;
|
|
84
|
+
private initializeAdLayer;
|
|
85
|
+
setDisableAds(disabled: boolean): void;
|
|
83
86
|
private syncMainContentAudioWhenVisible;
|
|
84
87
|
getStreamType(): "hls" | "other";
|
|
85
88
|
shouldShowNativeControls(): boolean;
|
|
@@ -92,6 +95,7 @@ declare class StormcloudVideoPlayer {
|
|
|
92
95
|
private stopAdInsertionPolling;
|
|
93
96
|
private fetchAdInsertionPoint;
|
|
94
97
|
private checkAdInsertionInManifest;
|
|
98
|
+
private extractTsFilename;
|
|
95
99
|
private fragmentMatchesSegment;
|
|
96
100
|
private clearAdInsertionOffsetTimer;
|
|
97
101
|
private startContinuousFetchLoop;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/players/FilePlayer.cjs"],"names":[
|
|
1
|
+
{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/players/FilePlayer.cjs"],"names":[],"mappings":"AAAA","sourcesContent":["\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/players/FilePlayer.tsx\nvar FilePlayer_exports = {};\n__export(FilePlayer_exports, {\n default: () => FilePlayer\n});\nmodule.exports = __toCommonJS(FilePlayer_exports);\nvar import_react = require(\"react\");\n\n// src/patterns.ts\nvar HLS_EXTENSIONS = /\\.(m3u8)($|\\?)/i;\nvar HLS_PATHS = /\\/hls\\//i;\nvar DASH_EXTENSIONS = /\\.(mpd)($|\\?)/i;\nvar VIDEO_EXTENSIONS = /\\.(mp4|webm|ogg|avi|mov|wmv|flv|mkv)($|\\?)/i;\nvar AUDIO_EXTENSIONS = /\\.(mp3|wav|ogg|aac|wma|flac|m4a)($|\\?)/i;\nvar canPlay = {\n hls: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return HLS_EXTENSIONS.test(url) || HLS_PATHS.test(url);\n },\n dash: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return DASH_EXTENSIONS.test(url);\n },\n video: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url);\n },\n audio: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return AUDIO_EXTENSIONS.test(url);\n },\n file: (url) => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url) || AUDIO_EXTENSIONS.test(url);\n }\n};\n\n// src/players/FilePlayer.tsx\nvar FilePlayer = class extends import_react.Component {\n constructor() {\n super(...arguments);\n this.mounted = false;\n this.ready = false;\n this.load = () => {\n if (!this.props.videoElement || !this.props.src) return;\n const video = this.props.videoElement;\n const handleLoadedMetadata = () => {\n if (this.mounted && !this.ready) {\n this.ready = true;\n this.props.onReady?.();\n }\n };\n const handlePlay = () => {\n if (this.mounted) {\n this.props.onPlay?.();\n }\n };\n const handlePause = () => {\n if (this.mounted) {\n this.props.onPause?.();\n }\n };\n const handleEnded = () => {\n if (this.mounted) {\n this.props.onEnded?.();\n }\n };\n const handleError = (error) => {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n };\n const handleLoadedData = () => {\n if (this.mounted) {\n this.props.onLoaded?.();\n }\n };\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"play\", handlePlay);\n video.addEventListener(\"pause\", handlePause);\n video.addEventListener(\"ended\", handleEnded);\n video.addEventListener(\"error\", handleError);\n video.addEventListener(\"loadeddata\", handleLoadedData);\n video.src = this.props.src;\n if (this.props.autoplay !== void 0) video.autoplay = this.props.autoplay;\n if (this.props.muted !== void 0) video.muted = this.props.muted;\n if (this.props.loop !== void 0) video.loop = this.props.loop;\n if (this.props.controls !== void 0) video.controls = this.props.controls;\n if (this.props.playsInline !== void 0)\n video.playsInline = this.props.playsInline;\n if (this.props.preload !== void 0)\n video.preload = this.props.preload;\n if (this.props.poster !== void 0) video.poster = this.props.poster;\n this.props.onMount?.(this);\n return () => {\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"play\", handlePlay);\n video.removeEventListener(\"pause\", handlePause);\n video.removeEventListener(\"ended\", handleEnded);\n video.removeEventListener(\"error\", handleError);\n video.removeEventListener(\"loadeddata\", handleLoadedData);\n };\n };\n this.play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource = video.src || video.currentSrc && video.currentSrc !== \"\" || video.readyState >= 1;\n if (hasValidSource) {\n video.play()?.catch((error) => {\n console.error(\"[FilePlayer] Failed to play:\", error);\n this.props.onError?.(error);\n });\n } else {\n console.warn(\"[FilePlayer] Cannot play: video has no valid source\");\n }\n }\n };\n this.pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n }\n };\n this.stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n this.seekTo = (seconds, keepPlaying) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n this.setVolume = (volume) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n this.mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n this.unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n this.setPlaybackRate = (rate) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n this.setLoop = (loop) => {\n if (this.props.videoElement) {\n this.props.videoElement.loop = loop;\n }\n };\n this.getDuration = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n this.getCurrentTime = () => {\n if (this.props.videoElement && isFinite(this.props.videoElement.currentTime)) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n this.getSecondsLoaded = () => {\n if (this.props.videoElement && this.props.videoElement.buffered.length > 0) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n this.getInternalPlayer = (key = \"player\") => {\n if (key === \"video\") return this.props.videoElement;\n return null;\n };\n this.enablePIP = async () => {\n if (this.props.videoElement && \"requestPictureInPicture\" in this.props.videoElement) {\n try {\n await this.props.videoElement.requestPictureInPicture();\n } catch (error) {\n console.warn(\"Picture-in-Picture failed:\", error);\n }\n }\n };\n this.disablePIP = async () => {\n if (document.pictureInPictureElement) {\n try {\n await document.exitPictureInPicture();\n } catch (error) {\n console.warn(\"Exit Picture-in-Picture failed:\", error);\n }\n }\n };\n }\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n componentWillUnmount() {\n this.mounted = false;\n }\n componentDidUpdate(prevProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n render() {\n return null;\n }\n};\nFilePlayer.displayName = \"FilePlayer\";\nFilePlayer.canPlay = canPlay.file;\n"]}
|
|
@@ -2767,6 +2767,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
2767
2767
|
this.maxTotalAdRequestsPerBreak = 20;
|
|
2768
2768
|
this.pendingAdBreak = null;
|
|
2769
2769
|
this.savedMutedStateBeforeAd = null;
|
|
2770
|
+
this.adLayerInitialized = false;
|
|
2770
2771
|
this.consecutiveFailures = 0;
|
|
2771
2772
|
this.maxConsecutiveFailures = 5;
|
|
2772
2773
|
this.lastAdRequestTime = 0;
|
|
@@ -3415,12 +3416,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
3415
3416
|
this.video.autoplay = !!this.config.autoplay;
|
|
3416
3417
|
this.video.muted = !!this.config.muted;
|
|
3417
3418
|
if (!this.config.disableAds) {
|
|
3418
|
-
this.
|
|
3419
|
-
if (!this.config.disableFiller) {
|
|
3420
|
-
this.ensureFillerVideo();
|
|
3421
|
-
}
|
|
3422
|
-
this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3423
|
-
this.attachAdLayerEventListeners();
|
|
3419
|
+
this.initializeAdLayer();
|
|
3424
3420
|
}
|
|
3425
3421
|
this.timeUpdateHandler = function() {
|
|
3426
3422
|
_this.onTimeUpdate(_this.video.currentTime);
|
|
@@ -3521,6 +3517,31 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
3521
3517
|
return this.showAds;
|
|
3522
3518
|
}
|
|
3523
3519
|
},
|
|
3520
|
+
{
|
|
3521
|
+
key: "initializeAdLayer",
|
|
3522
|
+
value: function initializeAdLayer() {
|
|
3523
|
+
if (this.adLayerInitialized) return;
|
|
3524
|
+
this.adLayer.initialize();
|
|
3525
|
+
if (!this.config.disableFiller) {
|
|
3526
|
+
this.ensureFillerVideo();
|
|
3527
|
+
}
|
|
3528
|
+
this.adLayer.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3529
|
+
this.attachAdLayerEventListeners();
|
|
3530
|
+
this.adLayerInitialized = true;
|
|
3531
|
+
}
|
|
3532
|
+
},
|
|
3533
|
+
{
|
|
3534
|
+
key: "setDisableAds",
|
|
3535
|
+
value: function setDisableAds(disabled) {
|
|
3536
|
+
this.config.disableAds = disabled;
|
|
3537
|
+
if (!disabled && this.attached) {
|
|
3538
|
+
this.initializeAdLayer();
|
|
3539
|
+
}
|
|
3540
|
+
if (this.config.debugAdTiming) {
|
|
3541
|
+
console.log("[StormcloudVideoPlayer] setDisableAds:", disabled);
|
|
3542
|
+
}
|
|
3543
|
+
}
|
|
3544
|
+
},
|
|
3524
3545
|
{
|
|
3525
3546
|
key: "syncMainContentAudioWhenVisible",
|
|
3526
3547
|
value: function syncMainContentAudioWhenVisible() {
|
|
@@ -4045,14 +4066,21 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
4045
4066
|
}
|
|
4046
4067
|
}
|
|
4047
4068
|
},
|
|
4069
|
+
{
|
|
4070
|
+
key: "extractTsFilename",
|
|
4071
|
+
value: function extractTsFilename(url) {
|
|
4072
|
+
var _parts_;
|
|
4073
|
+
var clean = url.includes("?") ? url.slice(0, url.indexOf("?")) : url;
|
|
4074
|
+
var parts = clean.split("/");
|
|
4075
|
+
return (_parts_ = parts[parts.length - 1]) !== null && _parts_ !== void 0 ? _parts_ : clean;
|
|
4076
|
+
}
|
|
4077
|
+
},
|
|
4048
4078
|
{
|
|
4049
4079
|
key: "fragmentMatchesSegment",
|
|
4050
4080
|
value: function fragmentMatchesSegment(frag, segmentName) {
|
|
4051
|
-
var _rawUrl_split_;
|
|
4052
4081
|
var rawUrl = (frag === null || frag === void 0 ? void 0 : frag.url) || (frag === null || frag === void 0 ? void 0 : frag.relurl) || "";
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
return url.endsWith(name) || url.includes(name);
|
|
4082
|
+
if (!rawUrl) return false;
|
|
4083
|
+
return this.extractTsFilename(rawUrl) === this.extractTsFilename(segmentName);
|
|
4056
4084
|
}
|
|
4057
4085
|
},
|
|
4058
4086
|
{
|