stormcloud-video-player 0.2.13 → 0.2.14
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 +2 -2
- package/lib/index.cjs +238 -117
- 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 +238 -117
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +196 -92
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/players/FilePlayer.cjs +14 -7
- package/lib/players/FilePlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.cjs +204 -97
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +218 -104
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +89 -16
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.d.cts +2 -0
- package/lib/sdk/ima.cjs +34 -24
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +203 -97
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/utils/browserCompat.cjs +2 -1
- package/lib/utils/browserCompat.cjs.map +1 -1
- package/lib/utils/tracking.cjs +10 -9
- package/lib/utils/tracking.cjs.map +1 -1
- package/package.json +1 -1
package/lib/sdk/hlsAdPlayer.cjs
CHANGED
|
@@ -38,7 +38,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
38
38
|
let adPlaying = false;
|
|
39
39
|
let originalMutedState = false;
|
|
40
40
|
const listeners = /* @__PURE__ */ new Map();
|
|
41
|
-
const licenseKey = options
|
|
41
|
+
const licenseKey = options == null ? void 0 : options.licenseKey;
|
|
42
|
+
const mainHlsInstance = options == null ? void 0 : options.mainHlsInstance;
|
|
42
43
|
let adVideoElement;
|
|
43
44
|
let adHls;
|
|
44
45
|
let adContainerEl;
|
|
@@ -85,7 +86,74 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
85
86
|
}
|
|
86
87
|
});
|
|
87
88
|
}
|
|
89
|
+
function getMainStreamQuality() {
|
|
90
|
+
if (!mainHlsInstance || !mainHlsInstance.levels) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
const currentLevel = mainHlsInstance.currentLevel;
|
|
94
|
+
if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {
|
|
95
|
+
const autoLevel = mainHlsInstance.loadLevel;
|
|
96
|
+
if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {
|
|
97
|
+
const level2 = mainHlsInstance.levels[autoLevel];
|
|
98
|
+
return {
|
|
99
|
+
width: level2.width || 1920,
|
|
100
|
+
height: level2.height || 1080,
|
|
101
|
+
bitrate: level2.bitrate || 5e6
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
const level = mainHlsInstance.levels[currentLevel];
|
|
107
|
+
return {
|
|
108
|
+
width: level.width || 1920,
|
|
109
|
+
height: level.height || 1080,
|
|
110
|
+
bitrate: level.bitrate || 5e6
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function selectBestMediaFile(mediaFiles) {
|
|
114
|
+
if (mediaFiles.length === 0) {
|
|
115
|
+
throw new Error("No media files available");
|
|
116
|
+
}
|
|
117
|
+
const firstFile = mediaFiles[0];
|
|
118
|
+
if (!firstFile) {
|
|
119
|
+
throw new Error("No media files available");
|
|
120
|
+
}
|
|
121
|
+
if (mediaFiles.length === 1) {
|
|
122
|
+
return firstFile;
|
|
123
|
+
}
|
|
124
|
+
const mainQuality = getMainStreamQuality();
|
|
125
|
+
if (!mainQuality) {
|
|
126
|
+
console.log("[HlsAdPlayer] No main stream quality info, using first media file");
|
|
127
|
+
return firstFile;
|
|
128
|
+
}
|
|
129
|
+
console.log("[HlsAdPlayer] Main stream quality:", mainQuality);
|
|
130
|
+
const scoredFiles = mediaFiles.map((file) => {
|
|
131
|
+
const widthDiff = Math.abs(file.width - mainQuality.width);
|
|
132
|
+
const heightDiff = Math.abs(file.height - mainQuality.height);
|
|
133
|
+
const resolutionDiff = widthDiff + heightDiff;
|
|
134
|
+
const fileBitrate = (file.bitrate || 5e3) * 1e3;
|
|
135
|
+
const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);
|
|
136
|
+
const score = resolutionDiff * 2 + bitrateDiff / 1e3;
|
|
137
|
+
return { file, score, resolutionDiff, bitrateDiff };
|
|
138
|
+
});
|
|
139
|
+
scoredFiles.sort((a, b) => a.score - b.score);
|
|
140
|
+
const bestMatch = scoredFiles[0];
|
|
141
|
+
if (!bestMatch) {
|
|
142
|
+
console.log("[HlsAdPlayer] No best match found, using first media file");
|
|
143
|
+
return firstFile;
|
|
144
|
+
}
|
|
145
|
+
console.log("[HlsAdPlayer] Selected media file:", {
|
|
146
|
+
url: bestMatch.file.url,
|
|
147
|
+
resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,
|
|
148
|
+
bitrate: bestMatch.file.bitrate,
|
|
149
|
+
score: bestMatch.score,
|
|
150
|
+
resolutionDiff: bestMatch.resolutionDiff,
|
|
151
|
+
bitrateDiff: bestMatch.bitrateDiff
|
|
152
|
+
});
|
|
153
|
+
return bestMatch.file;
|
|
154
|
+
}
|
|
88
155
|
function parseVastXml(xmlString) {
|
|
156
|
+
var _a, _b, _c, _d;
|
|
89
157
|
try {
|
|
90
158
|
const parser = new DOMParser();
|
|
91
159
|
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
|
|
@@ -100,19 +168,20 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
100
168
|
return null;
|
|
101
169
|
}
|
|
102
170
|
const adId = adElement.getAttribute("id") || "unknown";
|
|
103
|
-
const title = xmlDoc.querySelector("AdTitle")
|
|
104
|
-
const durationText = xmlDoc.querySelector("Duration")
|
|
171
|
+
const title = ((_a = xmlDoc.querySelector("AdTitle")) == null ? void 0 : _a.textContent) || "Ad";
|
|
172
|
+
const durationText = ((_b = xmlDoc.querySelector("Duration")) == null ? void 0 : _b.textContent) || "00:00:30";
|
|
105
173
|
const durationParts = durationText.split(":");
|
|
106
174
|
const duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
|
|
107
175
|
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
108
176
|
const mediaFiles = [];
|
|
109
177
|
mediaFileElements.forEach((mf) => {
|
|
178
|
+
var _a2;
|
|
110
179
|
const type = mf.getAttribute("type") || "";
|
|
111
180
|
if (type === "application/x-mpegURL" || type.includes("m3u8")) {
|
|
112
181
|
const bitrateAttr = mf.getAttribute("bitrate");
|
|
113
182
|
const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
|
|
114
183
|
mediaFiles.push({
|
|
115
|
-
url: mf.textContent
|
|
184
|
+
url: ((_a2 = mf.textContent) == null ? void 0 : _a2.trim()) || "",
|
|
116
185
|
type,
|
|
117
186
|
width: parseInt(mf.getAttribute("width") || "1920", 10),
|
|
118
187
|
height: parseInt(mf.getAttribute("height") || "1080", 10),
|
|
@@ -141,12 +210,14 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
141
210
|
error: []
|
|
142
211
|
};
|
|
143
212
|
xmlDoc.querySelectorAll("Impression").forEach((el) => {
|
|
144
|
-
|
|
213
|
+
var _a2;
|
|
214
|
+
const url = (_a2 = el.textContent) == null ? void 0 : _a2.trim();
|
|
145
215
|
if (url) trackingUrls.impression.push(url);
|
|
146
216
|
});
|
|
147
217
|
xmlDoc.querySelectorAll("Tracking").forEach((el) => {
|
|
218
|
+
var _a2;
|
|
148
219
|
const event = el.getAttribute("event");
|
|
149
|
-
const url = el.textContent
|
|
220
|
+
const url = (_a2 = el.textContent) == null ? void 0 : _a2.trim();
|
|
150
221
|
if (event && url) {
|
|
151
222
|
const eventKey = event;
|
|
152
223
|
if (trackingUrls[eventKey]) {
|
|
@@ -154,7 +225,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
154
225
|
}
|
|
155
226
|
}
|
|
156
227
|
});
|
|
157
|
-
const clickThrough = xmlDoc.querySelector("ClickThrough")
|
|
228
|
+
const clickThrough = (_d = (_c = xmlDoc.querySelector("ClickThrough")) == null ? void 0 : _c.textContent) == null ? void 0 : _d.trim();
|
|
158
229
|
return {
|
|
159
230
|
id: adId,
|
|
160
231
|
title,
|
|
@@ -246,7 +317,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
246
317
|
adContainerEl.style.display = "none";
|
|
247
318
|
adContainerEl.style.pointerEvents = "none";
|
|
248
319
|
}
|
|
249
|
-
if (!options
|
|
320
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
250
321
|
contentVideo.play().catch(() => {
|
|
251
322
|
});
|
|
252
323
|
console.log("[HlsAdPlayer] Content resumed (VOD mode)");
|
|
@@ -264,7 +335,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
264
335
|
adContainerEl.style.display = "none";
|
|
265
336
|
adContainerEl.style.pointerEvents = "none";
|
|
266
337
|
}
|
|
267
|
-
if (!options
|
|
338
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
268
339
|
if (contentVideo.paused) {
|
|
269
340
|
contentVideo.play().catch(() => {
|
|
270
341
|
});
|
|
@@ -274,6 +345,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
274
345
|
}
|
|
275
346
|
return {
|
|
276
347
|
initialize() {
|
|
348
|
+
var _a;
|
|
277
349
|
console.log("[HlsAdPlayer] Initializing");
|
|
278
350
|
if (!adContainerEl) {
|
|
279
351
|
const container = document.createElement("div");
|
|
@@ -288,7 +360,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
288
360
|
container.style.pointerEvents = "none";
|
|
289
361
|
container.style.zIndex = "2";
|
|
290
362
|
container.style.backgroundColor = "#000";
|
|
291
|
-
contentVideo.parentElement
|
|
363
|
+
(_a = contentVideo.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
292
364
|
adContainerEl = container;
|
|
293
365
|
}
|
|
294
366
|
},
|
|
@@ -330,7 +402,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
330
402
|
try {
|
|
331
403
|
if (!adVideoElement) {
|
|
332
404
|
adVideoElement = createAdVideoElement();
|
|
333
|
-
adContainerEl
|
|
405
|
+
adContainerEl == null ? void 0 : adContainerEl.appendChild(adVideoElement);
|
|
334
406
|
setupAdEventListeners();
|
|
335
407
|
}
|
|
336
408
|
trackingFired = {
|
|
@@ -341,7 +413,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
341
413
|
thirdQuartile: false,
|
|
342
414
|
complete: false
|
|
343
415
|
};
|
|
344
|
-
if (!options
|
|
416
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
345
417
|
contentVideo.pause();
|
|
346
418
|
console.log("[HlsAdPlayer] Content paused (VOD mode)");
|
|
347
419
|
} else {
|
|
@@ -354,7 +426,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
354
426
|
adContainerEl.style.pointerEvents = "auto";
|
|
355
427
|
}
|
|
356
428
|
emit("content_pause");
|
|
357
|
-
const mediaFile = currentAd.mediaFiles
|
|
429
|
+
const mediaFile = selectBestMediaFile(currentAd.mediaFiles);
|
|
358
430
|
if (!mediaFile) {
|
|
359
431
|
throw new Error("No media file available for ad");
|
|
360
432
|
}
|
|
@@ -414,7 +486,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
414
486
|
adVideoElement.pause();
|
|
415
487
|
adVideoElement.src = "";
|
|
416
488
|
}
|
|
417
|
-
if (!options
|
|
489
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
418
490
|
contentVideo.play().catch(() => {
|
|
419
491
|
});
|
|
420
492
|
}
|
|
@@ -434,7 +506,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
434
506
|
adVideoElement.remove();
|
|
435
507
|
adVideoElement = void 0;
|
|
436
508
|
}
|
|
437
|
-
if (adContainerEl
|
|
509
|
+
if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
|
|
438
510
|
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
439
511
|
}
|
|
440
512
|
adContainerEl = void 0;
|
|
@@ -460,7 +532,8 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
460
532
|
listeners.get(event).add(listener);
|
|
461
533
|
},
|
|
462
534
|
off(event, listener) {
|
|
463
|
-
|
|
535
|
+
var _a;
|
|
536
|
+
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
464
537
|
},
|
|
465
538
|
updateOriginalMutedState(muted) {
|
|
466
539
|
originalMutedState = muted;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/sdk/hlsAdPlayer.ts"],"sourcesContent":["import type { ImaController } from \"../types\";\nimport Hls from \"hls.js\";\n\ninterface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\ninterface VastTrackingUrls {\n impression: string[];\n start: string[];\n firstQuartile: string[];\n midpoint: string[];\n thirdQuartile: string[];\n complete: string[];\n mute: string[];\n unmute: string[];\n pause: string[];\n resume: string[];\n fullscreen: string[];\n exitFullscreen: string[];\n skip: string[];\n error: string[];\n}\n\ninterface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\nexport function createHlsAdPlayer(\n contentVideo: HTMLVideoElement,\n options?: { continueLiveStreamDuringAds?: boolean; licenseKey?: string }\n): ImaController {\n let adPlaying = false;\n let originalMutedState = false;\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n const licenseKey = options?.licenseKey;\n\n let adVideoElement: HTMLVideoElement | undefined;\n let adHls: Hls | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let currentAd: VastAd | undefined;\n let sessionId: string | undefined;\n\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error in event listener for ${event}:`, error);\n }\n }\n }\n\n function generateSessionId(): string {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n\n function fireTrackingPixels(urls: string[]): void {\n if (!urls || urls.length === 0) return;\n\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n\n // Add session_id if available\n if (sessionId) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}session_id=${sessionId}`;\n }\n\n // Add license_key if available\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}license_key=${licenseKey}`;\n }\n\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n\n function parseVastXml(xmlString: string): VastAd | null {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\"[HlsAdPlayer] XML parsing error:\", parserError.textContent);\n return null;\n }\n\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return null;\n }\n\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n\n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration =\n parseInt(durationParts[0] || \"0\", 10) * 3600 +\n parseInt(durationParts[1] || \"0\", 10) * 60 +\n parseInt(durationParts[2] || \"0\", 10);\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n mediaFileElements.forEach((mf) => {\n const type = mf.getAttribute(\"type\") || \"\";\n if (type === \"application/x-mpegURL\" || type.includes(\"m3u8\")) {\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : undefined;\n\n mediaFiles.push({\n url: mf.textContent?.trim() || \"\",\n type,\n width: parseInt(mf.getAttribute(\"width\") || \"1920\", 10),\n height: parseInt(mf.getAttribute(\"height\") || \"1080\", 10),\n bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : undefined,\n });\n }\n });\n\n if (mediaFiles.length === 0) {\n console.warn(\"[HlsAdPlayer] No HLS media files found in VAST XML\");\n return null;\n }\n\n const trackingUrls: VastTrackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: [],\n };\n\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event as keyof VastTrackingUrls;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n\n const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough,\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return null;\n }\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n return video;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement || !currentAd) return;\n\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n\n const progress = adVideoElement.currentTime / currentAd.duration;\n\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n\n handleAdComplete();\n });\n\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement!.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement!.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement!.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n\n function handleAdComplete(): void {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n contentVideo.muted = originalMutedState;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {});\n console.log(\"[HlsAdPlayer] Content resumed (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content unmuted (Live mode)\");\n }\n\n emit(\"content_resume\");\n emit(\"all_ads_completed\");\n }\n\n function handleAdError(): void {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n contentVideo.muted = originalMutedState;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n if (!options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n contentVideo.play().catch(() => {});\n }\n }\n\n emit(\"ad_error\");\n }\n\n return {\n initialize() {\n console.log(\"[HlsAdPlayer] Initializing\");\n\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"2\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n\n async requestAds(vastTagUrl: string) {\n console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n\n if (adPlaying) {\n console.warn(\"[HlsAdPlayer] Cannot request new ads while an ad is playing\");\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n\n try {\n sessionId = generateSessionId();\n\n const response = await fetch(vastTagUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n\n const vastXml = await response.text();\n console.log(\"[HlsAdPlayer] VAST XML received\");\n\n const ad = parseVastXml(vastXml);\n if (!ad) {\n throw new Error(\"Failed to parse VAST XML or no ads available\");\n }\n\n currentAd = ad;\n console.log(`[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`);\n\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n\n async play() {\n if (!currentAd) {\n console.warn(\"[HlsAdPlayer] Cannot play: No ad loaded\");\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n\n console.log(\"[HlsAdPlayer] Starting ad playback\");\n\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.pause();\n console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n }\n\n contentVideo.muted = true;\n adPlaying = true;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n\n emit(\"content_pause\");\n\n const mediaFile = currentAd.mediaFiles[0];\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n\n console.log(`[HlsAdPlayer] Loading ad from: ${mediaFile.url}`);\n\n if (Hls.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n\n adHls = new Hls({\n enableWorker: true,\n lowLatencyMode: false,\n });\n\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n\n adHls.on(Hls.Events.MANIFEST_PARSED, () => {\n console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n adVideoElement!.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n });\n\n adHls.on(Hls.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(\"HLS not supported\");\n }\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n contentVideo.muted = originalMutedState;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {});\n }\n\n currentAd = undefined;\n },\n\n destroy() {\n console.log(\"[HlsAdPlayer] Destroying\");\n adPlaying = false;\n contentVideo.muted = originalMutedState;\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n\n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n\n updateOriginalMutedState(muted: boolean) {\n originalMutedState = muted;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\n\n setAdVolume(volume: number) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n };\n}\n\n"],"mappings":"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","names":["Hls"]}
|
|
1
|
+
{"version":3,"sources":["../../src/sdk/hlsAdPlayer.ts"],"sourcesContent":["import type { ImaController } from \"../types\";\nimport Hls from \"hls.js\";\n\ninterface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\ninterface VastTrackingUrls {\n impression: string[];\n start: string[];\n firstQuartile: string[];\n midpoint: string[];\n thirdQuartile: string[];\n complete: string[];\n mute: string[];\n unmute: string[];\n pause: string[];\n resume: string[];\n fullscreen: string[];\n exitFullscreen: string[];\n skip: string[];\n error: string[];\n}\n\ninterface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\nexport function createHlsAdPlayer(\n contentVideo: HTMLVideoElement,\n options?: {\n continueLiveStreamDuringAds?: boolean;\n licenseKey?: string;\n mainHlsInstance?: Hls;\n }\n): ImaController {\n let adPlaying = false;\n let originalMutedState = false;\n const listeners = new Map<string, Set<(payload?: any) => void>>();\n const licenseKey = options?.licenseKey;\n const mainHlsInstance = options?.mainHlsInstance;\n\n let adVideoElement: HTMLVideoElement | undefined;\n let adHls: Hls | undefined;\n let adContainerEl: HTMLDivElement | undefined;\n let currentAd: VastAd | undefined;\n let sessionId: string | undefined;\n\n let trackingFired = {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n function emit(event: string, payload?: any): void {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of Array.from(set)) {\n try {\n fn(payload);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error in event listener for ${event}:`, error);\n }\n }\n }\n\n function generateSessionId(): string {\n return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }\n\n function fireTrackingPixels(urls: string[]): void {\n if (!urls || urls.length === 0) return;\n\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n\n if (sessionId) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}session_id=${sessionId}`;\n }\n\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}license_key=${licenseKey}`;\n }\n\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);\n }\n });\n }\n\n function getMainStreamQuality(): { width: number; height: number; bitrate: number } | null {\n if (!mainHlsInstance || !mainHlsInstance.levels) {\n return null;\n }\n\n const currentLevel = mainHlsInstance.currentLevel;\n if (currentLevel === -1 || !mainHlsInstance.levels[currentLevel]) {\n const autoLevel = mainHlsInstance.loadLevel;\n if (autoLevel !== -1 && mainHlsInstance.levels[autoLevel]) {\n const level = mainHlsInstance.levels[autoLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n return null;\n }\n\n const level = mainHlsInstance.levels[currentLevel];\n return {\n width: level.width || 1920,\n height: level.height || 1080,\n bitrate: level.bitrate || 5000000,\n };\n }\n\n function selectBestMediaFile(mediaFiles: VastMediaFile[]): VastMediaFile {\n if (mediaFiles.length === 0) {\n throw new Error(\"No media files available\");\n }\n\n const firstFile = mediaFiles[0];\n if (!firstFile) {\n throw new Error(\"No media files available\");\n }\n\n if (mediaFiles.length === 1) {\n return firstFile;\n }\n\n const mainQuality = getMainStreamQuality();\n if (!mainQuality) {\n console.log(\"[HlsAdPlayer] No main stream quality info, using first media file\");\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Main stream quality:\", mainQuality);\n\n const scoredFiles = mediaFiles.map((file) => {\n const widthDiff = Math.abs(file.width - mainQuality.width);\n const heightDiff = Math.abs(file.height - mainQuality.height);\n const resolutionDiff = widthDiff + heightDiff;\n\n const fileBitrate = (file.bitrate || 5000) * 1000;\n const bitrateDiff = Math.abs(fileBitrate - mainQuality.bitrate);\n\n const score = resolutionDiff * 2 + bitrateDiff / 1000;\n\n return { file, score, resolutionDiff, bitrateDiff };\n });\n\n scoredFiles.sort((a, b) => a.score - b.score);\n\n const bestMatch = scoredFiles[0];\n if (!bestMatch) {\n console.log(\"[HlsAdPlayer] No best match found, using first media file\");\n return firstFile;\n }\n\n console.log(\"[HlsAdPlayer] Selected media file:\", {\n url: bestMatch.file.url,\n resolution: `${bestMatch.file.width}x${bestMatch.file.height}`,\n bitrate: bestMatch.file.bitrate,\n score: bestMatch.score,\n resolutionDiff: bestMatch.resolutionDiff,\n bitrateDiff: bestMatch.bitrateDiff,\n });\n\n return bestMatch.file;\n }\n\n function parseVastXml(xmlString: string): VastAd | null {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\"[HlsAdPlayer] XML parsing error:\", parserError.textContent);\n return null;\n }\n\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(\"[HlsAdPlayer] No Ad element found in VAST XML\");\n return null;\n }\n\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n\n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration =\n parseInt(durationParts[0] || \"0\", 10) * 3600 +\n parseInt(durationParts[1] || \"0\", 10) * 60 +\n parseInt(durationParts[2] || \"0\", 10);\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n mediaFileElements.forEach((mf) => {\n const type = mf.getAttribute(\"type\") || \"\";\n if (type === \"application/x-mpegURL\" || type.includes(\"m3u8\")) {\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : undefined;\n\n mediaFiles.push({\n url: mf.textContent?.trim() || \"\",\n type,\n width: parseInt(mf.getAttribute(\"width\") || \"1920\", 10),\n height: parseInt(mf.getAttribute(\"height\") || \"1080\", 10),\n bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : undefined,\n });\n }\n });\n\n if (mediaFiles.length === 0) {\n console.warn(\"[HlsAdPlayer] No HLS media files found in VAST XML\");\n return null;\n }\n\n const trackingUrls: VastTrackingUrls = {\n impression: [],\n start: [],\n firstQuartile: [],\n midpoint: [],\n thirdQuartile: [],\n complete: [],\n mute: [],\n unmute: [],\n pause: [],\n resume: [],\n fullscreen: [],\n exitFullscreen: [],\n skip: [],\n error: [],\n };\n\n xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\n });\n\n xmlDoc.querySelectorAll(\"Tracking\").forEach((el) => {\n const event = el.getAttribute(\"event\");\n const url = el.textContent?.trim();\n if (event && url) {\n const eventKey = event as keyof VastTrackingUrls;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n\n const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough,\n };\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error parsing VAST XML:\", error);\n return null;\n }\n }\n\n function createAdVideoElement(): HTMLVideoElement {\n const video = document.createElement(\"video\");\n video.style.position = \"absolute\";\n video.style.left = \"0\";\n video.style.top = \"0\";\n video.style.width = \"100%\";\n video.style.height = \"100%\";\n video.style.objectFit = \"contain\";\n video.style.backgroundColor = \"#000\";\n video.playsInline = true;\n video.muted = false;\n return video;\n }\n\n function setupAdEventListeners(): void {\n if (!adVideoElement || !currentAd) return;\n\n adVideoElement.addEventListener(\"timeupdate\", () => {\n if (!currentAd || !adVideoElement) return;\n\n const progress = adVideoElement.currentTime / currentAd.duration;\n\n if (progress >= 0.25 && !trackingFired.firstQuartile) {\n trackingFired.firstQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.firstQuartile);\n }\n\n if (progress >= 0.5 && !trackingFired.midpoint) {\n trackingFired.midpoint = true;\n fireTrackingPixels(currentAd.trackingUrls.midpoint);\n }\n\n if (progress >= 0.75 && !trackingFired.thirdQuartile) {\n trackingFired.thirdQuartile = true;\n fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);\n }\n });\n\n adVideoElement.addEventListener(\"playing\", () => {\n if (!currentAd || trackingFired.start) return;\n trackingFired.start = true;\n fireTrackingPixels(currentAd.trackingUrls.start);\n console.log(\"[HlsAdPlayer] Ad started playing\");\n });\n\n adVideoElement.addEventListener(\"ended\", () => {\n if (!currentAd || trackingFired.complete) return;\n trackingFired.complete = true;\n fireTrackingPixels(currentAd.trackingUrls.complete);\n console.log(\"[HlsAdPlayer] Ad completed\");\n\n handleAdComplete();\n });\n\n adVideoElement.addEventListener(\"error\", (e) => {\n console.error(\"[HlsAdPlayer] Ad video error:\", e);\n if (currentAd) {\n fireTrackingPixels(currentAd.trackingUrls.error);\n }\n handleAdError();\n });\n\n adVideoElement.addEventListener(\"volumechange\", () => {\n if (!currentAd) return;\n if (adVideoElement!.muted) {\n fireTrackingPixels(currentAd.trackingUrls.mute);\n } else {\n fireTrackingPixels(currentAd.trackingUrls.unmute);\n }\n });\n\n adVideoElement.addEventListener(\"pause\", () => {\n if (currentAd && !adVideoElement!.ended) {\n fireTrackingPixels(currentAd.trackingUrls.pause);\n }\n });\n\n adVideoElement.addEventListener(\"play\", () => {\n if (currentAd && adVideoElement!.currentTime > 0) {\n fireTrackingPixels(currentAd.trackingUrls.resume);\n }\n });\n }\n\n function handleAdComplete(): void {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n contentVideo.muted = originalMutedState;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {});\n console.log(\"[HlsAdPlayer] Content resumed (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content unmuted (Live mode)\");\n }\n\n emit(\"content_resume\");\n emit(\"all_ads_completed\");\n }\n\n function handleAdError(): void {\n console.log(\"[HlsAdPlayer] Handling ad error\");\n adPlaying = false;\n contentVideo.muted = originalMutedState;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n if (!options?.continueLiveStreamDuringAds) {\n if (contentVideo.paused) {\n contentVideo.play().catch(() => {});\n }\n }\n\n emit(\"ad_error\");\n }\n\n return {\n initialize() {\n console.log(\"[HlsAdPlayer] Initializing\");\n\n if (!adContainerEl) {\n const container = document.createElement(\"div\");\n container.style.position = \"absolute\";\n container.style.left = \"0\";\n container.style.top = \"0\";\n container.style.right = \"0\";\n container.style.bottom = \"0\";\n container.style.display = \"none\";\n container.style.alignItems = \"center\";\n container.style.justifyContent = \"center\";\n container.style.pointerEvents = \"none\";\n container.style.zIndex = \"2\";\n container.style.backgroundColor = \"#000\";\n\n contentVideo.parentElement?.appendChild(container);\n adContainerEl = container;\n }\n },\n\n async requestAds(vastTagUrl: string) {\n console.log(\"[HlsAdPlayer] Requesting ads:\", vastTagUrl);\n\n if (adPlaying) {\n console.warn(\"[HlsAdPlayer] Cannot request new ads while an ad is playing\");\n return Promise.reject(new Error(\"Ad already playing\"));\n }\n\n try {\n sessionId = generateSessionId();\n\n const response = await fetch(vastTagUrl);\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n\n const vastXml = await response.text();\n console.log(\"[HlsAdPlayer] VAST XML received\");\n\n const ad = parseVastXml(vastXml);\n if (!ad) {\n throw new Error(\"Failed to parse VAST XML or no ads available\");\n }\n\n currentAd = ad;\n console.log(`[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`);\n\n fireTrackingPixels(ad.trackingUrls.impression);\n trackingFired.impression = true;\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error requesting ads:\", error);\n emit(\"ad_error\");\n return Promise.reject(error);\n }\n },\n\n async play() {\n if (!currentAd) {\n console.warn(\"[HlsAdPlayer] Cannot play: No ad loaded\");\n return Promise.reject(new Error(\"No ad loaded\"));\n }\n\n console.log(\"[HlsAdPlayer] Starting ad playback\");\n\n try {\n if (!adVideoElement) {\n adVideoElement = createAdVideoElement();\n adContainerEl?.appendChild(adVideoElement);\n setupAdEventListeners();\n }\n\n trackingFired = {\n impression: trackingFired.impression,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.pause();\n console.log(\"[HlsAdPlayer] Content paused (VOD mode)\");\n } else {\n console.log(\"[HlsAdPlayer] Content continues (Live mode)\");\n }\n\n contentVideo.muted = true;\n adPlaying = true;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"flex\";\n adContainerEl.style.pointerEvents = \"auto\";\n }\n\n emit(\"content_pause\");\n\n const mediaFile = selectBestMediaFile(currentAd.mediaFiles);\n if (!mediaFile) {\n throw new Error(\"No media file available for ad\");\n }\n\n console.log(`[HlsAdPlayer] Loading ad from: ${mediaFile.url}`);\n\n if (Hls.isSupported()) {\n if (adHls) {\n adHls.destroy();\n }\n\n adHls = new Hls({\n enableWorker: true,\n lowLatencyMode: false,\n });\n\n adHls.loadSource(mediaFile.url);\n adHls.attachMedia(adVideoElement);\n\n adHls.on(Hls.Events.MANIFEST_PARSED, () => {\n console.log(\"[HlsAdPlayer] HLS manifest parsed, starting playback\");\n adVideoElement!.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n });\n\n adHls.on(Hls.Events.ERROR, (event, data) => {\n console.error(\"[HlsAdPlayer] HLS error:\", data);\n if (data.fatal) {\n handleAdError();\n }\n });\n } else if (adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")) {\n adVideoElement.src = mediaFile.url;\n adVideoElement.play().catch((error) => {\n console.error(\"[HlsAdPlayer] Error starting ad playback:\", error);\n handleAdError();\n });\n } else {\n throw new Error(\"HLS not supported\");\n }\n\n return Promise.resolve();\n } catch (error) {\n console.error(\"[HlsAdPlayer] Error playing ad:\", error);\n handleAdError();\n return Promise.reject(error);\n }\n },\n\n async stop() {\n console.log(\"[HlsAdPlayer] Stopping ad\");\n adPlaying = false;\n contentVideo.muted = originalMutedState;\n\n if (adContainerEl) {\n adContainerEl.style.display = \"none\";\n adContainerEl.style.pointerEvents = \"none\";\n }\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n }\n\n if (!options?.continueLiveStreamDuringAds) {\n contentVideo.play().catch(() => {});\n }\n\n currentAd = undefined;\n },\n\n destroy() {\n console.log(\"[HlsAdPlayer] Destroying\");\n adPlaying = false;\n contentVideo.muted = originalMutedState;\n\n if (adHls) {\n adHls.destroy();\n adHls = undefined;\n }\n\n if (adVideoElement) {\n adVideoElement.pause();\n adVideoElement.src = \"\";\n adVideoElement.remove();\n adVideoElement = undefined;\n }\n\n if (adContainerEl?.parentElement) {\n adContainerEl.parentElement.removeChild(adContainerEl);\n }\n\n adContainerEl = undefined;\n currentAd = undefined;\n listeners.clear();\n },\n\n isAdPlaying() {\n return adPlaying;\n },\n\n resize(width: number, height: number) {\n console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);\n\n if (adContainerEl) {\n adContainerEl.style.width = `${width}px`;\n adContainerEl.style.height = `${height}px`;\n }\n\n if (adVideoElement) {\n adVideoElement.style.width = `${width}px`;\n adVideoElement.style.height = `${height}px`;\n }\n },\n\n on(event: string, listener: (payload?: any) => void) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(listener);\n },\n\n off(event: string, listener: (payload?: any) => void) {\n listeners.get(event)?.delete(listener);\n },\n\n updateOriginalMutedState(muted: boolean) {\n originalMutedState = muted;\n },\n\n getOriginalMutedState() {\n return originalMutedState;\n },\n\n setAdVolume(volume: number) {\n if (adVideoElement && adPlaying) {\n adVideoElement.volume = Math.max(0, Math.min(1, volume));\n }\n },\n\n getAdVolume(): number {\n if (adVideoElement && adPlaying) {\n return adVideoElement.volume;\n }\n return 1;\n },\n };\n}\n\n"],"mappings":"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","names":["level","_a","Hls"]}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { I as ImaController } from '../types-mVgmKmzM.cjs';
|
|
2
|
+
import Hls from 'hls.js';
|
|
2
3
|
|
|
3
4
|
declare function createHlsAdPlayer(contentVideo: HTMLVideoElement, options?: {
|
|
4
5
|
continueLiveStreamDuringAds?: boolean;
|
|
5
6
|
licenseKey?: string;
|
|
7
|
+
mainHlsInstance?: Hls;
|
|
6
8
|
}): ImaController;
|
|
7
9
|
|
|
8
10
|
export { createHlsAdPlayer };
|
package/lib/sdk/ima.cjs
CHANGED
|
@@ -34,7 +34,8 @@ function getWebKitVersion(ua) {
|
|
|
34
34
|
return match && match[1] ? parseInt(match[1], 10) : 0;
|
|
35
35
|
}
|
|
36
36
|
function getPlatform() {
|
|
37
|
-
|
|
37
|
+
var _a;
|
|
38
|
+
if ("userAgentData" in navigator && ((_a = navigator.userAgentData) == null ? void 0 : _a.platform)) {
|
|
38
39
|
return navigator.userAgentData.platform;
|
|
39
40
|
}
|
|
40
41
|
const ua = navigator.userAgent;
|
|
@@ -173,6 +174,7 @@ function createImaController(video, options) {
|
|
|
173
174
|
}
|
|
174
175
|
}
|
|
175
176
|
function ensureImaLoaded() {
|
|
177
|
+
var _a, _b, _c;
|
|
176
178
|
if (!supportsGoogleIMA()) {
|
|
177
179
|
console.warn(
|
|
178
180
|
"[IMA] Google IMA SDK is not supported on this browser. Please use HLS ad player instead."
|
|
@@ -183,7 +185,7 @@ function createImaController(video, options) {
|
|
|
183
185
|
}
|
|
184
186
|
try {
|
|
185
187
|
const frameEl = window.frameElement;
|
|
186
|
-
const sandboxAttr = frameEl
|
|
188
|
+
const sandboxAttr = ((_a = frameEl == null ? void 0 : frameEl.getAttribute) == null ? void 0 : _a.call(frameEl, "sandbox")) || "";
|
|
187
189
|
if (sandboxAttr) {
|
|
188
190
|
const tokens = new Set(
|
|
189
191
|
sandboxAttr.split(/\s+/).map((t) => t.trim()).filter((t) => t.length > 0)
|
|
@@ -197,13 +199,13 @@ function createImaController(video, options) {
|
|
|
197
199
|
}
|
|
198
200
|
} catch {
|
|
199
201
|
}
|
|
200
|
-
if (typeof window !== "undefined" && window.google
|
|
202
|
+
if (typeof window !== "undefined" && ((_b = window.google) == null ? void 0 : _b.ima))
|
|
201
203
|
return Promise.resolve();
|
|
202
204
|
const existing = document.querySelector(
|
|
203
205
|
'script[data-ima="true"]'
|
|
204
206
|
);
|
|
205
207
|
if (existing) {
|
|
206
|
-
if (window.google
|
|
208
|
+
if ((_c = window.google) == null ? void 0 : _c.ima) {
|
|
207
209
|
return Promise.resolve();
|
|
208
210
|
}
|
|
209
211
|
return new Promise((resolve, reject) => {
|
|
@@ -261,6 +263,7 @@ function createImaController(video, options) {
|
|
|
261
263
|
return {
|
|
262
264
|
initialize() {
|
|
263
265
|
ensureImaLoaded().then(() => {
|
|
266
|
+
var _a, _b;
|
|
264
267
|
const google = window.google;
|
|
265
268
|
if (!adDisplayContainer) {
|
|
266
269
|
const container = document.createElement("div");
|
|
@@ -274,14 +277,14 @@ function createImaController(video, options) {
|
|
|
274
277
|
container.style.justifyContent = "center";
|
|
275
278
|
container.style.pointerEvents = "none";
|
|
276
279
|
container.style.zIndex = "2";
|
|
277
|
-
video.parentElement
|
|
280
|
+
(_a = video.parentElement) == null ? void 0 : _a.appendChild(container);
|
|
278
281
|
adContainerEl = container;
|
|
279
282
|
adDisplayContainer = new google.ima.AdDisplayContainer(
|
|
280
283
|
container,
|
|
281
284
|
video
|
|
282
285
|
);
|
|
283
286
|
try {
|
|
284
|
-
adDisplayContainer.initialize
|
|
287
|
+
(_b = adDisplayContainer.initialize) == null ? void 0 : _b.call(adDisplayContainer);
|
|
285
288
|
} catch {
|
|
286
289
|
}
|
|
287
290
|
}
|
|
@@ -366,6 +369,7 @@ function createImaController(video, options) {
|
|
|
366
369
|
adsManager.addEventListener(
|
|
367
370
|
AdErrorEvent.AD_ERROR,
|
|
368
371
|
(errorEvent) => {
|
|
372
|
+
var _a;
|
|
369
373
|
console.error("[IMA] Ad error:", errorEvent.getError());
|
|
370
374
|
destroyAdsManager();
|
|
371
375
|
adPlaying = false;
|
|
@@ -396,10 +400,10 @@ function createImaController(video, options) {
|
|
|
396
400
|
"[IMA] Max retries reached, emitting ad_error"
|
|
397
401
|
);
|
|
398
402
|
emit("ad_error");
|
|
399
|
-
if (!options
|
|
403
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
400
404
|
if (video.paused) {
|
|
401
405
|
console.log("[IMA] Resuming paused video after ad error");
|
|
402
|
-
video.play()
|
|
406
|
+
(_a = video.play()) == null ? void 0 : _a.catch(() => {
|
|
403
407
|
});
|
|
404
408
|
}
|
|
405
409
|
}
|
|
@@ -410,7 +414,7 @@ function createImaController(video, options) {
|
|
|
410
414
|
AdEvent.CONTENT_PAUSE_REQUESTED,
|
|
411
415
|
() => {
|
|
412
416
|
console.log("[IMA] Content pause requested");
|
|
413
|
-
if (!options
|
|
417
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
414
418
|
video.pause();
|
|
415
419
|
console.log("[IMA] Video paused (VOD mode)");
|
|
416
420
|
} else {
|
|
@@ -436,6 +440,7 @@ function createImaController(video, options) {
|
|
|
436
440
|
adsManager.addEventListener(
|
|
437
441
|
AdEvent.CONTENT_RESUME_REQUESTED,
|
|
438
442
|
() => {
|
|
443
|
+
var _a;
|
|
439
444
|
console.log("[IMA] Content resume requested");
|
|
440
445
|
adPlaying = false;
|
|
441
446
|
video.muted = originalMutedState;
|
|
@@ -446,8 +451,8 @@ function createImaController(video, options) {
|
|
|
446
451
|
"[IMA] Ad container hidden - pointer events disabled"
|
|
447
452
|
);
|
|
448
453
|
}
|
|
449
|
-
if (!options
|
|
450
|
-
video.play()
|
|
454
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
455
|
+
(_a = video.play()) == null ? void 0 : _a.catch(() => {
|
|
451
456
|
});
|
|
452
457
|
console.log("[IMA] Video resumed (VOD mode)");
|
|
453
458
|
} else {
|
|
@@ -469,7 +474,7 @@ function createImaController(video, options) {
|
|
|
469
474
|
"[IMA] Ad container hidden after all ads completed"
|
|
470
475
|
);
|
|
471
476
|
}
|
|
472
|
-
if (!options
|
|
477
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
473
478
|
video.play().catch(() => {
|
|
474
479
|
});
|
|
475
480
|
console.log(
|
|
@@ -497,7 +502,7 @@ function createImaController(video, options) {
|
|
|
497
502
|
adContainerEl.style.display = "none";
|
|
498
503
|
console.log("[IMA] Ad container hidden after setup error");
|
|
499
504
|
}
|
|
500
|
-
if (!options
|
|
505
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
501
506
|
if (video.paused) {
|
|
502
507
|
console.log("[IMA] Resuming paused video after setup error");
|
|
503
508
|
video.play().catch(() => {
|
|
@@ -525,7 +530,7 @@ function createImaController(video, options) {
|
|
|
525
530
|
adContainerEl.style.display = "none";
|
|
526
531
|
console.log("[IMA] Ad container hidden after loader error");
|
|
527
532
|
}
|
|
528
|
-
if (!options
|
|
533
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
529
534
|
if (video.paused) {
|
|
530
535
|
console.log("[IMA] Resuming paused video after loader error");
|
|
531
536
|
video.play().catch(() => {
|
|
@@ -547,14 +552,15 @@ function createImaController(video, options) {
|
|
|
547
552
|
return adsLoadedPromise;
|
|
548
553
|
} catch (error) {
|
|
549
554
|
console.error("[IMA] Failed to request ads:", error);
|
|
550
|
-
currentReject
|
|
555
|
+
currentReject == null ? void 0 : currentReject(error);
|
|
551
556
|
adsLoadedReject = void 0;
|
|
552
557
|
adsLoadedResolve = void 0;
|
|
553
558
|
return Promise.reject(error);
|
|
554
559
|
}
|
|
555
560
|
},
|
|
556
561
|
async play() {
|
|
557
|
-
|
|
562
|
+
var _a, _b;
|
|
563
|
+
if (!((_a = window.google) == null ? void 0 : _a.ima) || !adDisplayContainer) {
|
|
558
564
|
console.warn(
|
|
559
565
|
"[IMA] Cannot play ad: IMA SDK or ad container not available"
|
|
560
566
|
);
|
|
@@ -576,14 +582,15 @@ function createImaController(video, options) {
|
|
|
576
582
|
} catch (error) {
|
|
577
583
|
console.error("[IMA] Error starting ad playback:", error);
|
|
578
584
|
adPlaying = false;
|
|
579
|
-
if (!options
|
|
580
|
-
video.play()
|
|
585
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
586
|
+
(_b = video.play()) == null ? void 0 : _b.catch(() => {
|
|
581
587
|
});
|
|
582
588
|
}
|
|
583
589
|
return Promise.reject(error);
|
|
584
590
|
}
|
|
585
591
|
},
|
|
586
592
|
async stop() {
|
|
593
|
+
var _a;
|
|
587
594
|
adPlaying = false;
|
|
588
595
|
video.muted = originalMutedState;
|
|
589
596
|
if (adContainerEl) {
|
|
@@ -592,11 +599,11 @@ function createImaController(video, options) {
|
|
|
592
599
|
console.log("[IMA] Ad container hidden after stop");
|
|
593
600
|
}
|
|
594
601
|
try {
|
|
595
|
-
adsManager
|
|
602
|
+
(_a = adsManager == null ? void 0 : adsManager.stop) == null ? void 0 : _a.call(adsManager);
|
|
596
603
|
} catch {
|
|
597
604
|
}
|
|
598
605
|
destroyAdsManager();
|
|
599
|
-
if (!options
|
|
606
|
+
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
600
607
|
video.play().catch(() => {
|
|
601
608
|
});
|
|
602
609
|
console.log("[IMA] Video resumed after stop (VOD mode)");
|
|
@@ -605,6 +612,7 @@ function createImaController(video, options) {
|
|
|
605
612
|
}
|
|
606
613
|
},
|
|
607
614
|
destroy() {
|
|
615
|
+
var _a;
|
|
608
616
|
destroyAdsManager();
|
|
609
617
|
adPlaying = false;
|
|
610
618
|
video.muted = originalMutedState;
|
|
@@ -613,10 +621,10 @@ function createImaController(video, options) {
|
|
|
613
621
|
adContainerEl.style.display = "none";
|
|
614
622
|
}
|
|
615
623
|
try {
|
|
616
|
-
adsLoader
|
|
624
|
+
(_a = adsLoader == null ? void 0 : adsLoader.destroy) == null ? void 0 : _a.call(adsLoader);
|
|
617
625
|
} catch {
|
|
618
626
|
}
|
|
619
|
-
if (adContainerEl
|
|
627
|
+
if (adContainerEl == null ? void 0 : adContainerEl.parentElement) {
|
|
620
628
|
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
621
629
|
}
|
|
622
630
|
adContainerEl = void 0;
|
|
@@ -627,7 +635,8 @@ function createImaController(video, options) {
|
|
|
627
635
|
return adPlaying;
|
|
628
636
|
},
|
|
629
637
|
resize(width, height) {
|
|
630
|
-
|
|
638
|
+
var _a;
|
|
639
|
+
if (!adsManager || !((_a = window.google) == null ? void 0 : _a.ima)) {
|
|
631
640
|
console.warn(
|
|
632
641
|
"[IMA] Cannot resize: No ads manager or IMA SDK available"
|
|
633
642
|
);
|
|
@@ -645,7 +654,8 @@ function createImaController(video, options) {
|
|
|
645
654
|
listeners.get(event).add(listener);
|
|
646
655
|
},
|
|
647
656
|
off(event, listener) {
|
|
648
|
-
|
|
657
|
+
var _a;
|
|
658
|
+
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
649
659
|
},
|
|
650
660
|
updateOriginalMutedState(muted) {
|
|
651
661
|
originalMutedState = muted;
|