stormcloud-video-player 0.2.14 → 0.2.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/README.md +92 -11
- package/dist/stormcloud-vp.min.js +2 -2
- package/lib/index.cjs +397 -256
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +2 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +397 -256
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +91 -30
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +2 -0
- package/lib/players/FilePlayer.cjs +12 -1
- package/lib/players/FilePlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.cjs +104 -33
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +116 -34
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +27 -8
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +372 -252
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +1 -1
|
@@ -21,6 +21,8 @@ declare class StormcloudVideoPlayer {
|
|
|
21
21
|
private totalAdsInBreak;
|
|
22
22
|
private showAds;
|
|
23
23
|
private isLiveStream;
|
|
24
|
+
private nativeHlsMode;
|
|
25
|
+
private videoSrcProtection;
|
|
24
26
|
constructor(config: StormcloudVideoPlayerConfig);
|
|
25
27
|
private createAdPlayer;
|
|
26
28
|
load(): Promise<void>;
|
|
@@ -128,8 +128,19 @@ var FilePlayer = class extends import_react.Component {
|
|
|
128
128
|
};
|
|
129
129
|
};
|
|
130
130
|
this.play = () => {
|
|
131
|
+
var _a;
|
|
131
132
|
if (this.props.videoElement) {
|
|
132
|
-
this.props.videoElement
|
|
133
|
+
const video = this.props.videoElement;
|
|
134
|
+
const hasValidSource = video.src || video.currentSrc && video.currentSrc !== "" || video.readyState >= 1;
|
|
135
|
+
if (hasValidSource) {
|
|
136
|
+
(_a = video.play()) == null ? void 0 : _a.catch((error) => {
|
|
137
|
+
var _a2, _b;
|
|
138
|
+
console.error("[FilePlayer] Failed to play:", error);
|
|
139
|
+
(_b = (_a2 = this.props).onError) == null ? void 0 : _b.call(_a2, error);
|
|
140
|
+
});
|
|
141
|
+
} else {
|
|
142
|
+
console.warn("[FilePlayer] Cannot play: video has no valid source");
|
|
143
|
+
}
|
|
133
144
|
}
|
|
134
145
|
};
|
|
135
146
|
this.pause = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/players/FilePlayer.tsx","../../src/patterns.ts"],"sourcesContent":["import { Component } from \"react\";\nimport { canPlay } from \"../patterns\";\n\nexport interface FilePlayerProps {\n src: string;\n videoElement?: HTMLVideoElement;\n onMount?: (player: any) => void;\n onReady?: () => void;\n onPlay?: () => void;\n onPause?: () => void;\n onEnded?: () => void;\n onLoaded?: () => void;\n onError?: (error: any) => void;\n autoplay?: boolean;\n muted?: boolean;\n loop?: boolean;\n controls?: boolean;\n playsInline?: boolean;\n preload?: string;\n poster?: string;\n}\n\nexport default class FilePlayer extends Component<FilePlayerProps> {\n static displayName = \"FilePlayer\";\n\n static canPlay = canPlay.file;\n\n private mounted = false;\n private ready = false;\n\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n\n componentWillUnmount() {\n this.mounted = false;\n }\n\n componentDidUpdate(prevProps: FilePlayerProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n\n load = () => {\n if (!this.props.videoElement || !this.props.src) return;\n\n const video = this.props.videoElement;\n\n const handleLoadedMetadata = () => {\n if (this.mounted && !this.ready) {\n this.ready = true;\n this.props.onReady?.();\n }\n };\n\n const handlePlay = () => {\n if (this.mounted) {\n this.props.onPlay?.();\n }\n };\n\n const handlePause = () => {\n if (this.mounted) {\n this.props.onPause?.();\n }\n };\n\n const handleEnded = () => {\n if (this.mounted) {\n this.props.onEnded?.();\n }\n };\n\n const handleError = (error: any) => {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n };\n\n const handleLoadedData = () => {\n if (this.mounted) {\n this.props.onLoaded?.();\n }\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\n video.src = this.props.src;\n if (this.props.autoplay !== undefined) video.autoplay = this.props.autoplay;\n if (this.props.muted !== undefined) video.muted = this.props.muted;\n if (this.props.loop !== undefined) video.loop = this.props.loop;\n if (this.props.controls !== undefined) video.controls = this.props.controls;\n if (this.props.playsInline !== undefined)\n video.playsInline = this.props.playsInline;\n if (this.props.preload !== undefined)\n video.preload = this.props.preload as \"\" | \"metadata\" | \"none\" | \"auto\";\n if (this.props.poster !== undefined) video.poster = this.props.poster;\n\n this.props.onMount?.(this);\n\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\n play = () => {\n if (this.props.videoElement) {\n this.props.videoElement.play();\n }\n };\n\n pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n }\n };\n\n stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n\n seekTo = (seconds: number, keepPlaying?: boolean) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n\n setVolume = (volume: number) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n\n mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n\n unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n\n setPlaybackRate = (rate: number) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n\n setLoop = (loop: boolean) => {\n if (this.props.videoElement) {\n this.props.videoElement.loop = loop;\n }\n };\n\n getDuration = (): number | null => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n\n getCurrentTime = (): number | null => {\n if (\n this.props.videoElement &&\n isFinite(this.props.videoElement.currentTime)\n ) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n\n getSecondsLoaded = (): number | null => {\n if (\n this.props.videoElement &&\n this.props.videoElement.buffered.length > 0\n ) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n\n getInternalPlayer = (key = \"player\") => {\n if (key === \"video\") return this.props.videoElement;\n return null;\n };\n\n enablePIP = async () => {\n if (\n this.props.videoElement &&\n \"requestPictureInPicture\" in this.props.videoElement\n ) {\n try {\n await (this.props.videoElement as any).requestPictureInPicture();\n } catch (error) {\n console.warn(\"Picture-in-Picture failed:\", error);\n }\n }\n };\n\n 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 render() {\n return null;\n }\n}\n","export const HLS_EXTENSIONS = /\\.(m3u8)($|\\?)/i;\nexport const HLS_PATHS = /\\/hls\\//i;\nexport const DASH_EXTENSIONS = /\\.(mpd)($|\\?)/i;\nexport const VIDEO_EXTENSIONS = /\\.(mp4|webm|ogg|avi|mov|wmv|flv|mkv)($|\\?)/i;\nexport const AUDIO_EXTENSIONS = /\\.(mp3|wav|ogg|aac|wma|flac|m4a)($|\\?)/i;\n\nexport const canPlay = {\n hls: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return HLS_EXTENSIONS.test(url) || HLS_PATHS.test(url);\n },\n\n dash: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return DASH_EXTENSIONS.test(url);\n },\n\n video: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url);\n },\n\n audio: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return AUDIO_EXTENSIONS.test(url);\n },\n\n file: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url) || AUDIO_EXTENSIONS.test(url);\n },\n};\n"],"mappings":"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","names":["_a","_b"]}
|
|
1
|
+
{"version":3,"sources":["../../src/players/FilePlayer.tsx","../../src/patterns.ts"],"sourcesContent":["import { Component } from \"react\";\nimport { canPlay } from \"../patterns\";\n\nexport interface FilePlayerProps {\n src: string;\n videoElement?: HTMLVideoElement;\n onMount?: (player: any) => void;\n onReady?: () => void;\n onPlay?: () => void;\n onPause?: () => void;\n onEnded?: () => void;\n onLoaded?: () => void;\n onError?: (error: any) => void;\n autoplay?: boolean;\n muted?: boolean;\n loop?: boolean;\n controls?: boolean;\n playsInline?: boolean;\n preload?: string;\n poster?: string;\n}\n\nexport default class FilePlayer extends Component<FilePlayerProps> {\n static displayName = \"FilePlayer\";\n\n static canPlay = canPlay.file;\n\n private mounted = false;\n private ready = false;\n\n componentDidMount() {\n this.mounted = true;\n this.load();\n }\n\n componentWillUnmount() {\n this.mounted = false;\n }\n\n componentDidUpdate(prevProps: FilePlayerProps) {\n if (prevProps.src !== this.props.src) {\n this.load();\n }\n }\n\n load = () => {\n if (!this.props.videoElement || !this.props.src) return;\n\n const video = this.props.videoElement;\n\n const handleLoadedMetadata = () => {\n if (this.mounted && !this.ready) {\n this.ready = true;\n this.props.onReady?.();\n }\n };\n\n const handlePlay = () => {\n if (this.mounted) {\n this.props.onPlay?.();\n }\n };\n\n const handlePause = () => {\n if (this.mounted) {\n this.props.onPause?.();\n }\n };\n\n const handleEnded = () => {\n if (this.mounted) {\n this.props.onEnded?.();\n }\n };\n\n const handleError = (error: any) => {\n if (this.mounted) {\n this.props.onError?.(error);\n }\n };\n\n const handleLoadedData = () => {\n if (this.mounted) {\n this.props.onLoaded?.();\n }\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\n video.src = this.props.src;\n if (this.props.autoplay !== undefined) video.autoplay = this.props.autoplay;\n if (this.props.muted !== undefined) video.muted = this.props.muted;\n if (this.props.loop !== undefined) video.loop = this.props.loop;\n if (this.props.controls !== undefined) video.controls = this.props.controls;\n if (this.props.playsInline !== undefined)\n video.playsInline = this.props.playsInline;\n if (this.props.preload !== undefined)\n video.preload = this.props.preload as \"\" | \"metadata\" | \"none\" | \"auto\";\n if (this.props.poster !== undefined) video.poster = this.props.poster;\n\n this.props.onMount?.(this);\n\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\n play = () => {\n if (this.props.videoElement) {\n const video = this.props.videoElement;\n const hasValidSource =\n video.src ||\n (video.currentSrc && video.currentSrc !== \"\") ||\n video.readyState >= 1;\n\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\n pause = () => {\n if (this.props.videoElement) {\n this.props.videoElement.pause();\n }\n };\n\n stop = () => {\n this.pause();\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = 0;\n }\n };\n\n seekTo = (seconds: number, keepPlaying?: boolean) => {\n if (this.props.videoElement) {\n this.props.videoElement.currentTime = seconds;\n if (!keepPlaying) {\n this.pause();\n }\n }\n };\n\n setVolume = (volume: number) => {\n if (this.props.videoElement) {\n this.props.videoElement.volume = Math.max(0, Math.min(1, volume));\n }\n };\n\n mute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = true;\n }\n };\n\n unmute = () => {\n if (this.props.videoElement) {\n this.props.videoElement.muted = false;\n }\n };\n\n setPlaybackRate = (rate: number) => {\n if (this.props.videoElement && rate > 0) {\n this.props.videoElement.playbackRate = rate;\n }\n };\n\n setLoop = (loop: boolean) => {\n if (this.props.videoElement) {\n this.props.videoElement.loop = loop;\n }\n };\n\n getDuration = (): number | null => {\n if (this.props.videoElement && isFinite(this.props.videoElement.duration)) {\n return this.props.videoElement.duration;\n }\n return null;\n };\n\n getCurrentTime = (): number | null => {\n if (\n this.props.videoElement &&\n isFinite(this.props.videoElement.currentTime)\n ) {\n return this.props.videoElement.currentTime;\n }\n return null;\n };\n\n getSecondsLoaded = (): number | null => {\n if (\n this.props.videoElement &&\n this.props.videoElement.buffered.length > 0\n ) {\n return this.props.videoElement.buffered.end(\n this.props.videoElement.buffered.length - 1\n );\n }\n return null;\n };\n\n getInternalPlayer = (key = \"player\") => {\n if (key === \"video\") return this.props.videoElement;\n return null;\n };\n\n enablePIP = async () => {\n if (\n this.props.videoElement &&\n \"requestPictureInPicture\" in this.props.videoElement\n ) {\n try {\n await (this.props.videoElement as any).requestPictureInPicture();\n } catch (error) {\n console.warn(\"Picture-in-Picture failed:\", error);\n }\n }\n };\n\n 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 render() {\n return null;\n }\n}\n","export const HLS_EXTENSIONS = /\\.(m3u8)($|\\?)/i;\nexport const HLS_PATHS = /\\/hls\\//i;\nexport const DASH_EXTENSIONS = /\\.(mpd)($|\\?)/i;\nexport const VIDEO_EXTENSIONS = /\\.(mp4|webm|ogg|avi|mov|wmv|flv|mkv)($|\\?)/i;\nexport const AUDIO_EXTENSIONS = /\\.(mp3|wav|ogg|aac|wma|flac|m4a)($|\\?)/i;\n\nexport const canPlay = {\n hls: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return HLS_EXTENSIONS.test(url) || HLS_PATHS.test(url);\n },\n\n dash: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return DASH_EXTENSIONS.test(url);\n },\n\n video: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url);\n },\n\n audio: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return AUDIO_EXTENSIONS.test(url);\n },\n\n file: (url: string): boolean => {\n if (!url || typeof url !== \"string\") return false;\n return VIDEO_EXTENSIONS.test(url) || AUDIO_EXTENSIONS.test(url);\n },\n};\n"],"mappings":"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","names":["_a","_b"]}
|
|
@@ -853,7 +853,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
853
853
|
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
|
|
854
854
|
const parserError = xmlDoc.querySelector("parsererror");
|
|
855
855
|
if (parserError) {
|
|
856
|
-
console.error("[HlsAdPlayer] XML parsing error:", parserError.textContent);
|
|
856
|
+
console.error("[HlsAdPlayer] XML parsing error (malformed VAST XML):", parserError.textContent);
|
|
857
857
|
return null;
|
|
858
858
|
}
|
|
859
859
|
const adElement = xmlDoc.querySelector("Ad");
|
|
@@ -863,28 +863,45 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
863
863
|
}
|
|
864
864
|
const adId = adElement.getAttribute("id") || "unknown";
|
|
865
865
|
const title = ((_a = xmlDoc.querySelector("AdTitle")) == null ? void 0 : _a.textContent) || "Ad";
|
|
866
|
+
const isNoAdAvailable = adId === "empty" || title.toLowerCase().includes("no ad available") || title.toLowerCase() === "no ad available";
|
|
866
867
|
const durationText = ((_b = xmlDoc.querySelector("Duration")) == null ? void 0 : _b.textContent) || "00:00:30";
|
|
867
868
|
const durationParts = durationText.split(":");
|
|
868
869
|
const duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
|
|
869
870
|
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
870
871
|
const mediaFiles = [];
|
|
871
|
-
mediaFileElements.
|
|
872
|
+
console.log(`[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`);
|
|
873
|
+
mediaFileElements.forEach((mf, index) => {
|
|
872
874
|
var _a2;
|
|
873
875
|
const type = mf.getAttribute("type") || "";
|
|
876
|
+
const url = ((_a2 = mf.textContent) == null ? void 0 : _a2.trim()) || "";
|
|
877
|
+
const width = mf.getAttribute("width") || "";
|
|
878
|
+
const height = mf.getAttribute("height") || "";
|
|
879
|
+
console.log(`[HlsAdPlayer] MediaFile ${index}: type="${type}", url="${url}", width="${width}", height="${height}"`);
|
|
874
880
|
if (type === "application/x-mpegURL" || type.includes("m3u8")) {
|
|
881
|
+
if (!url) {
|
|
882
|
+
console.warn(`[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`);
|
|
883
|
+
return;
|
|
884
|
+
}
|
|
875
885
|
const bitrateAttr = mf.getAttribute("bitrate");
|
|
876
886
|
const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
|
|
877
887
|
mediaFiles.push({
|
|
878
|
-
url
|
|
888
|
+
url,
|
|
879
889
|
type,
|
|
880
|
-
width: parseInt(
|
|
881
|
-
height: parseInt(
|
|
890
|
+
width: parseInt(width || "1920", 10),
|
|
891
|
+
height: parseInt(height || "1080", 10),
|
|
882
892
|
bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
|
|
883
893
|
});
|
|
894
|
+
console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);
|
|
895
|
+
} else {
|
|
896
|
+
console.log(`[HlsAdPlayer] MediaFile ${index} ignored (type="${type}" is not HLS)`);
|
|
884
897
|
}
|
|
885
898
|
});
|
|
886
899
|
if (mediaFiles.length === 0) {
|
|
887
|
-
|
|
900
|
+
if (isNoAdAvailable) {
|
|
901
|
+
console.warn("[HlsAdPlayer] No ads available (VAST response indicates no ads)");
|
|
902
|
+
} else {
|
|
903
|
+
console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
|
|
904
|
+
}
|
|
888
905
|
return null;
|
|
889
906
|
}
|
|
890
907
|
const trackingUrls = {
|
|
@@ -1072,9 +1089,11 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1072
1089
|
}
|
|
1073
1090
|
const vastXml = await response.text();
|
|
1074
1091
|
console.log("[HlsAdPlayer] VAST XML received");
|
|
1092
|
+
console.log("[HlsAdPlayer] VAST XML content (first 2000 chars):", vastXml.substring(0, 2e3));
|
|
1075
1093
|
const ad = parseVastXml(vastXml);
|
|
1076
1094
|
if (!ad) {
|
|
1077
|
-
|
|
1095
|
+
console.warn("[HlsAdPlayer] No ads available from VAST response");
|
|
1096
|
+
return Promise.resolve();
|
|
1078
1097
|
}
|
|
1079
1098
|
currentAd = ad;
|
|
1080
1099
|
console.log(`[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`);
|
|
@@ -1089,7 +1108,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
1089
1108
|
},
|
|
1090
1109
|
async play() {
|
|
1091
1110
|
if (!currentAd) {
|
|
1092
|
-
console.warn("[HlsAdPlayer] Cannot play: No ad loaded");
|
|
1111
|
+
console.warn("[HlsAdPlayer] Cannot play: No ad loaded (no ads available)");
|
|
1093
1112
|
return Promise.reject(new Error("No ad loaded"));
|
|
1094
1113
|
}
|
|
1095
1114
|
console.log("[HlsAdPlayer] Starting ad playback");
|
|
@@ -1720,6 +1739,8 @@ var StormcloudVideoPlayer = class {
|
|
|
1720
1739
|
this.totalAdsInBreak = 0;
|
|
1721
1740
|
this.showAds = false;
|
|
1722
1741
|
this.isLiveStream = false;
|
|
1742
|
+
this.nativeHlsMode = false;
|
|
1743
|
+
this.videoSrcProtection = null;
|
|
1723
1744
|
initializePolyfills();
|
|
1724
1745
|
const browserOverrides = getBrowserConfigOverrides();
|
|
1725
1746
|
this.config = { ...config, ...browserOverrides };
|
|
@@ -1740,7 +1761,9 @@ var StormcloudVideoPlayer = class {
|
|
|
1740
1761
|
}
|
|
1741
1762
|
if (adPlayerType === "hls") {
|
|
1742
1763
|
if (this.config.debugAdTiming) {
|
|
1743
|
-
console.log(
|
|
1764
|
+
console.log(
|
|
1765
|
+
"[StormcloudVideoPlayer] Creating HLS ad player (AdStorm mode)"
|
|
1766
|
+
);
|
|
1744
1767
|
}
|
|
1745
1768
|
return createHlsAdPlayer(this.video, {
|
|
1746
1769
|
continueLiveStreamDuringAds,
|
|
@@ -1749,7 +1772,9 @@ var StormcloudVideoPlayer = class {
|
|
|
1749
1772
|
});
|
|
1750
1773
|
} else {
|
|
1751
1774
|
if (this.config.debugAdTiming) {
|
|
1752
|
-
console.log(
|
|
1775
|
+
console.log(
|
|
1776
|
+
"[StormcloudVideoPlayer] Creating Google IMA ad player (Default mode)"
|
|
1777
|
+
);
|
|
1753
1778
|
}
|
|
1754
1779
|
return createImaController(this.video, {
|
|
1755
1780
|
continueLiveStreamDuringAds
|
|
@@ -1773,11 +1798,13 @@ var StormcloudVideoPlayer = class {
|
|
|
1773
1798
|
}
|
|
1774
1799
|
this.initializeTracking();
|
|
1775
1800
|
if (this.shouldUseNativeHls()) {
|
|
1801
|
+
this.nativeHlsMode = true;
|
|
1802
|
+
this.videoSrcProtection = this.config.src;
|
|
1776
1803
|
this.video.src = this.config.src;
|
|
1777
1804
|
this.isLiveStream = (_a = this.config.lowLatencyMode) != null ? _a : false;
|
|
1778
1805
|
if (this.config.debugAdTiming) {
|
|
1779
1806
|
console.log(
|
|
1780
|
-
"[StormcloudVideoPlayer]
|
|
1807
|
+
"[StormcloudVideoPlayer] Using native HLS playback - VOD mode:",
|
|
1781
1808
|
{
|
|
1782
1809
|
isLive: this.isLiveStream,
|
|
1783
1810
|
allowNativeHls: this.config.allowNativeHls,
|
|
@@ -1925,7 +1952,9 @@ var StormcloudVideoPlayer = class {
|
|
|
1925
1952
|
this.ima.initialize();
|
|
1926
1953
|
this.ima.on("all_ads_completed", () => {
|
|
1927
1954
|
if (this.config.debugAdTiming) {
|
|
1928
|
-
console.log(
|
|
1955
|
+
console.log(
|
|
1956
|
+
"[StormcloudVideoPlayer] IMA all_ads_completed event received"
|
|
1957
|
+
);
|
|
1929
1958
|
}
|
|
1930
1959
|
});
|
|
1931
1960
|
this.ima.on("ad_error", () => {
|
|
@@ -1990,13 +2019,31 @@ var StormcloudVideoPlayer = class {
|
|
|
1990
2019
|
this.video.addEventListener("timeupdate", () => {
|
|
1991
2020
|
this.onTimeUpdate(this.video.currentTime);
|
|
1992
2021
|
});
|
|
2022
|
+
this.video.addEventListener("emptied", () => {
|
|
2023
|
+
if (this.nativeHlsMode && this.videoSrcProtection && !this.ima.isAdPlaying()) {
|
|
2024
|
+
if (this.config.debugAdTiming) {
|
|
2025
|
+
console.log(
|
|
2026
|
+
"[StormcloudVideoPlayer] Video src was cleared, restoring:",
|
|
2027
|
+
this.videoSrcProtection
|
|
2028
|
+
);
|
|
2029
|
+
}
|
|
2030
|
+
const currentTime = this.video.currentTime;
|
|
2031
|
+
const wasPaused = this.video.paused;
|
|
2032
|
+
this.video.src = this.videoSrcProtection;
|
|
2033
|
+
this.video.currentTime = currentTime;
|
|
2034
|
+
if (!wasPaused) {
|
|
2035
|
+
this.video.play().catch(() => {
|
|
2036
|
+
});
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
});
|
|
1993
2040
|
}
|
|
1994
2041
|
shouldUseNativeHls() {
|
|
1995
2042
|
const streamType = this.getStreamType();
|
|
1996
2043
|
if (streamType === "other") {
|
|
1997
2044
|
return true;
|
|
1998
2045
|
}
|
|
1999
|
-
const canNative = this.video.canPlayType("application/vnd.apple.
|
|
2046
|
+
const canNative = this.video.canPlayType("application/vnd.apple.mpegurl");
|
|
2000
2047
|
return !!(this.config.allowNativeHls && canNative);
|
|
2001
2048
|
}
|
|
2002
2049
|
onId3Tag(tag) {
|
|
@@ -2423,10 +2470,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2423
2470
|
var _a, _b, _c;
|
|
2424
2471
|
const vastMode = this.config.vastMode || "default";
|
|
2425
2472
|
if (this.config.debugAdTiming) {
|
|
2426
|
-
console.log(
|
|
2427
|
-
"[StormcloudVideoPlayer] VAST mode:",
|
|
2428
|
-
vastMode
|
|
2429
|
-
);
|
|
2473
|
+
console.log("[StormcloudVideoPlayer] VAST mode:", vastMode);
|
|
2430
2474
|
}
|
|
2431
2475
|
if (vastMode === "adstorm") {
|
|
2432
2476
|
if (!this.config.licenseKey) {
|
|
@@ -2441,7 +2485,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2441
2485
|
this.apiVastTagUrl = vastEndpoint;
|
|
2442
2486
|
if (this.config.debugAdTiming) {
|
|
2443
2487
|
console.log(
|
|
2444
|
-
"[StormcloudVideoPlayer] Using AdStorm VAST endpoint:",
|
|
2488
|
+
"[StormcloudVideoPlayer] Using AdStorm VAST endpoint (adstorm mode):",
|
|
2445
2489
|
vastEndpoint
|
|
2446
2490
|
);
|
|
2447
2491
|
}
|
|
@@ -2544,10 +2588,7 @@ var StormcloudVideoPlayer = class {
|
|
|
2544
2588
|
this.currentAdIndex = 0;
|
|
2545
2589
|
this.totalAdsInBreak = 1;
|
|
2546
2590
|
if (this.config.debugAdTiming) {
|
|
2547
|
-
console.log(
|
|
2548
|
-
"[StormcloudVideoPlayer] Using VAST endpoint:",
|
|
2549
|
-
vastTagUrl
|
|
2550
|
-
);
|
|
2591
|
+
console.log("[StormcloudVideoPlayer] Using VAST endpoint:", vastTagUrl);
|
|
2551
2592
|
}
|
|
2552
2593
|
} else if (tags && tags.length > 0) {
|
|
2553
2594
|
vastTagUrl = tags[0];
|
|
@@ -2697,12 +2738,26 @@ var StormcloudVideoPlayer = class {
|
|
|
2697
2738
|
this.startAdFailsafeTimer();
|
|
2698
2739
|
try {
|
|
2699
2740
|
await this.ima.requestAds(vastTagUrl);
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2741
|
+
try {
|
|
2742
|
+
if (this.config.debugAdTiming) {
|
|
2743
|
+
console.log(
|
|
2744
|
+
"[StormcloudVideoPlayer] Ad request completed, attempting playback"
|
|
2745
|
+
);
|
|
2746
|
+
}
|
|
2747
|
+
await this.ima.play();
|
|
2748
|
+
if (this.config.debugAdTiming) {
|
|
2749
|
+
console.log(
|
|
2750
|
+
"[StormcloudVideoPlayer] Ad playback started successfully"
|
|
2751
|
+
);
|
|
2752
|
+
}
|
|
2753
|
+
} catch (playError) {
|
|
2754
|
+
if (this.config.debugAdTiming) {
|
|
2755
|
+
console.log(
|
|
2756
|
+
"[StormcloudVideoPlayer] No ads available, skipping playback"
|
|
2757
|
+
);
|
|
2758
|
+
}
|
|
2759
|
+
this.handleAdFailure();
|
|
2760
|
+
return;
|
|
2706
2761
|
}
|
|
2707
2762
|
} catch (error) {
|
|
2708
2763
|
if (this.config.debugAdTiming) {
|
|
@@ -2755,7 +2810,9 @@ var StormcloudVideoPlayer = class {
|
|
|
2755
2810
|
});
|
|
2756
2811
|
} else {
|
|
2757
2812
|
if (this.config.debugAdTiming) {
|
|
2758
|
-
console.log(
|
|
2813
|
+
console.log(
|
|
2814
|
+
"[StormcloudVideoPlayer] Video is already playing, no resume needed"
|
|
2815
|
+
);
|
|
2759
2816
|
}
|
|
2760
2817
|
}
|
|
2761
2818
|
}
|
|
@@ -2774,7 +2831,11 @@ var StormcloudVideoPlayer = class {
|
|
|
2774
2831
|
if (this.config.debugAdTiming) {
|
|
2775
2832
|
console.warn(
|
|
2776
2833
|
"[StormcloudVideoPlayer] Failsafe timer triggered - forcing video resume",
|
|
2777
|
-
{
|
|
2834
|
+
{
|
|
2835
|
+
paused: this.video.paused,
|
|
2836
|
+
showAds: this.showAds,
|
|
2837
|
+
adPlaying: this.ima.isAdPlaying()
|
|
2838
|
+
}
|
|
2778
2839
|
);
|
|
2779
2840
|
}
|
|
2780
2841
|
this.handleAdFailure();
|
|
@@ -2996,10 +3057,20 @@ var HlsPlayer = class extends import_react.Component {
|
|
|
2996
3057
|
}
|
|
2997
3058
|
};
|
|
2998
3059
|
this.play = () => {
|
|
2999
|
-
var _a, _b;
|
|
3060
|
+
var _a, _b, _c;
|
|
3000
3061
|
if (this.props.videoElement) {
|
|
3001
|
-
this.props.videoElement
|
|
3002
|
-
|
|
3062
|
+
const video = this.props.videoElement;
|
|
3063
|
+
const hasValidSource = video.src || video.currentSrc && video.currentSrc !== "" || video.readyState >= 1;
|
|
3064
|
+
if (hasValidSource) {
|
|
3065
|
+
(_a = video.play()) == null ? void 0 : _a.catch((error) => {
|
|
3066
|
+
var _a2, _b2;
|
|
3067
|
+
console.error("[HlsPlayer] Failed to play:", error);
|
|
3068
|
+
(_b2 = (_a2 = this.props).onError) == null ? void 0 : _b2.call(_a2, error);
|
|
3069
|
+
});
|
|
3070
|
+
(_c = (_b = this.props).onPlay) == null ? void 0 : _c.call(_b);
|
|
3071
|
+
} else {
|
|
3072
|
+
console.warn("[HlsPlayer] Cannot play: video has no valid source");
|
|
3073
|
+
}
|
|
3003
3074
|
}
|
|
3004
3075
|
};
|
|
3005
3076
|
this.pause = () => {
|