stormcloud-video-player 0.2.16 → 0.2.18
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 +387 -56
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +6 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +387 -56
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +266 -23
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +5 -1
- package/lib/players/HlsPlayer.cjs +268 -23
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.d.cts +1 -1
- package/lib/players/index.cjs +268 -23
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +76 -12
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.d.cts +1 -1
- package/lib/sdk/ima.cjs +73 -2
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/sdk/ima.d.cts +1 -1
- package/lib/{types-mVgmKmzM.d.cts → types-J6-Dpcvw.d.cts} +1 -0
- package/lib/ui/StormcloudVideoPlayer.cjs +383 -56
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
- package/lib/utils/tracking.d.cts +1 -1
- package/package.json +1 -1
package/lib/sdk/hlsAdPlayer.cjs
CHANGED
|
@@ -60,7 +60,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
60
60
|
try {
|
|
61
61
|
fn(payload);
|
|
62
62
|
} catch (error) {
|
|
63
|
-
console.warn(
|
|
63
|
+
console.warn(
|
|
64
|
+
`[HlsAdPlayer] Error in event listener for ${event}:`,
|
|
65
|
+
error
|
|
66
|
+
);
|
|
64
67
|
}
|
|
65
68
|
}
|
|
66
69
|
}
|
|
@@ -123,7 +126,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
123
126
|
}
|
|
124
127
|
const mainQuality = getMainStreamQuality();
|
|
125
128
|
if (!mainQuality) {
|
|
126
|
-
console.log(
|
|
129
|
+
console.log(
|
|
130
|
+
"[HlsAdPlayer] No main stream quality info, using first media file"
|
|
131
|
+
);
|
|
127
132
|
return firstFile;
|
|
128
133
|
}
|
|
129
134
|
console.log("[HlsAdPlayer] Main stream quality:", mainQuality);
|
|
@@ -159,7 +164,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
159
164
|
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
|
|
160
165
|
const parserError = xmlDoc.querySelector("parsererror");
|
|
161
166
|
if (parserError) {
|
|
162
|
-
console.error(
|
|
167
|
+
console.error(
|
|
168
|
+
"[HlsAdPlayer] XML parsing error (malformed VAST XML):",
|
|
169
|
+
parserError.textContent
|
|
170
|
+
);
|
|
163
171
|
return null;
|
|
164
172
|
}
|
|
165
173
|
const adElement = xmlDoc.querySelector("Ad");
|
|
@@ -175,17 +183,23 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
175
183
|
const duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
|
|
176
184
|
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
177
185
|
const mediaFiles = [];
|
|
178
|
-
console.log(
|
|
186
|
+
console.log(
|
|
187
|
+
`[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`
|
|
188
|
+
);
|
|
179
189
|
mediaFileElements.forEach((mf, index) => {
|
|
180
190
|
var _a2;
|
|
181
191
|
const type = mf.getAttribute("type") || "";
|
|
182
192
|
const url = ((_a2 = mf.textContent) == null ? void 0 : _a2.trim()) || "";
|
|
183
193
|
const width = mf.getAttribute("width") || "";
|
|
184
194
|
const height = mf.getAttribute("height") || "";
|
|
185
|
-
console.log(
|
|
195
|
+
console.log(
|
|
196
|
+
`[HlsAdPlayer] MediaFile ${index}: type="${type}", url="${url}", width="${width}", height="${height}"`
|
|
197
|
+
);
|
|
186
198
|
if (type === "application/x-mpegURL" || type.includes("m3u8")) {
|
|
187
199
|
if (!url) {
|
|
188
|
-
console.warn(
|
|
200
|
+
console.warn(
|
|
201
|
+
`[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`
|
|
202
|
+
);
|
|
189
203
|
return;
|
|
190
204
|
}
|
|
191
205
|
const bitrateAttr = mf.getAttribute("bitrate");
|
|
@@ -199,12 +213,16 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
199
213
|
});
|
|
200
214
|
console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);
|
|
201
215
|
} else {
|
|
202
|
-
console.log(
|
|
216
|
+
console.log(
|
|
217
|
+
`[HlsAdPlayer] MediaFile ${index} ignored (type="${type}" is not HLS)`
|
|
218
|
+
);
|
|
203
219
|
}
|
|
204
220
|
});
|
|
205
221
|
if (mediaFiles.length === 0) {
|
|
206
222
|
if (isNoAdAvailable) {
|
|
207
|
-
console.warn(
|
|
223
|
+
console.warn(
|
|
224
|
+
"[HlsAdPlayer] No ads available (VAST response indicates no ads)"
|
|
225
|
+
);
|
|
208
226
|
} else {
|
|
209
227
|
console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
|
|
210
228
|
}
|
|
@@ -267,6 +285,10 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
267
285
|
video.style.backgroundColor = "#000";
|
|
268
286
|
video.playsInline = true;
|
|
269
287
|
video.muted = false;
|
|
288
|
+
video.volume = 1;
|
|
289
|
+
console.log(
|
|
290
|
+
`[HlsAdPlayer] Created ad video element with volume ${video.volume}`
|
|
291
|
+
);
|
|
270
292
|
return video;
|
|
271
293
|
}
|
|
272
294
|
function setupAdEventListeners() {
|
|
@@ -326,10 +348,22 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
326
348
|
}
|
|
327
349
|
});
|
|
328
350
|
}
|
|
351
|
+
function setAdPlayingFlag(isPlaying) {
|
|
352
|
+
if (isPlaying) {
|
|
353
|
+
contentVideo.dataset.stormcloudAdPlaying = "true";
|
|
354
|
+
} else {
|
|
355
|
+
delete contentVideo.dataset.stormcloudAdPlaying;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
329
358
|
function handleAdComplete() {
|
|
330
359
|
console.log("[HlsAdPlayer] Handling ad completion");
|
|
331
360
|
adPlaying = false;
|
|
361
|
+
setAdPlayingFlag(false);
|
|
362
|
+
const previousMutedState = contentVideo.muted;
|
|
332
363
|
contentVideo.muted = originalMutedState;
|
|
364
|
+
console.log(
|
|
365
|
+
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
366
|
+
);
|
|
333
367
|
if (adContainerEl) {
|
|
334
368
|
adContainerEl.style.display = "none";
|
|
335
369
|
adContainerEl.style.pointerEvents = "none";
|
|
@@ -347,7 +381,12 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
347
381
|
function handleAdError() {
|
|
348
382
|
console.log("[HlsAdPlayer] Handling ad error");
|
|
349
383
|
adPlaying = false;
|
|
384
|
+
setAdPlayingFlag(false);
|
|
385
|
+
const previousMutedState = contentVideo.muted;
|
|
350
386
|
contentVideo.muted = originalMutedState;
|
|
387
|
+
console.log(
|
|
388
|
+
`[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
389
|
+
);
|
|
351
390
|
if (adContainerEl) {
|
|
352
391
|
adContainerEl.style.display = "none";
|
|
353
392
|
adContainerEl.style.pointerEvents = "none";
|
|
@@ -384,7 +423,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
384
423
|
async requestAds(vastTagUrl) {
|
|
385
424
|
console.log("[HlsAdPlayer] Requesting ads:", vastTagUrl);
|
|
386
425
|
if (adPlaying) {
|
|
387
|
-
console.warn(
|
|
426
|
+
console.warn(
|
|
427
|
+
"[HlsAdPlayer] Cannot request new ads while an ad is playing"
|
|
428
|
+
);
|
|
388
429
|
return Promise.reject(new Error("Ad already playing"));
|
|
389
430
|
}
|
|
390
431
|
try {
|
|
@@ -395,14 +436,20 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
395
436
|
}
|
|
396
437
|
const vastXml = await response.text();
|
|
397
438
|
console.log("[HlsAdPlayer] VAST XML received");
|
|
398
|
-
console.log(
|
|
439
|
+
console.log(
|
|
440
|
+
"[HlsAdPlayer] VAST XML content (first 2000 chars):",
|
|
441
|
+
vastXml.substring(0, 2e3)
|
|
442
|
+
);
|
|
399
443
|
const ad = parseVastXml(vastXml);
|
|
400
444
|
if (!ad) {
|
|
401
445
|
console.warn("[HlsAdPlayer] No ads available from VAST response");
|
|
446
|
+
emit("ad_error");
|
|
402
447
|
return Promise.resolve();
|
|
403
448
|
}
|
|
404
449
|
currentAd = ad;
|
|
405
|
-
console.log(
|
|
450
|
+
console.log(
|
|
451
|
+
`[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`
|
|
452
|
+
);
|
|
406
453
|
fireTrackingPixels(ad.trackingUrls.impression);
|
|
407
454
|
trackingFired.impression = true;
|
|
408
455
|
return Promise.resolve();
|
|
@@ -414,7 +461,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
414
461
|
},
|
|
415
462
|
async play() {
|
|
416
463
|
if (!currentAd) {
|
|
417
|
-
console.warn(
|
|
464
|
+
console.warn(
|
|
465
|
+
"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)"
|
|
466
|
+
);
|
|
418
467
|
return Promise.reject(new Error("No ad loaded"));
|
|
419
468
|
}
|
|
420
469
|
console.log("[HlsAdPlayer] Starting ad playback");
|
|
@@ -432,6 +481,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
432
481
|
thirdQuartile: false,
|
|
433
482
|
complete: false
|
|
434
483
|
};
|
|
484
|
+
const contentVolume = contentVideo.volume;
|
|
435
485
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
436
486
|
contentVideo.pause();
|
|
437
487
|
console.log("[HlsAdPlayer] Content paused (VOD mode)");
|
|
@@ -440,6 +490,15 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
440
490
|
}
|
|
441
491
|
contentVideo.muted = true;
|
|
442
492
|
adPlaying = true;
|
|
493
|
+
setAdPlayingFlag(true);
|
|
494
|
+
if (adVideoElement) {
|
|
495
|
+
const adVolume = originalMutedState ? 0 : contentVolume;
|
|
496
|
+
adVideoElement.volume = Math.max(0, Math.min(1, adVolume));
|
|
497
|
+
adVideoElement.muted = false;
|
|
498
|
+
console.log(
|
|
499
|
+
`[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`
|
|
500
|
+
);
|
|
501
|
+
}
|
|
443
502
|
if (adContainerEl) {
|
|
444
503
|
adContainerEl.style.display = "flex";
|
|
445
504
|
adContainerEl.style.pointerEvents = "auto";
|
|
@@ -492,6 +551,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
492
551
|
async stop() {
|
|
493
552
|
console.log("[HlsAdPlayer] Stopping ad");
|
|
494
553
|
adPlaying = false;
|
|
554
|
+
setAdPlayingFlag(false);
|
|
495
555
|
contentVideo.muted = originalMutedState;
|
|
496
556
|
if (adContainerEl) {
|
|
497
557
|
adContainerEl.style.display = "none";
|
|
@@ -514,6 +574,7 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
514
574
|
destroy() {
|
|
515
575
|
console.log("[HlsAdPlayer] Destroying");
|
|
516
576
|
adPlaying = false;
|
|
577
|
+
setAdPlayingFlag(false);
|
|
517
578
|
contentVideo.muted = originalMutedState;
|
|
518
579
|
if (adHls) {
|
|
519
580
|
adHls.destroy();
|
|
@@ -555,6 +616,9 @@ function createHlsAdPlayer(contentVideo, options) {
|
|
|
555
616
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
556
617
|
},
|
|
557
618
|
updateOriginalMutedState(muted) {
|
|
619
|
+
console.log(
|
|
620
|
+
`[HlsAdPlayer] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
621
|
+
);
|
|
558
622
|
originalMutedState = muted;
|
|
559
623
|
},
|
|
560
624
|
getOriginalMutedState() {
|
|
@@ -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?: {\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 // Check for XML parsing errors (malformed XML)\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\"[HlsAdPlayer] XML parsing error (malformed VAST XML):\", 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 // Check if this is an \"empty\" VAST response (no ads available)\n const isNoAdAvailable = \n adId === \"empty\" || \n title.toLowerCase().includes(\"no ad available\") ||\n title.toLowerCase() === \"no ad available\";\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 console.log(`[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`);\n\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n \n console.log(`[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`);\n\n if (type === \"application/x-mpegURL\" || type.includes(\"m3u8\")) {\n if (!url) {\n console.warn(`[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`);\n return;\n }\n\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : undefined;\n\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : undefined,\n });\n \n console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);\n } else {\n console.log(`[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not HLS)`);\n }\n });\n\n // No ads available - return null without error (this is a warning case, not an error)\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\"[HlsAdPlayer] No ads available (VAST response indicates no ads)\");\n } else {\n console.warn(\"[HlsAdPlayer] No HLS media files found in VAST XML\");\n }\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 console.log(\"[HlsAdPlayer] VAST XML content (first 2000 chars):\", vastXml.substring(0, 2000));\n\n const ad = parseVastXml(vastXml);\n if (!ad) {\n // parseVastXml returns null for two cases:\n // 1. XML parsing error (already logged as error)\n // 2. No ads available (already logged as warning)\n // In both cases, we should resolve (not reject) to indicate the request completed,\n // but no ads are available. The caller can check if currentAd is set.\n console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n return Promise.resolve();\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 // This catch block handles network errors, fetch failures, etc.\n // These are actual errors that should be logged and propagated\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 (no ads available)\");\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,iBAAgB;AAoCT,SAAS,kBACd,cACA,SAKe;AACf,MAAI,YAAY;AAChB,MAAI,qBAAqB;AACzB,QAAM,YAAY,oBAAI,IAA0C;AAChE,QAAM,aAAa,mCAAS;AAC5B,QAAM,kBAAkB,mCAAS;AAEjC,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI,gBAAgB;AAAA,IAClB,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,eAAe;AAAA,IACf,UAAU;AAAA,IACV,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAEA,WAAS,KAAK,OAAe,SAAqB;AAChD,UAAM,MAAM,UAAU,IAAI,KAAK;AAC/B,QAAI,CAAC,IAAK;AACV,eAAW,MAAM,MAAM,KAAK,GAAG,GAAG;AAChC,UAAI;AACF,WAAG,OAAO;AAAA,MACZ,SAAS,OAAO;AACd,gBAAQ,KAAK,6CAA6C,KAAK,KAAK,KAAK;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AAEA,WAAS,oBAA4B;AACnC,WAAO,WAAW,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,GAAG,CAAC,CAAC;AAAA,EACzE;AAEA,WAAS,mBAAmB,MAAsB;AAChD,QAAI,CAAC,QAAQ,KAAK,WAAW,EAAG;AAEhC,SAAK,QAAQ,CAAC,QAAQ;AACpB,UAAI;AACF,YAAI,cAAc;AAElB,YAAI,WAAW;AACb,wBAAc,GAAG,WAAW,GAAG,YAAY,SAAS,GAAG,IAAI,MAAM,GAAG,cAAc,SAAS;AAAA,QAC7F;AAEA,YAAI,YAAY;AACd,wBAAc,GAAG,WAAW,GAAG,YAAY,SAAS,GAAG,IAAI,MAAM,GAAG,eAAe,UAAU;AAAA,QAC/F;AAEA,cAAM,MAAM,IAAI,MAAM,GAAG,CAAC;AAC1B,YAAI,MAAM;AACV,gBAAQ,IAAI,uCAAuC,WAAW,EAAE;AAAA,MAClE,SAAS,OAAO;AACd,gBAAQ,KAAK,8CAA8C,KAAK;AAAA,MAClE;AAAA,IACF,CAAC;AAAA,EACH;AAEA,WAAS,uBAAkF;AACzF,QAAI,CAAC,mBAAmB,CAAC,gBAAgB,QAAQ;AAC/C,aAAO;AAAA,IACT;AAEA,UAAM,eAAe,gBAAgB;AACrC,QAAI,iBAAiB,MAAM,CAAC,gBAAgB,OAAO,YAAY,GAAG;AAChE,YAAM,YAAY,gBAAgB;AAClC,UAAI,cAAc,MAAM,gBAAgB,OAAO,SAAS,GAAG;AACzD,cAAMA,SAAQ,gBAAgB,OAAO,SAAS;AAC9C,eAAO;AAAA,UACL,OAAOA,OAAM,SAAS;AAAA,UACtB,QAAQA,OAAM,UAAU;AAAA,UACxB,SAASA,OAAM,WAAW;AAAA,QAC5B;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,UAAM,QAAQ,gBAAgB,OAAO,YAAY;AACjD,WAAO;AAAA,MACL,OAAO,MAAM,SAAS;AAAA,MACtB,QAAQ,MAAM,UAAU;AAAA,MACxB,SAAS,MAAM,WAAW;AAAA,IAC5B;AAAA,EACF;AAEA,WAAS,oBAAoB,YAA4C;AACvE,QAAI,WAAW,WAAW,GAAG;AAC3B,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,UAAM,YAAY,WAAW,CAAC;AAC9B,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,QAAI,WAAW,WAAW,GAAG;AAC3B,aAAO;AAAA,IACT;AAEA,UAAM,cAAc,qBAAqB;AACzC,QAAI,CAAC,aAAa;AAChB,cAAQ,IAAI,mEAAmE;AAC/E,aAAO;AAAA,IACT;AAEA,YAAQ,IAAI,sCAAsC,WAAW;AAE7D,UAAM,cAAc,WAAW,IAAI,CAAC,SAAS;AAC3C,YAAM,YAAY,KAAK,IAAI,KAAK,QAAQ,YAAY,KAAK;AACzD,YAAM,aAAa,KAAK,IAAI,KAAK,SAAS,YAAY,MAAM;AAC5D,YAAM,iBAAiB,YAAY;AAEnC,YAAM,eAAe,KAAK,WAAW,OAAQ;AAC7C,YAAM,cAAc,KAAK,IAAI,cAAc,YAAY,OAAO;AAE9D,YAAM,QAAQ,iBAAiB,IAAI,cAAc;AAEjD,aAAO,EAAE,MAAM,OAAO,gBAAgB,YAAY;AAAA,IACpD,CAAC;AAED,gBAAY,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAE5C,UAAM,YAAY,YAAY,CAAC;AAC/B,QAAI,CAAC,WAAW;AACd,cAAQ,IAAI,2DAA2D;AACvE,aAAO;AAAA,IACT;AAEA,YAAQ,IAAI,sCAAsC;AAAA,MAChD,KAAK,UAAU,KAAK;AAAA,MACpB,YAAY,GAAG,UAAU,KAAK,KAAK,IAAI,UAAU,KAAK,MAAM;AAAA,MAC5D,SAAS,UAAU,KAAK;AAAA,MACxB,OAAO,UAAU;AAAA,MACjB,gBAAgB,UAAU;AAAA,MAC1B,aAAa,UAAU;AAAA,IACzB,CAAC;AAED,WAAO,UAAU;AAAA,EACnB;AAEA,WAAS,aAAa,WAAkC;AA5L1D;AA6LI,QAAI;AACF,YAAM,SAAS,IAAI,UAAU;AAC7B,YAAM,SAAS,OAAO,gBAAgB,WAAW,UAAU;AAG3D,YAAM,cAAc,OAAO,cAAc,aAAa;AACtD,UAAI,aAAa;AACf,gBAAQ,MAAM,yDAAyD,YAAY,WAAW;AAC9F,eAAO;AAAA,MACT;AAEA,YAAM,YAAY,OAAO,cAAc,IAAI;AAC3C,UAAI,CAAC,WAAW;AACd,gBAAQ,KAAK,+CAA+C;AAC5D,eAAO;AAAA,MACT;AAEA,YAAM,OAAO,UAAU,aAAa,IAAI,KAAK;AAC7C,YAAM,UAAQ,YAAO,cAAc,SAAS,MAA9B,mBAAiC,gBAAe;AAG9D,YAAM,kBACJ,SAAS,WACT,MAAM,YAAY,EAAE,SAAS,iBAAiB,KAC9C,MAAM,YAAY,MAAM;AAE1B,YAAM,iBAAe,YAAO,cAAc,UAAU,MAA/B,mBAAkC,gBAAe;AACtE,YAAM,gBAAgB,aAAa,MAAM,GAAG;AAC5C,YAAM,WACJ,SAAS,cAAc,CAAC,KAAK,KAAK,EAAE,IAAI,OACxC,SAAS,cAAc,CAAC,KAAK,KAAK,EAAE,IAAI,KACxC,SAAS,cAAc,CAAC,KAAK,KAAK,EAAE;AAEtC,YAAM,oBAAoB,OAAO,iBAAiB,WAAW;AAC7D,YAAM,aAA8B,CAAC;AAErC,cAAQ,IAAI,uBAAuB,kBAAkB,MAAM,mCAAmC;AAE9F,wBAAkB,QAAQ,CAAC,IAAI,UAAU;AAnO/C,YAAAC;AAoOQ,cAAM,OAAO,GAAG,aAAa,MAAM,KAAK;AACxC,cAAM,QAAMA,MAAA,GAAG,gBAAH,gBAAAA,IAAgB,WAAU;AACtC,cAAM,QAAQ,GAAG,aAAa,OAAO,KAAK;AAC1C,cAAM,SAAS,GAAG,aAAa,QAAQ,KAAK;AAE5C,gBAAQ,IAAI,2BAA2B,KAAK,WAAW,IAAI,WAAW,GAAG,aAAa,KAAK,cAAc,MAAM,GAAG;AAElH,YAAI,SAAS,2BAA2B,KAAK,SAAS,MAAM,GAAG;AAC7D,cAAI,CAAC,KAAK;AACR,oBAAQ,KAAK,2BAA2B,KAAK,6BAA6B;AAC1E;AAAA,UACF;AAEA,gBAAM,cAAc,GAAG,aAAa,SAAS;AAC7C,gBAAM,eAAe,cAAc,SAAS,aAAa,EAAE,IAAI;AAE/D,qBAAW,KAAK;AAAA,YACd;AAAA,YACA;AAAA,YACA,OAAO,SAAS,SAAS,QAAQ,EAAE;AAAA,YACnC,QAAQ,SAAS,UAAU,QAAQ,EAAE;AAAA,YACrC,SAAS,gBAAgB,eAAe,IAAI,eAAe;AAAA,UAC7D,CAAC;AAED,kBAAQ,IAAI,sCAAsC,GAAG,EAAE;AAAA,QACzD,OAAO;AACL,kBAAQ,IAAI,2BAA2B,KAAK,mBAAmB,IAAI,eAAe;AAAA,QACpF;AAAA,MACF,CAAC;AAGD,UAAI,WAAW,WAAW,GAAG;AAC3B,YAAI,iBAAiB;AACnB,kBAAQ,KAAK,iEAAiE;AAAA,QAChF,OAAO;AACL,kBAAQ,KAAK,oDAAoD;AAAA,QACnE;AACA,eAAO;AAAA,MACT;AAEA,YAAM,eAAiC;AAAA,QACrC,YAAY,CAAC;AAAA,QACb,OAAO,CAAC;AAAA,QACR,eAAe,CAAC;AAAA,QAChB,UAAU,CAAC;AAAA,QACX,eAAe,CAAC;AAAA,QAChB,UAAU,CAAC;AAAA,QACX,MAAM,CAAC;AAAA,QACP,QAAQ,CAAC;AAAA,QACT,OAAO,CAAC;AAAA,QACR,QAAQ,CAAC;AAAA,QACT,YAAY,CAAC;AAAA,QACb,gBAAgB,CAAC;AAAA,QACjB,MAAM,CAAC;AAAA,QACP,OAAO,CAAC;AAAA,MACV;AAEA,aAAO,iBAAiB,YAAY,EAAE,QAAQ,CAAC,OAAO;AA7R5D,YAAAA;AA8RQ,cAAM,OAAMA,MAAA,GAAG,gBAAH,gBAAAA,IAAgB;AAC5B,YAAI,IAAK,cAAa,WAAW,KAAK,GAAG;AAAA,MAC3C,CAAC;AAED,aAAO,iBAAiB,UAAU,EAAE,QAAQ,CAAC,OAAO;AAlS1D,YAAAA;AAmSQ,cAAM,QAAQ,GAAG,aAAa,OAAO;AACrC,cAAM,OAAMA,MAAA,GAAG,gBAAH,gBAAAA,IAAgB;AAC5B,YAAI,SAAS,KAAK;AAChB,gBAAM,WAAW;AACjB,cAAI,aAAa,QAAQ,GAAG;AAC1B,yBAAa,QAAQ,EAAE,KAAK,GAAG;AAAA,UACjC;AAAA,QACF;AAAA,MACF,CAAC;AAED,YAAM,gBAAe,kBAAO,cAAc,cAAc,MAAnC,mBAAsC,gBAAtC,mBAAmD;AAExE,aAAO;AAAA,QACL,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,yCAAyC,KAAK;AAC5D,aAAO;AAAA,IACT;AAAA,EACF;AAEA,WAAS,uBAAyC;AAChD,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,MAAM,WAAW;AACvB,UAAM,MAAM,OAAO;AACnB,UAAM,MAAM,MAAM;AAClB,UAAM,MAAM,QAAQ;AACpB,UAAM,MAAM,SAAS;AACrB,UAAM,MAAM,YAAY;AACxB,UAAM,MAAM,kBAAkB;AAC9B,UAAM,cAAc;AACpB,UAAM,QAAQ;AACd,WAAO;AAAA,EACT;AAEA,WAAS,wBAA8B;AACrC,QAAI,CAAC,kBAAkB,CAAC,UAAW;AAEnC,mBAAe,iBAAiB,cAAc,MAAM;AAClD,UAAI,CAAC,aAAa,CAAC,eAAgB;AAEnC,YAAM,WAAW,eAAe,cAAc,UAAU;AAExD,UAAI,YAAY,QAAQ,CAAC,cAAc,eAAe;AACpD,sBAAc,gBAAgB;AAC9B,2BAAmB,UAAU,aAAa,aAAa;AAAA,MACzD;AAEA,UAAI,YAAY,OAAO,CAAC,cAAc,UAAU;AAC9C,sBAAc,WAAW;AACzB,2BAAmB,UAAU,aAAa,QAAQ;AAAA,MACpD;AAEA,UAAI,YAAY,QAAQ,CAAC,cAAc,eAAe;AACpD,sBAAc,gBAAgB;AAC9B,2BAAmB,UAAU,aAAa,aAAa;AAAA,MACzD;AAAA,IACF,CAAC;AAED,mBAAe,iBAAiB,WAAW,MAAM;AAC/C,UAAI,CAAC,aAAa,cAAc,MAAO;AACvC,oBAAc,QAAQ;AACtB,yBAAmB,UAAU,aAAa,KAAK;AAC/C,cAAQ,IAAI,kCAAkC;AAAA,IAChD,CAAC;AAED,mBAAe,iBAAiB,SAAS,MAAM;AAC7C,UAAI,CAAC,aAAa,cAAc,SAAU;AAC1C,oBAAc,WAAW;AACzB,yBAAmB,UAAU,aAAa,QAAQ;AAClD,cAAQ,IAAI,4BAA4B;AAExC,uBAAiB;AAAA,IACnB,CAAC;AAED,mBAAe,iBAAiB,SAAS,CAAC,MAAM;AAC9C,cAAQ,MAAM,iCAAiC,CAAC;AAChD,UAAI,WAAW;AACb,2BAAmB,UAAU,aAAa,KAAK;AAAA,MACjD;AACA,oBAAc;AAAA,IAChB,CAAC;AAED,mBAAe,iBAAiB,gBAAgB,MAAM;AACpD,UAAI,CAAC,UAAW;AAChB,UAAI,eAAgB,OAAO;AACzB,2BAAmB,UAAU,aAAa,IAAI;AAAA,MAChD,OAAO;AACL,2BAAmB,UAAU,aAAa,MAAM;AAAA,MAClD;AAAA,IACF,CAAC;AAED,mBAAe,iBAAiB,SAAS,MAAM;AAC7C,UAAI,aAAa,CAAC,eAAgB,OAAO;AACvC,2BAAmB,UAAU,aAAa,KAAK;AAAA,MACjD;AAAA,IACF,CAAC;AAED,mBAAe,iBAAiB,QAAQ,MAAM;AAC5C,UAAI,aAAa,eAAgB,cAAc,GAAG;AAChD,2BAAmB,UAAU,aAAa,MAAM;AAAA,MAClD;AAAA,IACF,CAAC;AAAA,EACH;AAEA,WAAS,mBAAyB;AAChC,YAAQ,IAAI,sCAAsC;AAClD,gBAAY;AACZ,iBAAa,QAAQ;AAErB,QAAI,eAAe;AACjB,oBAAc,MAAM,UAAU;AAC9B,oBAAc,MAAM,gBAAgB;AAAA,IACtC;AAEA,QAAI,EAAC,mCAAS,8BAA6B;AACzC,mBAAa,KAAK,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAClC,cAAQ,IAAI,0CAA0C;AAAA,IACxD,OAAO;AACL,cAAQ,IAAI,2CAA2C;AAAA,IACzD;AAEA,SAAK,gBAAgB;AACrB,SAAK,mBAAmB;AAAA,EAC1B;AAEA,WAAS,gBAAsB;AAC7B,YAAQ,IAAI,iCAAiC;AAC7C,gBAAY;AACZ,iBAAa,QAAQ;AAErB,QAAI,eAAe;AACjB,oBAAc,MAAM,UAAU;AAC9B,oBAAc,MAAM,gBAAgB;AAAA,IACtC;AAEA,QAAI,EAAC,mCAAS,8BAA6B;AACzC,UAAI,aAAa,QAAQ;AACvB,qBAAa,KAAK,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MACpC;AAAA,IACF;AAEA,SAAK,UAAU;AAAA,EACjB;AAEA,SAAO;AAAA,IACL,aAAa;AA1bjB;AA2bM,cAAQ,IAAI,4BAA4B;AAExC,UAAI,CAAC,eAAe;AAClB,cAAM,YAAY,SAAS,cAAc,KAAK;AAC9C,kBAAU,MAAM,WAAW;AAC3B,kBAAU,MAAM,OAAO;AACvB,kBAAU,MAAM,MAAM;AACtB,kBAAU,MAAM,QAAQ;AACxB,kBAAU,MAAM,SAAS;AACzB,kBAAU,MAAM,UAAU;AAC1B,kBAAU,MAAM,aAAa;AAC7B,kBAAU,MAAM,iBAAiB;AACjC,kBAAU,MAAM,gBAAgB;AAChC,kBAAU,MAAM,SAAS;AACzB,kBAAU,MAAM,kBAAkB;AAElC,2BAAa,kBAAb,mBAA4B,YAAY;AACxC,wBAAgB;AAAA,MAClB;AAAA,IACF;AAAA,IAEA,MAAM,WAAW,YAAoB;AACnC,cAAQ,IAAI,iCAAiC,UAAU;AAEvD,UAAI,WAAW;AACb,gBAAQ,KAAK,6DAA6D;AAC1E,eAAO,QAAQ,OAAO,IAAI,MAAM,oBAAoB,CAAC;AAAA,MACvD;AAEA,UAAI;AACF,oBAAY,kBAAkB;AAE9B,cAAM,WAAW,MAAM,MAAM,UAAU;AACvC,YAAI,CAAC,SAAS,IAAI;AAChB,gBAAM,IAAI,MAAM,yBAAyB,SAAS,UAAU,EAAE;AAAA,QAChE;AAEA,cAAM,UAAU,MAAM,SAAS,KAAK;AACpC,gBAAQ,IAAI,iCAAiC;AAC7C,gBAAQ,IAAI,sDAAsD,QAAQ,UAAU,GAAG,GAAI,CAAC;AAE5F,cAAM,KAAK,aAAa,OAAO;AAC/B,YAAI,CAAC,IAAI;AAMP,kBAAQ,KAAK,mDAAmD;AAChE,iBAAO,QAAQ,QAAQ;AAAA,QACzB;AAEA,oBAAY;AACZ,gBAAQ,IAAI,4BAA4B,GAAG,KAAK,eAAe,GAAG,QAAQ,GAAG;AAE7E,2BAAmB,GAAG,aAAa,UAAU;AAC7C,sBAAc,aAAa;AAE3B,eAAO,QAAQ,QAAQ;AAAA,MACzB,SAAS,OAAO;AAGd,gBAAQ,MAAM,uCAAuC,KAAK;AAC1D,aAAK,UAAU;AACf,eAAO,QAAQ,OAAO,KAAK;AAAA,MAC7B;AAAA,IACF;AAAA,IAEA,MAAM,OAAO;AACX,UAAI,CAAC,WAAW;AACd,gBAAQ,KAAK,4DAA4D;AACzE,eAAO,QAAQ,OAAO,IAAI,MAAM,cAAc,CAAC;AAAA,MACjD;AAEA,cAAQ,IAAI,oCAAoC;AAEhD,UAAI;AACF,YAAI,CAAC,gBAAgB;AACnB,2BAAiB,qBAAqB;AACtC,yDAAe,YAAY;AAC3B,gCAAsB;AAAA,QACxB;AAEA,wBAAgB;AAAA,UACd,YAAY,cAAc;AAAA,UAC1B,OAAO;AAAA,UACP,eAAe;AAAA,UACf,UAAU;AAAA,UACV,eAAe;AAAA,UACf,UAAU;AAAA,QACZ;AAEA,YAAI,EAAC,mCAAS,8BAA6B;AACzC,uBAAa,MAAM;AACnB,kBAAQ,IAAI,yCAAyC;AAAA,QACvD,OAAO;AACL,kBAAQ,IAAI,6CAA6C;AAAA,QAC3D;AAEA,qBAAa,QAAQ;AACrB,oBAAY;AAEZ,YAAI,eAAe;AACjB,wBAAc,MAAM,UAAU;AAC9B,wBAAc,MAAM,gBAAgB;AAAA,QACtC;AAEA,aAAK,eAAe;AAEpB,cAAM,YAAY,oBAAoB,UAAU,UAAU;AAC1D,YAAI,CAAC,WAAW;AACd,gBAAM,IAAI,MAAM,gCAAgC;AAAA,QAClD;AAEA,gBAAQ,IAAI,kCAAkC,UAAU,GAAG,EAAE;AAE7D,YAAI,WAAAC,QAAI,YAAY,GAAG;AACrB,cAAI,OAAO;AACT,kBAAM,QAAQ;AAAA,UAChB;AAEA,kBAAQ,IAAI,WAAAA,QAAI;AAAA,YACd,cAAc;AAAA,YACd,gBAAgB;AAAA,UAClB,CAAC;AAED,gBAAM,WAAW,UAAU,GAAG;AAC9B,gBAAM,YAAY,cAAc;AAEhC,gBAAM,GAAG,WAAAA,QAAI,OAAO,iBAAiB,MAAM;AACzC,oBAAQ,IAAI,sDAAsD;AAClE,2BAAgB,KAAK,EAAE,MAAM,CAAC,UAAU;AACtC,sBAAQ,MAAM,6CAA6C,KAAK;AAChE,4BAAc;AAAA,YAChB,CAAC;AAAA,UACH,CAAC;AAED,gBAAM,GAAG,WAAAA,QAAI,OAAO,OAAO,CAAC,OAAO,SAAS;AAC1C,oBAAQ,MAAM,4BAA4B,IAAI;AAC9C,gBAAI,KAAK,OAAO;AACd,4BAAc;AAAA,YAChB;AAAA,UACF,CAAC;AAAA,QACH,WAAW,eAAe,YAAY,+BAA+B,GAAG;AACtE,yBAAe,MAAM,UAAU;AAC/B,yBAAe,KAAK,EAAE,MAAM,CAAC,UAAU;AACrC,oBAAQ,MAAM,6CAA6C,KAAK;AAChE,0BAAc;AAAA,UAChB,CAAC;AAAA,QACH,OAAO;AACL,gBAAM,IAAI,MAAM,mBAAmB;AAAA,QACrC;AAEA,eAAO,QAAQ,QAAQ;AAAA,MACzB,SAAS,OAAO;AACd,gBAAQ,MAAM,mCAAmC,KAAK;AACtD,sBAAc;AACd,eAAO,QAAQ,OAAO,KAAK;AAAA,MAC7B;AAAA,IACF;AAAA,IAEA,MAAM,OAAO;AACX,cAAQ,IAAI,2BAA2B;AACvC,kBAAY;AACZ,mBAAa,QAAQ;AAErB,UAAI,eAAe;AACjB,sBAAc,MAAM,UAAU;AAC9B,sBAAc,MAAM,gBAAgB;AAAA,MACtC;AAEA,UAAI,OAAO;AACT,cAAM,QAAQ;AACd,gBAAQ;AAAA,MACV;AAEA,UAAI,gBAAgB;AAClB,uBAAe,MAAM;AACrB,uBAAe,MAAM;AAAA,MACvB;AAEA,UAAI,EAAC,mCAAS,8BAA6B;AACzC,qBAAa,KAAK,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MACpC;AAEA,kBAAY;AAAA,IACd;AAAA,IAEA,UAAU;AACR,cAAQ,IAAI,0BAA0B;AACtC,kBAAY;AACZ,mBAAa,QAAQ;AAErB,UAAI,OAAO;AACT,cAAM,QAAQ;AACd,gBAAQ;AAAA,MACV;AAEA,UAAI,gBAAgB;AAClB,uBAAe,MAAM;AACrB,uBAAe,MAAM;AACrB,uBAAe,OAAO;AACtB,yBAAiB;AAAA,MACnB;AAEA,UAAI,+CAAe,eAAe;AAChC,sBAAc,cAAc,YAAY,aAAa;AAAA,MACvD;AAEA,sBAAgB;AAChB,kBAAY;AACZ,gBAAU,MAAM;AAAA,IAClB;AAAA,IAEA,cAAc;AACZ,aAAO;AAAA,IACT;AAAA,IAEA,OAAO,OAAe,QAAgB;AACpC,cAAQ,IAAI,6BAA6B,KAAK,IAAI,MAAM,EAAE;AAE1D,UAAI,eAAe;AACjB,sBAAc,MAAM,QAAQ,GAAG,KAAK;AACpC,sBAAc,MAAM,SAAS,GAAG,MAAM;AAAA,MACxC;AAEA,UAAI,gBAAgB;AAClB,uBAAe,MAAM,QAAQ,GAAG,KAAK;AACrC,uBAAe,MAAM,SAAS,GAAG,MAAM;AAAA,MACzC;AAAA,IACF;AAAA,IAEA,GAAG,OAAe,UAAmC;AACnD,UAAI,CAAC,UAAU,IAAI,KAAK,EAAG,WAAU,IAAI,OAAO,oBAAI,IAAI,CAAC;AACzD,gBAAU,IAAI,KAAK,EAAG,IAAI,QAAQ;AAAA,IACpC;AAAA,IAEA,IAAI,OAAe,UAAmC;AAxqB1D;AAyqBM,sBAAU,IAAI,KAAK,MAAnB,mBAAsB,OAAO;AAAA,IAC/B;AAAA,IAEA,yBAAyB,OAAgB;AACvC,2BAAqB;AAAA,IACvB;AAAA,IAEA,wBAAwB;AACtB,aAAO;AAAA,IACT;AAAA,IAEA,YAAY,QAAgB;AAC1B,UAAI,kBAAkB,WAAW;AAC/B,uBAAe,SAAS,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC;AAAA,MACzD;AAAA,IACF;AAAA,IAEA,cAAsB;AACpB,UAAI,kBAAkB,WAAW;AAC/B,eAAO,eAAe;AAAA,MACxB;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":["level","_a","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(\n `[HlsAdPlayer] Error in event listener for ${event}:`,\n error\n );\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}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }session_id=${sessionId}`;\n }\n\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${\n trackingUrl.includes(\"?\") ? \"&\" : \"?\"\n }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(): {\n width: number;\n height: number;\n bitrate: number;\n } | 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(\n \"[HlsAdPlayer] No main stream quality info, using first media file\"\n );\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(\n \"[HlsAdPlayer] XML parsing error (malformed VAST XML):\",\n parserError.textContent\n );\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 isNoAdAvailable =\n adId === \"empty\" ||\n title.toLowerCase().includes(\"no ad available\") ||\n title.toLowerCase() === \"no ad available\";\n\n const durationText =\n 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 console.log(\n `[HlsAdPlayer] Found ${mediaFileElements.length} MediaFile element(s) in VAST XML`\n );\n\n mediaFileElements.forEach((mf, index) => {\n const type = mf.getAttribute(\"type\") || \"\";\n const url = mf.textContent?.trim() || \"\";\n const width = mf.getAttribute(\"width\") || \"\";\n const height = mf.getAttribute(\"height\") || \"\";\n\n console.log(\n `[HlsAdPlayer] MediaFile ${index}: type=\"${type}\", url=\"${url}\", width=\"${width}\", height=\"${height}\"`\n );\n\n if (type === \"application/x-mpegURL\" || type.includes(\"m3u8\")) {\n if (!url) {\n console.warn(\n `[HlsAdPlayer] MediaFile ${index} has HLS type but empty URL`\n );\n return;\n }\n\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr\n ? parseInt(bitrateAttr, 10)\n : undefined;\n\n mediaFiles.push({\n url,\n type,\n width: parseInt(width || \"1920\", 10),\n height: parseInt(height || \"1080\", 10),\n bitrate:\n bitrateValue && bitrateValue > 0 ? bitrateValue : undefined,\n });\n\n console.log(`[HlsAdPlayer] Added HLS MediaFile: ${url}`);\n } else {\n console.log(\n `[HlsAdPlayer] MediaFile ${index} ignored (type=\"${type}\" is not HLS)`\n );\n }\n });\n\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n \"[HlsAdPlayer] No ads available (VAST response indicates no ads)\"\n );\n } else {\n console.warn(\"[HlsAdPlayer] No HLS media files found in VAST XML\");\n }\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\n .querySelector(\"ClickThrough\")\n ?.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\n video.volume = 1.0;\n console.log(\n `[HlsAdPlayer] Created ad video element with volume ${video.volume}`\n );\n\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 setAdPlayingFlag(isPlaying: boolean): void {\n if (isPlaying) {\n contentVideo.dataset.stormcloudAdPlaying = \"true\";\n } else {\n delete contentVideo.dataset.stormcloudAdPlaying;\n }\n }\n\n function handleAdComplete(): void {\n console.log(\"[HlsAdPlayer] Handling ad completion\");\n adPlaying = false;\n setAdPlayingFlag(false);\n\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n console.log(\n `[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`\n );\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 setAdPlayingFlag(false);\n\n const previousMutedState = contentVideo.muted;\n contentVideo.muted = originalMutedState;\n console.log(\n `[HlsAdPlayer] Restored mute state: ${previousMutedState} -> ${originalMutedState}`\n );\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(\n \"[HlsAdPlayer] Cannot request new ads while an ad is playing\"\n );\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 console.log(\n \"[HlsAdPlayer] VAST XML content (first 2000 chars):\",\n vastXml.substring(0, 2000)\n );\n\n const ad = parseVastXml(vastXml);\n if (!ad) {\n console.warn(\"[HlsAdPlayer] No ads available from VAST response\");\n emit(\"ad_error\");\n return Promise.resolve();\n }\n\n currentAd = ad;\n console.log(\n `[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`\n );\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(\n \"[HlsAdPlayer] Cannot play: No ad loaded (no ads available)\"\n );\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 // Capture content volume BEFORE muting\n const contentVolume = contentVideo.volume;\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 setAdPlayingFlag(true);\n\n if (adVideoElement) {\n const adVolume = originalMutedState ? 0 : contentVolume;\n adVideoElement.volume = Math.max(0, Math.min(1, adVolume));\n adVideoElement.muted = false;\n console.log(\n `[HlsAdPlayer] Set ad video volume to ${adVideoElement.volume}, muted: ${adVideoElement.muted}, originalMutedState: ${originalMutedState}, contentVolume: ${contentVolume}`\n );\n }\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 (\n adVideoElement.canPlayType(\"application/vnd.apple.mpegurl\")\n ) {\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 setAdPlayingFlag(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 setAdPlayingFlag(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 console.log(\n `[HlsAdPlayer] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`\n );\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"],"mappings":"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","names":["level","_a","Hls"]}
|
package/lib/sdk/ima.cjs
CHANGED
|
@@ -163,6 +163,13 @@ function createImaController(video, options) {
|
|
|
163
163
|
let adPlaying = false;
|
|
164
164
|
let originalMutedState = false;
|
|
165
165
|
const listeners = /* @__PURE__ */ new Map();
|
|
166
|
+
function setAdPlayingFlag(isPlaying) {
|
|
167
|
+
if (isPlaying) {
|
|
168
|
+
video.dataset.stormcloudAdPlaying = "true";
|
|
169
|
+
} else {
|
|
170
|
+
delete video.dataset.stormcloudAdPlaying;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
166
173
|
function emit(event, payload) {
|
|
167
174
|
const set = listeners.get(event);
|
|
168
175
|
if (!set) return;
|
|
@@ -247,6 +254,14 @@ function createImaController(video, options) {
|
|
|
247
254
|
function makeAdsRequest(google, vastTagUrl) {
|
|
248
255
|
const adsRequest = new google.ima.AdsRequest();
|
|
249
256
|
adsRequest.adTagUrl = vastTagUrl;
|
|
257
|
+
const videoWidth = video.offsetWidth || video.clientWidth || 640;
|
|
258
|
+
const videoHeight = video.offsetHeight || video.clientHeight || 360;
|
|
259
|
+
adsRequest.linearAdSlotWidth = videoWidth;
|
|
260
|
+
adsRequest.linearAdSlotHeight = videoHeight;
|
|
261
|
+
adsRequest.nonLinearAdSlotWidth = videoWidth;
|
|
262
|
+
adsRequest.nonLinearAdSlotHeight = videoHeight;
|
|
263
|
+
adsRequest.vastLoadTimeout = 5e3;
|
|
264
|
+
console.log(`[IMA] Ads request dimensions: ${videoWidth}x${videoHeight}`);
|
|
250
265
|
adsLoader.requestAds(adsRequest);
|
|
251
266
|
}
|
|
252
267
|
function destroyAdsManager() {
|
|
@@ -293,6 +308,18 @@ function createImaController(video, options) {
|
|
|
293
308
|
},
|
|
294
309
|
async requestAds(vastTagUrl) {
|
|
295
310
|
console.log("[IMA] Requesting ads:", vastTagUrl);
|
|
311
|
+
if (!vastTagUrl || vastTagUrl.trim() === "") {
|
|
312
|
+
const error = new Error("VAST tag URL is empty or undefined");
|
|
313
|
+
console.warn("[IMA]", error.message);
|
|
314
|
+
return Promise.reject(error);
|
|
315
|
+
}
|
|
316
|
+
try {
|
|
317
|
+
new URL(vastTagUrl);
|
|
318
|
+
} catch (e) {
|
|
319
|
+
const error = new Error(`Invalid VAST tag URL format: ${vastTagUrl}`);
|
|
320
|
+
console.warn("[IMA]", error.message);
|
|
321
|
+
return Promise.reject(error);
|
|
322
|
+
}
|
|
296
323
|
if (adPlaying) {
|
|
297
324
|
console.warn(
|
|
298
325
|
"[IMA] Cannot request new ads while an ad is playing. Call stop() first."
|
|
@@ -354,6 +381,18 @@ function createImaController(video, options) {
|
|
|
354
381
|
);
|
|
355
382
|
}
|
|
356
383
|
}
|
|
384
|
+
const videoWidth = video.offsetWidth || video.clientWidth;
|
|
385
|
+
const videoHeight = video.offsetHeight || video.clientHeight;
|
|
386
|
+
if (!videoWidth || !videoHeight || videoWidth === 0 || videoHeight === 0) {
|
|
387
|
+
const error = new Error(
|
|
388
|
+
`Invalid video dimensions: ${videoWidth}x${videoHeight}. Cannot initialize ads.`
|
|
389
|
+
);
|
|
390
|
+
console.warn("[IMA]", error.message);
|
|
391
|
+
currentReject == null ? void 0 : currentReject(error);
|
|
392
|
+
adsLoadedReject = void 0;
|
|
393
|
+
adsLoadedResolve = void 0;
|
|
394
|
+
return Promise.reject(error);
|
|
395
|
+
}
|
|
357
396
|
if (!adsLoader) {
|
|
358
397
|
console.log("[IMA] Creating ads loader");
|
|
359
398
|
const adsLoaderCls = new google.ima.AdsLoader(adDisplayContainer);
|
|
@@ -373,7 +412,12 @@ function createImaController(video, options) {
|
|
|
373
412
|
console.error("[IMA] Ad error:", errorEvent.getError());
|
|
374
413
|
destroyAdsManager();
|
|
375
414
|
adPlaying = false;
|
|
415
|
+
const previousMutedState = video.muted;
|
|
376
416
|
video.muted = originalMutedState;
|
|
417
|
+
setAdPlayingFlag(false);
|
|
418
|
+
console.log(
|
|
419
|
+
`[IMA] Restored mute state after ad error: ${previousMutedState} -> ${originalMutedState}`
|
|
420
|
+
);
|
|
377
421
|
if (adContainerEl) {
|
|
378
422
|
adContainerEl.style.pointerEvents = "none";
|
|
379
423
|
adContainerEl.style.display = "none";
|
|
@@ -402,7 +446,9 @@ function createImaController(video, options) {
|
|
|
402
446
|
emit("ad_error");
|
|
403
447
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
404
448
|
if (video.paused) {
|
|
405
|
-
console.log(
|
|
449
|
+
console.log(
|
|
450
|
+
"[IMA] Resuming paused video after ad error"
|
|
451
|
+
);
|
|
406
452
|
(_a = video.play()) == null ? void 0 : _a.catch(() => {
|
|
407
453
|
});
|
|
408
454
|
}
|
|
@@ -424,11 +470,13 @@ function createImaController(video, options) {
|
|
|
424
470
|
}
|
|
425
471
|
video.muted = true;
|
|
426
472
|
adPlaying = true;
|
|
473
|
+
setAdPlayingFlag(true);
|
|
427
474
|
emit("content_pause");
|
|
428
475
|
}
|
|
429
476
|
);
|
|
430
477
|
adsManager.addEventListener(AdEvent.STARTED, () => {
|
|
431
478
|
console.log("[IMA] Ad started playing");
|
|
479
|
+
setAdPlayingFlag(true);
|
|
432
480
|
if (adContainerEl) {
|
|
433
481
|
adContainerEl.style.pointerEvents = "auto";
|
|
434
482
|
adContainerEl.style.display = "flex";
|
|
@@ -444,6 +492,7 @@ function createImaController(video, options) {
|
|
|
444
492
|
console.log("[IMA] Content resume requested");
|
|
445
493
|
adPlaying = false;
|
|
446
494
|
video.muted = originalMutedState;
|
|
495
|
+
setAdPlayingFlag(false);
|
|
447
496
|
if (adContainerEl) {
|
|
448
497
|
adContainerEl.style.pointerEvents = "none";
|
|
449
498
|
adContainerEl.style.display = "none";
|
|
@@ -467,6 +516,7 @@ function createImaController(video, options) {
|
|
|
467
516
|
console.log("[IMA] All ads completed");
|
|
468
517
|
adPlaying = false;
|
|
469
518
|
video.muted = originalMutedState;
|
|
519
|
+
setAdPlayingFlag(false);
|
|
470
520
|
if (adContainerEl) {
|
|
471
521
|
adContainerEl.style.pointerEvents = "none";
|
|
472
522
|
adContainerEl.style.display = "none";
|
|
@@ -497,6 +547,7 @@ function createImaController(video, options) {
|
|
|
497
547
|
console.error("[IMA] Error setting up ads manager:", e);
|
|
498
548
|
adPlaying = false;
|
|
499
549
|
video.muted = originalMutedState;
|
|
550
|
+
setAdPlayingFlag(false);
|
|
500
551
|
if (adContainerEl) {
|
|
501
552
|
adContainerEl.style.pointerEvents = "none";
|
|
502
553
|
adContainerEl.style.display = "none";
|
|
@@ -504,7 +555,9 @@ function createImaController(video, options) {
|
|
|
504
555
|
}
|
|
505
556
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
506
557
|
if (video.paused) {
|
|
507
|
-
console.log(
|
|
558
|
+
console.log(
|
|
559
|
+
"[IMA] Resuming paused video after setup error"
|
|
560
|
+
);
|
|
508
561
|
video.play().catch(() => {
|
|
509
562
|
});
|
|
510
563
|
}
|
|
@@ -524,7 +577,12 @@ function createImaController(video, options) {
|
|
|
524
577
|
(adErrorEvent) => {
|
|
525
578
|
console.error("[IMA] Ads loader error:", adErrorEvent.getError());
|
|
526
579
|
adPlaying = false;
|
|
580
|
+
const previousMutedState = video.muted;
|
|
527
581
|
video.muted = originalMutedState;
|
|
582
|
+
setAdPlayingFlag(false);
|
|
583
|
+
console.log(
|
|
584
|
+
`[IMA] Restored mute state: ${previousMutedState} -> ${originalMutedState}`
|
|
585
|
+
);
|
|
528
586
|
if (adContainerEl) {
|
|
529
587
|
adContainerEl.style.pointerEvents = "none";
|
|
530
588
|
adContainerEl.style.display = "none";
|
|
@@ -576,12 +634,20 @@ function createImaController(video, options) {
|
|
|
576
634
|
console.log(`[IMA] Initializing ads manager (${width}x${height})`);
|
|
577
635
|
adsManager.init(width, height, window.google.ima.ViewMode.NORMAL);
|
|
578
636
|
adPlaying = true;
|
|
637
|
+
const adVolume = originalMutedState ? 0 : video.volume;
|
|
638
|
+
try {
|
|
639
|
+
adsManager.setVolume(adVolume);
|
|
640
|
+
console.log(`[IMA] Set ad volume to ${adVolume}`);
|
|
641
|
+
} catch (error) {
|
|
642
|
+
console.warn("[IMA] Failed to set ad volume:", error);
|
|
643
|
+
}
|
|
579
644
|
console.log("[IMA] Starting ad playback");
|
|
580
645
|
adsManager.start();
|
|
581
646
|
return Promise.resolve();
|
|
582
647
|
} catch (error) {
|
|
583
648
|
console.error("[IMA] Error starting ad playback:", error);
|
|
584
649
|
adPlaying = false;
|
|
650
|
+
setAdPlayingFlag(false);
|
|
585
651
|
if (!(options == null ? void 0 : options.continueLiveStreamDuringAds)) {
|
|
586
652
|
(_b = video.play()) == null ? void 0 : _b.catch(() => {
|
|
587
653
|
});
|
|
@@ -593,6 +659,7 @@ function createImaController(video, options) {
|
|
|
593
659
|
var _a;
|
|
594
660
|
adPlaying = false;
|
|
595
661
|
video.muted = originalMutedState;
|
|
662
|
+
setAdPlayingFlag(false);
|
|
596
663
|
if (adContainerEl) {
|
|
597
664
|
adContainerEl.style.pointerEvents = "none";
|
|
598
665
|
adContainerEl.style.display = "none";
|
|
@@ -616,6 +683,7 @@ function createImaController(video, options) {
|
|
|
616
683
|
destroyAdsManager();
|
|
617
684
|
adPlaying = false;
|
|
618
685
|
video.muted = originalMutedState;
|
|
686
|
+
setAdPlayingFlag(false);
|
|
619
687
|
if (adContainerEl) {
|
|
620
688
|
adContainerEl.style.pointerEvents = "none";
|
|
621
689
|
adContainerEl.style.display = "none";
|
|
@@ -658,6 +726,9 @@ function createImaController(video, options) {
|
|
|
658
726
|
(_a = listeners.get(event)) == null ? void 0 : _a.delete(listener);
|
|
659
727
|
},
|
|
660
728
|
updateOriginalMutedState(muted) {
|
|
729
|
+
console.log(
|
|
730
|
+
`[IMA] updateOriginalMutedState called: ${originalMutedState} -> ${muted}`
|
|
731
|
+
);
|
|
661
732
|
originalMutedState = muted;
|
|
662
733
|
},
|
|
663
734
|
getOriginalMutedState() {
|