stormcloud-video-player 0.2.12 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -1
- package/dist/stormcloud-vp.min.js +2 -2
- package/lib/index.cjs +986 -52
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +75 -2
- package/lib/index.d.ts +75 -2
- package/lib/index.js +976 -52
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +922 -40
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +2 -2
- package/lib/players/HlsPlayer.cjs +922 -40
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/HlsPlayer.d.cts +1 -1
- package/lib/players/index.cjs +922 -40
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/hlsAdPlayer.cjs +488 -0
- package/lib/sdk/hlsAdPlayer.cjs.map +1 -0
- package/lib/sdk/hlsAdPlayer.d.cts +8 -0
- package/lib/sdk/ima.cjs +143 -0
- package/lib/sdk/ima.cjs.map +1 -1
- package/lib/sdk/ima.d.cts +1 -1
- package/lib/{types-GpA_hKek.d.cts → types-mVgmKmzM.d.cts} +3 -0
- package/lib/ui/StormcloudVideoPlayer.cjs +922 -40
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/ui/StormcloudVideoPlayer.d.cts +1 -1
- package/lib/utils/browserCompat.cjs +228 -0
- package/lib/utils/browserCompat.cjs.map +1 -0
- package/lib/utils/browserCompat.d.cts +36 -0
- package/lib/utils/polyfills.cjs +253 -0
- package/lib/utils/polyfills.cjs.map +1 -0
- package/lib/utils/polyfills.d.cts +11 -0
- package/lib/utils/tracking.d.cts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/sdk/hlsAdPlayer.ts
|
|
31
|
+
var hlsAdPlayer_exports = {};
|
|
32
|
+
__export(hlsAdPlayer_exports, {
|
|
33
|
+
createHlsAdPlayer: () => createHlsAdPlayer
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(hlsAdPlayer_exports);
|
|
36
|
+
var import_hls = __toESM(require("hls.js"), 1);
|
|
37
|
+
function createHlsAdPlayer(contentVideo, options) {
|
|
38
|
+
let adPlaying = false;
|
|
39
|
+
let originalMutedState = false;
|
|
40
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
41
|
+
const licenseKey = options?.licenseKey;
|
|
42
|
+
let adVideoElement;
|
|
43
|
+
let adHls;
|
|
44
|
+
let adContainerEl;
|
|
45
|
+
let currentAd;
|
|
46
|
+
let sessionId;
|
|
47
|
+
let trackingFired = {
|
|
48
|
+
impression: false,
|
|
49
|
+
start: false,
|
|
50
|
+
firstQuartile: false,
|
|
51
|
+
midpoint: false,
|
|
52
|
+
thirdQuartile: false,
|
|
53
|
+
complete: false
|
|
54
|
+
};
|
|
55
|
+
function emit(event, payload) {
|
|
56
|
+
const set = listeners.get(event);
|
|
57
|
+
if (!set) return;
|
|
58
|
+
for (const fn of Array.from(set)) {
|
|
59
|
+
try {
|
|
60
|
+
fn(payload);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.warn(`[HlsAdPlayer] Error in event listener for ${event}:`, error);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function generateSessionId() {
|
|
67
|
+
return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
68
|
+
}
|
|
69
|
+
function fireTrackingPixels(urls) {
|
|
70
|
+
if (!urls || urls.length === 0) return;
|
|
71
|
+
urls.forEach((url) => {
|
|
72
|
+
try {
|
|
73
|
+
let trackingUrl = url;
|
|
74
|
+
if (sessionId) {
|
|
75
|
+
trackingUrl = `${trackingUrl}${trackingUrl.includes("?") ? "&" : "?"}session_id=${sessionId}`;
|
|
76
|
+
}
|
|
77
|
+
if (licenseKey) {
|
|
78
|
+
trackingUrl = `${trackingUrl}${trackingUrl.includes("?") ? "&" : "?"}license_key=${licenseKey}`;
|
|
79
|
+
}
|
|
80
|
+
const img = new Image(1, 1);
|
|
81
|
+
img.src = trackingUrl;
|
|
82
|
+
console.log(`[HlsAdPlayer] Fired tracking pixel: ${trackingUrl}`);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.warn(`[HlsAdPlayer] Error firing tracking pixel:`, error);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
function parseVastXml(xmlString) {
|
|
89
|
+
try {
|
|
90
|
+
const parser = new DOMParser();
|
|
91
|
+
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
|
|
92
|
+
const parserError = xmlDoc.querySelector("parsererror");
|
|
93
|
+
if (parserError) {
|
|
94
|
+
console.error("[HlsAdPlayer] XML parsing error:", parserError.textContent);
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
const adElement = xmlDoc.querySelector("Ad");
|
|
98
|
+
if (!adElement) {
|
|
99
|
+
console.warn("[HlsAdPlayer] No Ad element found in VAST XML");
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const adId = adElement.getAttribute("id") || "unknown";
|
|
103
|
+
const title = xmlDoc.querySelector("AdTitle")?.textContent || "Ad";
|
|
104
|
+
const durationText = xmlDoc.querySelector("Duration")?.textContent || "00:00:30";
|
|
105
|
+
const durationParts = durationText.split(":");
|
|
106
|
+
const duration = parseInt(durationParts[0] || "0", 10) * 3600 + parseInt(durationParts[1] || "0", 10) * 60 + parseInt(durationParts[2] || "0", 10);
|
|
107
|
+
const mediaFileElements = xmlDoc.querySelectorAll("MediaFile");
|
|
108
|
+
const mediaFiles = [];
|
|
109
|
+
mediaFileElements.forEach((mf) => {
|
|
110
|
+
const type = mf.getAttribute("type") || "";
|
|
111
|
+
if (type === "application/x-mpegURL" || type.includes("m3u8")) {
|
|
112
|
+
const bitrateAttr = mf.getAttribute("bitrate");
|
|
113
|
+
const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;
|
|
114
|
+
mediaFiles.push({
|
|
115
|
+
url: mf.textContent?.trim() || "",
|
|
116
|
+
type,
|
|
117
|
+
width: parseInt(mf.getAttribute("width") || "1920", 10),
|
|
118
|
+
height: parseInt(mf.getAttribute("height") || "1080", 10),
|
|
119
|
+
bitrate: bitrateValue && bitrateValue > 0 ? bitrateValue : void 0
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
if (mediaFiles.length === 0) {
|
|
124
|
+
console.warn("[HlsAdPlayer] No HLS media files found in VAST XML");
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
const trackingUrls = {
|
|
128
|
+
impression: [],
|
|
129
|
+
start: [],
|
|
130
|
+
firstQuartile: [],
|
|
131
|
+
midpoint: [],
|
|
132
|
+
thirdQuartile: [],
|
|
133
|
+
complete: [],
|
|
134
|
+
mute: [],
|
|
135
|
+
unmute: [],
|
|
136
|
+
pause: [],
|
|
137
|
+
resume: [],
|
|
138
|
+
fullscreen: [],
|
|
139
|
+
exitFullscreen: [],
|
|
140
|
+
skip: [],
|
|
141
|
+
error: []
|
|
142
|
+
};
|
|
143
|
+
xmlDoc.querySelectorAll("Impression").forEach((el) => {
|
|
144
|
+
const url = el.textContent?.trim();
|
|
145
|
+
if (url) trackingUrls.impression.push(url);
|
|
146
|
+
});
|
|
147
|
+
xmlDoc.querySelectorAll("Tracking").forEach((el) => {
|
|
148
|
+
const event = el.getAttribute("event");
|
|
149
|
+
const url = el.textContent?.trim();
|
|
150
|
+
if (event && url) {
|
|
151
|
+
const eventKey = event;
|
|
152
|
+
if (trackingUrls[eventKey]) {
|
|
153
|
+
trackingUrls[eventKey].push(url);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
const clickThrough = xmlDoc.querySelector("ClickThrough")?.textContent?.trim();
|
|
158
|
+
return {
|
|
159
|
+
id: adId,
|
|
160
|
+
title,
|
|
161
|
+
duration,
|
|
162
|
+
mediaFiles,
|
|
163
|
+
trackingUrls,
|
|
164
|
+
clickThrough
|
|
165
|
+
};
|
|
166
|
+
} catch (error) {
|
|
167
|
+
console.error("[HlsAdPlayer] Error parsing VAST XML:", error);
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function createAdVideoElement() {
|
|
172
|
+
const video = document.createElement("video");
|
|
173
|
+
video.style.position = "absolute";
|
|
174
|
+
video.style.left = "0";
|
|
175
|
+
video.style.top = "0";
|
|
176
|
+
video.style.width = "100%";
|
|
177
|
+
video.style.height = "100%";
|
|
178
|
+
video.style.objectFit = "contain";
|
|
179
|
+
video.style.backgroundColor = "#000";
|
|
180
|
+
video.playsInline = true;
|
|
181
|
+
video.muted = false;
|
|
182
|
+
return video;
|
|
183
|
+
}
|
|
184
|
+
function setupAdEventListeners() {
|
|
185
|
+
if (!adVideoElement || !currentAd) return;
|
|
186
|
+
adVideoElement.addEventListener("timeupdate", () => {
|
|
187
|
+
if (!currentAd || !adVideoElement) return;
|
|
188
|
+
const progress = adVideoElement.currentTime / currentAd.duration;
|
|
189
|
+
if (progress >= 0.25 && !trackingFired.firstQuartile) {
|
|
190
|
+
trackingFired.firstQuartile = true;
|
|
191
|
+
fireTrackingPixels(currentAd.trackingUrls.firstQuartile);
|
|
192
|
+
}
|
|
193
|
+
if (progress >= 0.5 && !trackingFired.midpoint) {
|
|
194
|
+
trackingFired.midpoint = true;
|
|
195
|
+
fireTrackingPixels(currentAd.trackingUrls.midpoint);
|
|
196
|
+
}
|
|
197
|
+
if (progress >= 0.75 && !trackingFired.thirdQuartile) {
|
|
198
|
+
trackingFired.thirdQuartile = true;
|
|
199
|
+
fireTrackingPixels(currentAd.trackingUrls.thirdQuartile);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
adVideoElement.addEventListener("playing", () => {
|
|
203
|
+
if (!currentAd || trackingFired.start) return;
|
|
204
|
+
trackingFired.start = true;
|
|
205
|
+
fireTrackingPixels(currentAd.trackingUrls.start);
|
|
206
|
+
console.log("[HlsAdPlayer] Ad started playing");
|
|
207
|
+
});
|
|
208
|
+
adVideoElement.addEventListener("ended", () => {
|
|
209
|
+
if (!currentAd || trackingFired.complete) return;
|
|
210
|
+
trackingFired.complete = true;
|
|
211
|
+
fireTrackingPixels(currentAd.trackingUrls.complete);
|
|
212
|
+
console.log("[HlsAdPlayer] Ad completed");
|
|
213
|
+
handleAdComplete();
|
|
214
|
+
});
|
|
215
|
+
adVideoElement.addEventListener("error", (e) => {
|
|
216
|
+
console.error("[HlsAdPlayer] Ad video error:", e);
|
|
217
|
+
if (currentAd) {
|
|
218
|
+
fireTrackingPixels(currentAd.trackingUrls.error);
|
|
219
|
+
}
|
|
220
|
+
handleAdError();
|
|
221
|
+
});
|
|
222
|
+
adVideoElement.addEventListener("volumechange", () => {
|
|
223
|
+
if (!currentAd) return;
|
|
224
|
+
if (adVideoElement.muted) {
|
|
225
|
+
fireTrackingPixels(currentAd.trackingUrls.mute);
|
|
226
|
+
} else {
|
|
227
|
+
fireTrackingPixels(currentAd.trackingUrls.unmute);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
adVideoElement.addEventListener("pause", () => {
|
|
231
|
+
if (currentAd && !adVideoElement.ended) {
|
|
232
|
+
fireTrackingPixels(currentAd.trackingUrls.pause);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
adVideoElement.addEventListener("play", () => {
|
|
236
|
+
if (currentAd && adVideoElement.currentTime > 0) {
|
|
237
|
+
fireTrackingPixels(currentAd.trackingUrls.resume);
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
function handleAdComplete() {
|
|
242
|
+
console.log("[HlsAdPlayer] Handling ad completion");
|
|
243
|
+
adPlaying = false;
|
|
244
|
+
contentVideo.muted = originalMutedState;
|
|
245
|
+
if (adContainerEl) {
|
|
246
|
+
adContainerEl.style.display = "none";
|
|
247
|
+
adContainerEl.style.pointerEvents = "none";
|
|
248
|
+
}
|
|
249
|
+
if (!options?.continueLiveStreamDuringAds) {
|
|
250
|
+
contentVideo.play().catch(() => {
|
|
251
|
+
});
|
|
252
|
+
console.log("[HlsAdPlayer] Content resumed (VOD mode)");
|
|
253
|
+
} else {
|
|
254
|
+
console.log("[HlsAdPlayer] Content unmuted (Live mode)");
|
|
255
|
+
}
|
|
256
|
+
emit("content_resume");
|
|
257
|
+
emit("all_ads_completed");
|
|
258
|
+
}
|
|
259
|
+
function handleAdError() {
|
|
260
|
+
console.log("[HlsAdPlayer] Handling ad error");
|
|
261
|
+
adPlaying = false;
|
|
262
|
+
contentVideo.muted = originalMutedState;
|
|
263
|
+
if (adContainerEl) {
|
|
264
|
+
adContainerEl.style.display = "none";
|
|
265
|
+
adContainerEl.style.pointerEvents = "none";
|
|
266
|
+
}
|
|
267
|
+
if (!options?.continueLiveStreamDuringAds) {
|
|
268
|
+
if (contentVideo.paused) {
|
|
269
|
+
contentVideo.play().catch(() => {
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
emit("ad_error");
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
initialize() {
|
|
277
|
+
console.log("[HlsAdPlayer] Initializing");
|
|
278
|
+
if (!adContainerEl) {
|
|
279
|
+
const container = document.createElement("div");
|
|
280
|
+
container.style.position = "absolute";
|
|
281
|
+
container.style.left = "0";
|
|
282
|
+
container.style.top = "0";
|
|
283
|
+
container.style.right = "0";
|
|
284
|
+
container.style.bottom = "0";
|
|
285
|
+
container.style.display = "none";
|
|
286
|
+
container.style.alignItems = "center";
|
|
287
|
+
container.style.justifyContent = "center";
|
|
288
|
+
container.style.pointerEvents = "none";
|
|
289
|
+
container.style.zIndex = "2";
|
|
290
|
+
container.style.backgroundColor = "#000";
|
|
291
|
+
contentVideo.parentElement?.appendChild(container);
|
|
292
|
+
adContainerEl = container;
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
async requestAds(vastTagUrl) {
|
|
296
|
+
console.log("[HlsAdPlayer] Requesting ads:", vastTagUrl);
|
|
297
|
+
if (adPlaying) {
|
|
298
|
+
console.warn("[HlsAdPlayer] Cannot request new ads while an ad is playing");
|
|
299
|
+
return Promise.reject(new Error("Ad already playing"));
|
|
300
|
+
}
|
|
301
|
+
try {
|
|
302
|
+
sessionId = generateSessionId();
|
|
303
|
+
const response = await fetch(vastTagUrl);
|
|
304
|
+
if (!response.ok) {
|
|
305
|
+
throw new Error(`Failed to fetch VAST: ${response.statusText}`);
|
|
306
|
+
}
|
|
307
|
+
const vastXml = await response.text();
|
|
308
|
+
console.log("[HlsAdPlayer] VAST XML received");
|
|
309
|
+
const ad = parseVastXml(vastXml);
|
|
310
|
+
if (!ad) {
|
|
311
|
+
throw new Error("Failed to parse VAST XML or no ads available");
|
|
312
|
+
}
|
|
313
|
+
currentAd = ad;
|
|
314
|
+
console.log(`[HlsAdPlayer] Ad parsed: ${ad.title}, duration: ${ad.duration}s`);
|
|
315
|
+
fireTrackingPixels(ad.trackingUrls.impression);
|
|
316
|
+
trackingFired.impression = true;
|
|
317
|
+
return Promise.resolve();
|
|
318
|
+
} catch (error) {
|
|
319
|
+
console.error("[HlsAdPlayer] Error requesting ads:", error);
|
|
320
|
+
emit("ad_error");
|
|
321
|
+
return Promise.reject(error);
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
async play() {
|
|
325
|
+
if (!currentAd) {
|
|
326
|
+
console.warn("[HlsAdPlayer] Cannot play: No ad loaded");
|
|
327
|
+
return Promise.reject(new Error("No ad loaded"));
|
|
328
|
+
}
|
|
329
|
+
console.log("[HlsAdPlayer] Starting ad playback");
|
|
330
|
+
try {
|
|
331
|
+
if (!adVideoElement) {
|
|
332
|
+
adVideoElement = createAdVideoElement();
|
|
333
|
+
adContainerEl?.appendChild(adVideoElement);
|
|
334
|
+
setupAdEventListeners();
|
|
335
|
+
}
|
|
336
|
+
trackingFired = {
|
|
337
|
+
impression: trackingFired.impression,
|
|
338
|
+
start: false,
|
|
339
|
+
firstQuartile: false,
|
|
340
|
+
midpoint: false,
|
|
341
|
+
thirdQuartile: false,
|
|
342
|
+
complete: false
|
|
343
|
+
};
|
|
344
|
+
if (!options?.continueLiveStreamDuringAds) {
|
|
345
|
+
contentVideo.pause();
|
|
346
|
+
console.log("[HlsAdPlayer] Content paused (VOD mode)");
|
|
347
|
+
} else {
|
|
348
|
+
console.log("[HlsAdPlayer] Content continues (Live mode)");
|
|
349
|
+
}
|
|
350
|
+
contentVideo.muted = true;
|
|
351
|
+
adPlaying = true;
|
|
352
|
+
if (adContainerEl) {
|
|
353
|
+
adContainerEl.style.display = "flex";
|
|
354
|
+
adContainerEl.style.pointerEvents = "auto";
|
|
355
|
+
}
|
|
356
|
+
emit("content_pause");
|
|
357
|
+
const mediaFile = currentAd.mediaFiles[0];
|
|
358
|
+
if (!mediaFile) {
|
|
359
|
+
throw new Error("No media file available for ad");
|
|
360
|
+
}
|
|
361
|
+
console.log(`[HlsAdPlayer] Loading ad from: ${mediaFile.url}`);
|
|
362
|
+
if (import_hls.default.isSupported()) {
|
|
363
|
+
if (adHls) {
|
|
364
|
+
adHls.destroy();
|
|
365
|
+
}
|
|
366
|
+
adHls = new import_hls.default({
|
|
367
|
+
enableWorker: true,
|
|
368
|
+
lowLatencyMode: false
|
|
369
|
+
});
|
|
370
|
+
adHls.loadSource(mediaFile.url);
|
|
371
|
+
adHls.attachMedia(adVideoElement);
|
|
372
|
+
adHls.on(import_hls.default.Events.MANIFEST_PARSED, () => {
|
|
373
|
+
console.log("[HlsAdPlayer] HLS manifest parsed, starting playback");
|
|
374
|
+
adVideoElement.play().catch((error) => {
|
|
375
|
+
console.error("[HlsAdPlayer] Error starting ad playback:", error);
|
|
376
|
+
handleAdError();
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
adHls.on(import_hls.default.Events.ERROR, (event, data) => {
|
|
380
|
+
console.error("[HlsAdPlayer] HLS error:", data);
|
|
381
|
+
if (data.fatal) {
|
|
382
|
+
handleAdError();
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
} else if (adVideoElement.canPlayType("application/vnd.apple.mpegurl")) {
|
|
386
|
+
adVideoElement.src = mediaFile.url;
|
|
387
|
+
adVideoElement.play().catch((error) => {
|
|
388
|
+
console.error("[HlsAdPlayer] Error starting ad playback:", error);
|
|
389
|
+
handleAdError();
|
|
390
|
+
});
|
|
391
|
+
} else {
|
|
392
|
+
throw new Error("HLS not supported");
|
|
393
|
+
}
|
|
394
|
+
return Promise.resolve();
|
|
395
|
+
} catch (error) {
|
|
396
|
+
console.error("[HlsAdPlayer] Error playing ad:", error);
|
|
397
|
+
handleAdError();
|
|
398
|
+
return Promise.reject(error);
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
async stop() {
|
|
402
|
+
console.log("[HlsAdPlayer] Stopping ad");
|
|
403
|
+
adPlaying = false;
|
|
404
|
+
contentVideo.muted = originalMutedState;
|
|
405
|
+
if (adContainerEl) {
|
|
406
|
+
adContainerEl.style.display = "none";
|
|
407
|
+
adContainerEl.style.pointerEvents = "none";
|
|
408
|
+
}
|
|
409
|
+
if (adHls) {
|
|
410
|
+
adHls.destroy();
|
|
411
|
+
adHls = void 0;
|
|
412
|
+
}
|
|
413
|
+
if (adVideoElement) {
|
|
414
|
+
adVideoElement.pause();
|
|
415
|
+
adVideoElement.src = "";
|
|
416
|
+
}
|
|
417
|
+
if (!options?.continueLiveStreamDuringAds) {
|
|
418
|
+
contentVideo.play().catch(() => {
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
currentAd = void 0;
|
|
422
|
+
},
|
|
423
|
+
destroy() {
|
|
424
|
+
console.log("[HlsAdPlayer] Destroying");
|
|
425
|
+
adPlaying = false;
|
|
426
|
+
contentVideo.muted = originalMutedState;
|
|
427
|
+
if (adHls) {
|
|
428
|
+
adHls.destroy();
|
|
429
|
+
adHls = void 0;
|
|
430
|
+
}
|
|
431
|
+
if (adVideoElement) {
|
|
432
|
+
adVideoElement.pause();
|
|
433
|
+
adVideoElement.src = "";
|
|
434
|
+
adVideoElement.remove();
|
|
435
|
+
adVideoElement = void 0;
|
|
436
|
+
}
|
|
437
|
+
if (adContainerEl?.parentElement) {
|
|
438
|
+
adContainerEl.parentElement.removeChild(adContainerEl);
|
|
439
|
+
}
|
|
440
|
+
adContainerEl = void 0;
|
|
441
|
+
currentAd = void 0;
|
|
442
|
+
listeners.clear();
|
|
443
|
+
},
|
|
444
|
+
isAdPlaying() {
|
|
445
|
+
return adPlaying;
|
|
446
|
+
},
|
|
447
|
+
resize(width, height) {
|
|
448
|
+
console.log(`[HlsAdPlayer] Resizing to ${width}x${height}`);
|
|
449
|
+
if (adContainerEl) {
|
|
450
|
+
adContainerEl.style.width = `${width}px`;
|
|
451
|
+
adContainerEl.style.height = `${height}px`;
|
|
452
|
+
}
|
|
453
|
+
if (adVideoElement) {
|
|
454
|
+
adVideoElement.style.width = `${width}px`;
|
|
455
|
+
adVideoElement.style.height = `${height}px`;
|
|
456
|
+
}
|
|
457
|
+
},
|
|
458
|
+
on(event, listener) {
|
|
459
|
+
if (!listeners.has(event)) listeners.set(event, /* @__PURE__ */ new Set());
|
|
460
|
+
listeners.get(event).add(listener);
|
|
461
|
+
},
|
|
462
|
+
off(event, listener) {
|
|
463
|
+
listeners.get(event)?.delete(listener);
|
|
464
|
+
},
|
|
465
|
+
updateOriginalMutedState(muted) {
|
|
466
|
+
originalMutedState = muted;
|
|
467
|
+
},
|
|
468
|
+
getOriginalMutedState() {
|
|
469
|
+
return originalMutedState;
|
|
470
|
+
},
|
|
471
|
+
setAdVolume(volume) {
|
|
472
|
+
if (adVideoElement && adPlaying) {
|
|
473
|
+
adVideoElement.volume = Math.max(0, Math.min(1, volume));
|
|
474
|
+
}
|
|
475
|
+
},
|
|
476
|
+
getAdVolume() {
|
|
477
|
+
if (adVideoElement && adPlaying) {
|
|
478
|
+
return adVideoElement.volume;
|
|
479
|
+
}
|
|
480
|
+
return 1;
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
485
|
+
0 && (module.exports = {
|
|
486
|
+
createHlsAdPlayer
|
|
487
|
+
});
|
|
488
|
+
//# sourceMappingURL=hlsAdPlayer.cjs.map
|
|
@@ -0,0 +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"]}
|