stormcloud-video-player 0.5.7 → 0.5.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/stormcloud-vp.min.js +1 -1
- package/lib/index.cjs +117 -25
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +2 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +117 -25
- package/lib/index.js.map +1 -1
- package/lib/player/StormcloudVideoPlayer.cjs +117 -25
- package/lib/player/StormcloudVideoPlayer.cjs.map +1 -1
- package/lib/player/StormcloudVideoPlayer.d.cts +2 -0
- package/lib/players/HlsPlayer.cjs +117 -25
- package/lib/players/HlsPlayer.cjs.map +1 -1
- package/lib/players/index.cjs +117 -25
- package/lib/players/index.cjs.map +1 -1
- package/lib/sdk/prebidController.cjs +4 -6
- package/lib/sdk/prebidController.cjs.map +1 -1
- package/lib/sdk/vastParser.cjs +3 -5
- package/lib/sdk/vastParser.cjs.map +1 -1
- package/lib/sdk/vastParser.d.cts +1 -1
- package/lib/ui/StormcloudVideoPlayer.cjs +117 -25
- package/lib/ui/StormcloudVideoPlayer.cjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/sdk/vastParser.cjs","../../src/sdk/vastParser.ts"],"names":["key","__defProp","Object","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","enumerable","get","__copyProps","to","from","except","desc","call","__toCommonJS","mod","value","vastParser_exports","createEmptyTrackingState","fetchAndParseVastAd","fireTrackingPixels","parseVastXml","module","exports","isHlsType","type","includes","isMp4Type","xmlString","filter","logPrefix","xmlDoc","parser","DOMParser","parseFromString","parserError","querySelector","console","error","textContent","adElement","warn"],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2DAWaA,mCAAAA,CAAJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAVLC,YAAYC,OAAOC,cAAc;QACjCC,OAAAA,YAAmBF,IAAAA,CAAAA,EAAOG,YAAAA,OAAAA,CAAAA,SAAAA,GAAwB;gBAClDC;YAAAA,IAAAA,OAAAA,kBAAAA,GAAAA,GAAoBJ,OAAOK,CAAAA,cAA3BD,sCAAAA,gBAA2BC,IAAAA,YAAmB;YAC9CC,IAAAA,KAAAA,IAAeN,OAAOO,EAAAA,OAAS,CAACC,EAAAA,CAAAA,IAAAA,CAAAA,MAAc;QAC9CC,WAAW,kBAACC,QAAQC;QACtB,IAAK,GAAA,CAAIC,QAAQD,IACfZ,GAAAA,CAAAA,MAAUW,MAAAA,EAAQE,KAAAA,CAAM,SAAA;gBAAkBC;cAAhBC,EAAAA,CAAKH,GAAG,CAACC,GAAAA,EAAK,CAAA,YAAA,CAAA;cAAEC,EAAAA,OAAAA,kBAAAA,GAAY,WAAA,cAAZA,sCAAAA,EAAY,cAAA,IAAA;YAAK,IAAA,SAAA,KAAA;gBAC/D,IAAA,WAAA;gBACIE,IAAAA,MAAc,MAAA,CAAA,SAAA,EAAA,GAACC,IAAIC,MAAMC,QAAQC;oBAC/BF,MAAQ,CAAA,KAAA,CAAA,CAAOA,QAAAA,CAAAA,IAAAA,CAAAA,uBAAP,SAAOA,KAAG,MAAM,YAAY,OAAOA,SAAS,YAAY;oBAC7D,kCAAA,2BAAA;;;kBAAA,IAAInB,MAAAA,yBAAAA,OAAJ,aAAA,CAAA,6BAAIA,8CAAAA,oCAAAA,uBAAJ,WAAA,cAAIA,wDAAAA,kCAAJ,IAAA;oBACH,IAAI,CAACQ,aAAac,IAAI,CAACJ,IAAIlB,QAAQA,QAAQoB,QACzCnB,UAAUiB,IAAIlB,KAAK;0BAAEgB,KAAK,SAALA;4CAAWG,IAAI,CAACnB,IAAI;;sCAAEe,YAAY,CAAEM,CAAAA,OAAOjB,iBAAiBe,MAAMnB,IAAG,KAAMqB,KAAKN,UAAU;oCAAC;;gBAFpH,QAAK,YAAWT,kBAAkBa,0BAA7B,SAAA,6BAAA,QAAA,yBAAA;;gBAAA,KAAA,CAAA,GAAA,OAAA,WAAA,6BAAA;gBAAA;;;eAAA,cAAA,UAAA;QAAA,SAAA,GAAA,8DAAA,OAAA,YAAA,iEAAA;;sBAMLI;;;;;;wBANK,MAAA,YAAA;;;4CAAA;oDAAA;;;;;;gCAAA;sBAGP,EAAA,CAAA,SAAA,EAAA,EAAA;wBACA,MAAA,CAAOL,GAAAA,MAAAA,yBAAAA,OAAAA,SAAAA,UAAAA;oBACT;oBACIK;;wBAAe,SAAA,IAAA,IAACC;;;oBAAhBD,UAAAA,CAAe;6BAASN,EAAAA,CAAAA,GAAYhB,OAAZgB,MAAYhB,KAAAA,MAAU,CAAC,GAAG,cAAc;0BAAEwB,EAAAA,GAAAA,CAAY,CAAL,EAASD,OAAJ,CAAIA,UAAAA;oBCjBtF,EAAAE;;wBAAAA,aAAAA,GAAA,CAAA,KAAA,QAAA;;;;IAAAf,SAAAe,oBAAA;;IAAAC,KAAAA,qBAAA,SAAAA;iBAAAA;;QAAAC,OAAAA,cAAA,SAAAA;mBAAAA,IAAAA;;QAAAC,eAAAA,KAAA,SAAAA;mBAAAA;;IAAAC,cAAA,SAAAA;eAAAA,aAAAA,IAAAA,EAAAA,SAAAA,EAAAA,UAAAA;QAAAA,YAAAA,iEAAAA;;IAAA,KAAA,OAAA,CAAA,SAAA;QAAAC,GAAAC,CAAAA,MAAA,GAAAT,aAAAG;YAoCA,GAASO,CAAAA,SAAUC,IAAA,CAAA;YACjB,IAAA,CAAOA,SAAS,CAAA,0BAA2BA,KAAKC,QAAA,CAAS;gBAC3D,cAAA,GAAA,OAAA,aAAA,OAAA,YAAA,QAAA,CAAA,OAAA,MAAA,KAAA,eAAA,OAAA;YAEA,GAASC,UAAUF,IAAA;YACjB,IAAA,CAAOA,SAAS,EAAA,aAAeA,KAAKC,QAAA,CAAS;gBAC/C,cAAA,GAAA,OAAA,aAAA,OAAA,YAAA,QAAA,CAAA,OAAA,MAAA,KAAA,gBAAA,OAAA;YAEO,GAASL,aACdO,SAAA;cACAC,EAAAA,KAAAA,CAAAA,IAAAA,MAAAA,GAAAA,mDAA0B,OAC1BC,YAAAA,iEAAY;YAEZ,EAAI,EAAA,GAAA,GAAA;kBAoBYC,EAAAA,GAAAA,CAAAA,GAQZA,OARYA,WAAAA,IAQZA,uBAkHmBA,OAlHnBA,GAkHmBA,gBAAAA;YA7IrB,IAAMC,CAAAA,OAAAA,CAAS,IAAIC;cACnB,IAAMF,EAAAA,IAAAA,CAAAA,CAASC,EAAOE,OAAPF,MAAOE,KAAAA,WAAA,CAAgBN,WAAW,WAAA;YAEjD,IAAMO,cAAcJ,OAAOK,aAAA,CAAc;UACzC,IAAID,aAAa;YACfE,QAAQC,KAAA,CACN,GAAY,OAATR,WAAS,6CACZK,YAAYI,WAAA;YAEd,OAAO,0CAAA;QACT,KAAA,OAAA,GAAA;oCAEA,IAAMC,YAAYT,OAAOK,aAAA,CAAc;+BACvC,IAAI,CAACI,WAAW;kCACdH,QAAQI,IAAA,CAAK,GAAY,OAATX,WAAS;4BACzB,OAAO;SACT","sourcesContent":["\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/sdk/vastParser.ts\nvar vastParser_exports = {};\n__export(vastParser_exports, {\n createEmptyTrackingState: () => createEmptyTrackingState,\n fetchAndParseVastAd: () => fetchAndParseVastAd,\n fireTrackingPixels: () => fireTrackingPixels,\n parseVastXml: () => parseVastXml\n});\nmodule.exports = __toCommonJS(vastParser_exports);\nfunction isHlsType(type) {\n return type === \"application/x-mpegURL\" || type.includes(\"m3u8\");\n}\nfunction isMp4Type(type) {\n return type === \"video/mp4\" || type.includes(\"mp4\");\n}\nfunction parseVastXml(xmlString, filter = \"all\", logPrefix = \"[VastParser]\") {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n `${logPrefix} XML parsing error (malformed VAST XML):`,\n parserError.textContent\n );\n return null;\n }\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(`${logPrefix} No Ad element found in VAST XML`);\n return null;\n }\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n const isNoAdAvailable = adId === \"empty\" || title.toLowerCase().includes(\"no ad available\") || title.toLowerCase() === \"no ad available\";\n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + Math.round(parseFloat(durationParts[2] || \"0\"));\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n console.log(\n `${logPrefix} 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 console.log(\n `${logPrefix} MediaFile ${index}: type=\"${type}\", url=\"${url.substring(0, 80)}...\", width=\"${width}\", height=\"${height}\"`\n );\n if (!url) {\n console.warn(`${logPrefix} MediaFile ${index} has empty URL`);\n return;\n }\n const isHls = isHlsType(type);\n const isMp4 = isMp4Type(type);\n let accepted = false;\n if (filter === \"hls-only\") {\n accepted = isHls;\n } else if (filter === \"mp4-first\") {\n accepted = isMp4 || isHls;\n } else {\n accepted = true;\n }\n if (!accepted) {\n console.log(\n `${logPrefix} MediaFile ${index} ignored (type=\"${type}\" not accepted by filter \"${filter}\")`\n );\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\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 : void 0\n });\n console.log(`${logPrefix} Added MediaFile: type=\"${type}\" url=\"${url.substring(0, 80)}...\"`);\n });\n if (filter === \"mp4-first\" && mediaFiles.length > 1) {\n mediaFiles.sort((a, b) => {\n const aIsMp4 = isMp4Type(a.type) ? 0 : 1;\n const bIsMp4 = isMp4Type(b.type) ? 0 : 1;\n return aIsMp4 - bIsMp4;\n });\n }\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n `${logPrefix} No ads available (VAST response indicates no ads)`\n );\n } else {\n console.warn(`${logPrefix} No compatible media files found in VAST XML`);\n }\n return null;\n }\n const trackingUrls = {\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 xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\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;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough\n };\n } catch (error) {\n console.error(`${logPrefix} Error parsing VAST XML:`, error);\n return null;\n }\n}\nasync function fetchAndParseVastAd(vastTagUrl, filter = \"all\", logPrefix = \"[VastParser]\") {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n Accept: \"application/xml, text/xml, */*\"\n },\n referrerPolicy: \"no-referrer-when-downgrade\"\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n const vastXml = await response.text();\n console.log(`${logPrefix} VAST XML received`);\n console.log(\n `${logPrefix} VAST XML content (first 2000 chars):`,\n vastXml.substring(0, 2e3)\n );\n return parseVastXml(vastXml, filter, logPrefix);\n}\nfunction createEmptyTrackingState() {\n return {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n}\nfunction fireTrackingPixels(urls, sessionId, licenseKey, logPrefix = \"[VastParser]\") {\n if (!urls || urls.length === 0) return;\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n if (sessionId) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}session_id=${sessionId}`;\n }\n if (licenseKey) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}license_key=${licenseKey}`;\n }\n const img = new Image(1, 1);\n img.src = trackingUrl;\n console.log(`${logPrefix} Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`${logPrefix} Error firing tracking pixel:`, error);\n }\n });\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n createEmptyTrackingState,\n fetchAndParseVastAd,\n fireTrackingPixels,\n parseVastXml\n});\n","export interface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\nexport interface 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\nexport interface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\nexport type MediaFileFilter = \"hls-only\" | \"mp4-first\" | \"all\";\n\nfunction isHlsType(type: string): boolean {\n return type === \"application/x-mpegURL\" || type.includes(\"m3u8\");\n}\n\nfunction isMp4Type(type: string): boolean {\n return type === \"video/mp4\" || type.includes(\"mp4\");\n}\n\nexport function parseVastXml(\n xmlString: string,\n filter: MediaFileFilter = \"all\",\n logPrefix = \"[VastParser]\"\n): 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 `${logPrefix} 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(`${logPrefix} 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 Math.round(parseFloat(durationParts[2] || \"0\"));\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n console.log(\n `${logPrefix} 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 `${logPrefix} MediaFile ${index}: type=\"${type}\", url=\"${url.substring(0, 80)}...\", width=\"${width}\", height=\"${height}\"`\n );\n\n if (!url) {\n console.warn(`${logPrefix} MediaFile ${index} has empty URL`);\n return;\n }\n\n const isHls = isHlsType(type);\n const isMp4 = isMp4Type(type);\n\n let accepted = false;\n if (filter === \"hls-only\") {\n accepted = isHls;\n } else if (filter === \"mp4-first\") {\n accepted = isMp4 || isHls;\n } else {\n accepted = true;\n }\n\n if (!accepted) {\n console.log(\n `${logPrefix} MediaFile ${index} ignored (type=\"${type}\" not accepted by filter \"${filter}\")`\n );\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(`${logPrefix} Added MediaFile: type=\"${type}\" url=\"${url.substring(0, 80)}...\"`);\n });\n\n if (filter === \"mp4-first\" && mediaFiles.length > 1) {\n mediaFiles.sort((a, b) => {\n const aIsMp4 = isMp4Type(a.type) ? 0 : 1;\n const bIsMp4 = isMp4Type(b.type) ? 0 : 1;\n return aIsMp4 - bIsMp4;\n });\n }\n\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n `${logPrefix} No ads available (VAST response indicates no ads)`\n );\n } else {\n console.warn(`${logPrefix} No compatible 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(`${logPrefix} Error parsing VAST XML:`, error);\n return null;\n }\n}\n\nexport async function fetchAndParseVastAd(\n vastTagUrl: string,\n filter: MediaFileFilter = \"all\",\n logPrefix = \"[VastParser]\"\n): Promise<VastAd | null> {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n Accept: \"application/xml, text/xml, */*\",\n },\n referrerPolicy: \"no-referrer-when-downgrade\",\n });\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(`${logPrefix} VAST XML received`);\n console.log(\n `${logPrefix} VAST XML content (first 2000 chars):`,\n vastXml.substring(0, 2000)\n );\n\n return parseVastXml(vastXml, filter, logPrefix);\n}\n\nexport function createEmptyTrackingState() {\n return {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n}\n\nexport function fireTrackingPixels(\n urls: string[],\n sessionId?: string,\n licenseKey?: string,\n logPrefix = \"[VastParser]\"\n): 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(`${logPrefix} Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`${logPrefix} Error firing tracking pixel:`, error);\n }\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/ubuntu24-new/Dev/stormcloud-vp/lib/sdk/vastParser.cjs","../../src/sdk/vastParser.ts"],"names":["key","__defProp","Object","defineProperty","__getOwnPropDesc","getOwnPropertyDescriptor","__getOwnPropNames","getOwnPropertyNames","__hasOwnProp","prototype","hasOwnProperty","__export","target","all","name","enumerable","get","__copyProps","to","from","except","desc","call","__toCommonJS","mod","value","vastParser_exports","createEmptyTrackingState","fetchAndParseVastAd","fireTrackingPixels","parseVastXml","module","exports","isHlsType","type","includes","isMp4Type","xmlString","filter","logPrefix","xmlDoc","parser","DOMParser","parseFromString","parserError","querySelector","console","error","textContent","adElement","warn"],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2DAWaA,mCAAAA,CAAJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAVLC,YAAYC,OAAOC,cAAc;QACjCC,OAAAA,YAAmBF,IAAAA,CAAAA,EAAOG,YAAAA,OAAAA,CAAAA,SAAAA,GAAwB;gBAClDC;YAAAA,IAAAA,OAAAA,kBAAAA,GAAAA,GAAoBJ,OAAOK,CAAAA,cAA3BD,sCAAAA,gBAA2BC,IAAAA,YAAmB;YAC9CC,IAAAA,KAAAA,IAAeN,OAAOO,EAAAA,OAAS,CAACC,EAAAA,CAAAA,IAAAA,CAAAA,MAAc;QAC9CC,WAAW,kBAACC,QAAQC;QACtB,IAAK,GAAA,CAAIC,QAAQD,IACfZ,GAAAA,CAAAA,MAAUW,MAAAA,EAAQE,KAAAA,CAAM,SAAA;gBAAkBC;cAAhBC,EAAAA,CAAKH,GAAG,CAACC,GAAAA,EAAK,CAAA,YAAA,CAAA;cAAEC,EAAAA,OAAAA,kBAAAA,GAAY,WAAA,cAAZA,sCAAAA,EAAY,cAAA,IAAA;YAAK,IAAA,SAAA,KAAA;gBAC/D,IAAA,WAAA;gBACIE,IAAAA,MAAc,MAAA,CAAA,SAAA,EAAA,GAACC,IAAIC,MAAMC,QAAQC;oBAC/BF,MAAQ,CAAA,KAAA,CAAA,CAAOA,QAAAA,CAAAA,IAAAA,CAAAA,uBAAP,SAAOA,KAAG,MAAM,YAAY,OAAOA,SAAS,YAAY;oBAC7D,kCAAA,2BAAA;;;kBAAA,IAAInB,MAAAA,yBAAAA,OAAJ,aAAA,CAAA,6BAAIA,8CAAAA,oCAAAA,uBAAJ,WAAA,cAAIA,wDAAAA,kCAAJ,IAAA;oBACH,IAAI,CAACQ,aAAac,IAAI,CAACJ,IAAIlB,QAAQA,QAAQoB,QACzCnB,UAAUiB,IAAIlB,KAAK;0BAAEgB,KAAK,SAALA;4CAAWG,IAAI,CAACnB,IAAI;;sCAAEe,YAAY,CAAEM,CAAAA,OAAOjB,iBAAiBe,MAAMnB,IAAG,KAAMqB,KAAKN,UAAU;oCAAC;;gBAFpH,QAAK,YAAWT,kBAAkBa,0BAA7B,SAAA,6BAAA,QAAA,yBAAA;;gBAAA,KAAA,CAAA,GAAA,OAAA,WAAA,6BAAA;gBAAA;;;eAAA,cAAA,UAAA;QAAA,GAAA,MAAA,iEAAA,OAAA,YAAA,iEAAA;;sBAMLI;;;;;;wBANK,MAAA,YAAA;;;4CAAA;oDAAA;;;;;;gCAAA;sBAGP,EAAA,CAAA,SAAA,EAAA,EAAA;wBACA,MAAA,CAAOL,GAAAA,MAAAA,yBAAAA,OAAAA,SAAAA,UAAAA;oBACT;oBACIK;;wBAAe,SAAA,IAAA,IAACC;;;oBAAhBD,UAAAA,CAAe;6BAASN,EAAAA,CAAAA,GAAYhB,OAAZgB,MAAYhB,KAAAA,MAAU,CAAC,GAAG,cAAc;0BAAEwB,EAAAA,GAAAA,CAAY,CAAL,EAASD,OAAJ,CAAIA,UAAAA;oBCjBtF,EAAAE;;wBAAAA,aAAAA,GAAA,CAAA,KAAA,QAAA;;;;IAAAf,SAAAe,oBAAA;;IAAAC,KAAAA,qBAAA,SAAAA;iBAAAA;;QAAAC,OAAAA,cAAA,SAAAA;mBAAAA,IAAAA;;QAAAC,eAAAA,KAAA,SAAAA;mBAAAA;;IAAAC,cAAA,SAAAA;eAAAA,aAAAA,IAAAA,EAAAA,SAAAA;QAAAA,YAAAA,iEAAAA;;IAAA,KAAA,OAAA,CAAA,SAAA;QAAAC,GAAAC,CAAAA,MAAA,GAAAT,aAAAG;YAoCA,GAASO,CAAAA,SAAUC,IAAA,CAAA;YACjB,IAAA,CAAOA,SAAS,CAAA,0BAA2BA,KAAKC,QAAA,CAAS;gBAC3D,cAAA,GAAA,OAAA,aAAA,OAAA,YAAA,QAAA,CAAA,OAAA,MAAA,KAAA,eAAA,OAAA;YAEA,GAASC,UAAUF,IAAA;YACjB,IAAOA,CAAAA,KAAAA,EAAS,EAAA,MAAA,GAAA,IAAeA,KAAKC,QAAA,CAAS;YAC/C,IAAA,OAAA,GAAA,YAEO,GAASL,aACdO,SAAA;cACAC,EAAAA,GAAAA,GAAAA,CAAAA,iEAA0B,OAC1BC,YAAAA,iEAAY;YAEZ,EAAI,MAAA,GAAA,CAAA,GAAA,OAAA,WAAA,2BAAA,OAAA;gBAoBYC,CAAAA,OAAAA,eAQZA,wBAkHmBA,mCAAAA;cA7IrB,IAAMC,EAAAA,IAAAA,CAAAA,CAAS,EAAIC,OAAJ,GAAIA,QAAAA,kCAAAA;YACnB,IAAMF,SAASC,OAAOE,eAAA,CAAgBN,WAAW;UAEjD,IAAMO,cAAcJ,OAAOK,aAAA,CAAc;QACzC,IAAID,aAAa;YACfE,QAAQC,KAAA,CACN,GAAY,OAATR,WAAS,cAAA,+BACZK,YAAYI,WAAA;YAEd,CAAA,MAAO,CAAA,GAAA;oCACT;+BAEA,IAAMC,YAAYT,OAAOK,aAAA,CAAc;8BACvC,IAAI,CAACI,WAAW;4BACdH,QAAQI,IAAA,CAAK,GAAY,OAATX,WAAS;aACzB,OAAO","sourcesContent":["\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __export = (target, all) => {\n for (var name in all)\n __defProp(target, name, { get: all[name], enumerable: true });\n};\nvar __copyProps = (to, from, except, desc) => {\n if (from && typeof from === \"object\" || typeof from === \"function\") {\n for (let key of __getOwnPropNames(from))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });\n }\n return to;\n};\nvar __toCommonJS = (mod) => __copyProps(__defProp({}, \"__esModule\", { value: true }), mod);\n\n// src/sdk/vastParser.ts\nvar vastParser_exports = {};\n__export(vastParser_exports, {\n createEmptyTrackingState: () => createEmptyTrackingState,\n fetchAndParseVastAd: () => fetchAndParseVastAd,\n fireTrackingPixels: () => fireTrackingPixels,\n parseVastXml: () => parseVastXml\n});\nmodule.exports = __toCommonJS(vastParser_exports);\nfunction isHlsType(type) {\n return type === \"application/x-mpegURL\" || type.includes(\"m3u8\");\n}\nfunction isMp4Type(type) {\n return type === \"video/mp4\" || type.includes(\"mp4\");\n}\nfunction parseVastXml(xmlString, filter = \"all\", logPrefix = \"[VastParser]\") {\n try {\n const parser = new DOMParser();\n const xmlDoc = parser.parseFromString(xmlString, \"text/xml\");\n const parserError = xmlDoc.querySelector(\"parsererror\");\n if (parserError) {\n console.error(\n `${logPrefix} XML parsing error (malformed VAST XML):`,\n parserError.textContent\n );\n return null;\n }\n const adElement = xmlDoc.querySelector(\"Ad\");\n if (!adElement) {\n console.warn(`${logPrefix} No Ad element found in VAST XML`);\n return null;\n }\n const adId = adElement.getAttribute(\"id\") || \"unknown\";\n const title = xmlDoc.querySelector(\"AdTitle\")?.textContent || \"Ad\";\n const isNoAdAvailable = adId === \"empty\" || title.toLowerCase().includes(\"no ad available\") || title.toLowerCase() === \"no ad available\";\n const durationText = xmlDoc.querySelector(\"Duration\")?.textContent || \"00:00:30\";\n const durationParts = durationText.split(\":\");\n const duration = parseInt(durationParts[0] || \"0\", 10) * 3600 + parseInt(durationParts[1] || \"0\", 10) * 60 + Math.round(parseFloat(durationParts[2] || \"0\"));\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles = [];\n console.log(\n `${logPrefix} 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 console.log(\n `${logPrefix} MediaFile ${index}: type=\"${type}\", url=\"${url.substring(0, 80)}...\", width=\"${width}\", height=\"${height}\"`\n );\n if (!url) {\n console.warn(`${logPrefix} MediaFile ${index} has empty URL`);\n return;\n }\n const isHls = isHlsType(type);\n const isMp4 = isMp4Type(type);\n let accepted = false;\n if (filter === \"hls-only\") {\n accepted = isHls;\n } else if (filter === \"mp4-first\") {\n accepted = isMp4 || isHls;\n } else {\n accepted = true;\n }\n if (!accepted) {\n console.log(\n `${logPrefix} MediaFile ${index} ignored (type=\"${type}\" not accepted by filter \"${filter}\")`\n );\n return;\n }\n const bitrateAttr = mf.getAttribute(\"bitrate\");\n const bitrateValue = bitrateAttr ? parseInt(bitrateAttr, 10) : void 0;\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 : void 0\n });\n console.log(`${logPrefix} Added MediaFile: type=\"${type}\" url=\"${url.substring(0, 80)}...\"`);\n });\n if (filter === \"mp4-first\" && mediaFiles.length > 1) {\n mediaFiles.sort((a, b) => {\n const aIsMp4 = isMp4Type(a.type) ? 0 : 1;\n const bIsMp4 = isMp4Type(b.type) ? 0 : 1;\n return aIsMp4 - bIsMp4;\n });\n }\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n `${logPrefix} No ads available (VAST response indicates no ads)`\n );\n } else {\n console.warn(`${logPrefix} No compatible media files found in VAST XML`);\n }\n return null;\n }\n const trackingUrls = {\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 xmlDoc.querySelectorAll(\"Impression\").forEach((el) => {\n const url = el.textContent?.trim();\n if (url) trackingUrls.impression.push(url);\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;\n if (trackingUrls[eventKey]) {\n trackingUrls[eventKey].push(url);\n }\n }\n });\n const clickThrough = xmlDoc.querySelector(\"ClickThrough\")?.textContent?.trim();\n return {\n id: adId,\n title,\n duration,\n mediaFiles,\n trackingUrls,\n clickThrough\n };\n } catch (error) {\n console.error(`${logPrefix} Error parsing VAST XML:`, error);\n return null;\n }\n}\nasync function fetchAndParseVastAd(vastTagUrl, filter = \"all\", logPrefix = \"[VastParser]\") {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n Accept: \"application/xml, text/xml, */*\"\n },\n referrerPolicy: \"no-referrer-when-downgrade\"\n });\n if (!response.ok) {\n throw new Error(`Failed to fetch VAST: ${response.statusText}`);\n }\n const vastXml = await response.text();\n console.log(`${logPrefix} VAST XML received`);\n console.log(\n `${logPrefix} VAST XML content (first 2000 chars):`,\n vastXml.substring(0, 2e3)\n );\n return parseVastXml(vastXml, filter, logPrefix);\n}\nfunction createEmptyTrackingState() {\n return {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false\n };\n}\nfunction fireTrackingPixels(urls, sessionId, logPrefix = \"[VastParser]\") {\n if (!urls || urls.length === 0) return;\n urls.forEach((url) => {\n try {\n let trackingUrl = url;\n if (sessionId) {\n trackingUrl = `${trackingUrl}${trackingUrl.includes(\"?\") ? \"&\" : \"?\"}session_id=${sessionId}`;\n }\n const img = new Image(1, 1);\n img.onerror = () => {\n };\n img.src = trackingUrl;\n console.log(`${logPrefix} Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`${logPrefix} Error firing tracking pixel:`, error);\n }\n });\n}\n// Annotate the CommonJS export names for ESM import in node:\n0 && (module.exports = {\n createEmptyTrackingState,\n fetchAndParseVastAd,\n fireTrackingPixels,\n parseVastXml\n});\n","export interface VastMediaFile {\n url: string;\n type: string;\n width: number;\n height: number;\n bitrate?: number | undefined;\n}\n\nexport interface 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\nexport interface VastAd {\n id: string;\n title: string;\n duration: number;\n mediaFiles: VastMediaFile[];\n trackingUrls: VastTrackingUrls;\n clickThrough?: string | undefined;\n}\n\nexport type MediaFileFilter = \"hls-only\" | \"mp4-first\" | \"all\";\n\nfunction isHlsType(type: string): boolean {\n return type === \"application/x-mpegURL\" || type.includes(\"m3u8\");\n}\n\nfunction isMp4Type(type: string): boolean {\n return type === \"video/mp4\" || type.includes(\"mp4\");\n}\n\nexport function parseVastXml(\n xmlString: string,\n filter: MediaFileFilter = \"all\",\n logPrefix = \"[VastParser]\"\n): 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 `${logPrefix} 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(`${logPrefix} 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 Math.round(parseFloat(durationParts[2] || \"0\"));\n\n const mediaFileElements = xmlDoc.querySelectorAll(\"MediaFile\");\n const mediaFiles: VastMediaFile[] = [];\n\n console.log(\n `${logPrefix} 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 `${logPrefix} MediaFile ${index}: type=\"${type}\", url=\"${url.substring(0, 80)}...\", width=\"${width}\", height=\"${height}\"`\n );\n\n if (!url) {\n console.warn(`${logPrefix} MediaFile ${index} has empty URL`);\n return;\n }\n\n const isHls = isHlsType(type);\n const isMp4 = isMp4Type(type);\n\n let accepted = false;\n if (filter === \"hls-only\") {\n accepted = isHls;\n } else if (filter === \"mp4-first\") {\n accepted = isMp4 || isHls;\n } else {\n accepted = true;\n }\n\n if (!accepted) {\n console.log(\n `${logPrefix} MediaFile ${index} ignored (type=\"${type}\" not accepted by filter \"${filter}\")`\n );\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(`${logPrefix} Added MediaFile: type=\"${type}\" url=\"${url.substring(0, 80)}...\"`);\n });\n\n if (filter === \"mp4-first\" && mediaFiles.length > 1) {\n mediaFiles.sort((a, b) => {\n const aIsMp4 = isMp4Type(a.type) ? 0 : 1;\n const bIsMp4 = isMp4Type(b.type) ? 0 : 1;\n return aIsMp4 - bIsMp4;\n });\n }\n\n if (mediaFiles.length === 0) {\n if (isNoAdAvailable) {\n console.warn(\n `${logPrefix} No ads available (VAST response indicates no ads)`\n );\n } else {\n console.warn(`${logPrefix} No compatible 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(`${logPrefix} Error parsing VAST XML:`, error);\n return null;\n }\n}\n\nexport async function fetchAndParseVastAd(\n vastTagUrl: string,\n filter: MediaFileFilter = \"all\",\n logPrefix = \"[VastParser]\"\n): Promise<VastAd | null> {\n const response = await fetch(vastTagUrl, {\n mode: \"cors\",\n credentials: \"include\",\n headers: {\n Accept: \"application/xml, text/xml, */*\",\n },\n referrerPolicy: \"no-referrer-when-downgrade\",\n });\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(`${logPrefix} VAST XML received`);\n console.log(\n `${logPrefix} VAST XML content (first 2000 chars):`,\n vastXml.substring(0, 2000)\n );\n\n return parseVastXml(vastXml, filter, logPrefix);\n}\n\nexport function createEmptyTrackingState() {\n return {\n impression: false,\n start: false,\n firstQuartile: false,\n midpoint: false,\n thirdQuartile: false,\n complete: false,\n };\n}\n\nexport function fireTrackingPixels(\n urls: string[],\n sessionId?: string,\n logPrefix = \"[VastParser]\"\n): 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 const img = new Image(1, 1);\n img.onerror = () => {\n // 502 or other network errors are fire-and-forget; do not affect playback\n };\n img.src = trackingUrl;\n console.log(`${logPrefix} Fired tracking pixel: ${trackingUrl}`);\n } catch (error) {\n console.warn(`${logPrefix} Error firing tracking pixel:`, error);\n }\n });\n}\n"]}
|
package/lib/sdk/vastParser.d.cts
CHANGED
|
@@ -40,6 +40,6 @@ declare function createEmptyTrackingState(): {
|
|
|
40
40
|
thirdQuartile: boolean;
|
|
41
41
|
complete: boolean;
|
|
42
42
|
};
|
|
43
|
-
declare function fireTrackingPixels(urls: string[], sessionId?: string,
|
|
43
|
+
declare function fireTrackingPixels(urls: string[], sessionId?: string, logPrefix?: string): void;
|
|
44
44
|
|
|
45
45
|
export { type MediaFileFilter, type VastAd, type VastMediaFile, type VastTrackingUrls, createEmptyTrackingState, fetchAndParseVastAd, fireTrackingPixels, parseVastXml };
|
|
@@ -564,8 +564,8 @@ function createEmptyTrackingState() {
|
|
|
564
564
|
complete: false
|
|
565
565
|
};
|
|
566
566
|
}
|
|
567
|
-
function fireTrackingPixels(urls, sessionId
|
|
568
|
-
var logPrefix = arguments.length >
|
|
567
|
+
function fireTrackingPixels(urls, sessionId) {
|
|
568
|
+
var logPrefix = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : "[VastParser]";
|
|
569
569
|
if (!urls || urls.length === 0) return;
|
|
570
570
|
urls.forEach(function(url) {
|
|
571
571
|
try {
|
|
@@ -573,10 +573,8 @@ function fireTrackingPixels(urls, sessionId, licenseKey) {
|
|
|
573
573
|
if (sessionId) {
|
|
574
574
|
trackingUrl = "".concat(trackingUrl).concat(trackingUrl.includes("?") ? "&" : "?", "session_id=").concat(sessionId);
|
|
575
575
|
}
|
|
576
|
-
if (licenseKey) {
|
|
577
|
-
trackingUrl = "".concat(trackingUrl).concat(trackingUrl.includes("?") ? "&" : "?", "license_key=").concat(licenseKey);
|
|
578
|
-
}
|
|
579
576
|
var img = new Image(1, 1);
|
|
577
|
+
img.onerror = function() {};
|
|
580
578
|
img.src = trackingUrl;
|
|
581
579
|
console.log("".concat(logPrefix, " Fired tracking pixel: ").concat(trackingUrl));
|
|
582
580
|
} catch (error) {
|
|
@@ -977,7 +975,7 @@ function createPrebidController(contentVideo, options) {
|
|
|
977
975
|
return "session-".concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9));
|
|
978
976
|
}
|
|
979
977
|
function fireTrackingPixels2(urls) {
|
|
980
|
-
fireTrackingPixels(urls, sessionId,
|
|
978
|
+
fireTrackingPixels(urls, sessionId, LOG);
|
|
981
979
|
}
|
|
982
980
|
function getMainStreamQuality() {
|
|
983
981
|
if (!mainHlsInstance || !mainHlsInstance.levels) {
|
|
@@ -2714,6 +2712,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
2714
2712
|
this.totalAdRequestsInBreak = 0;
|
|
2715
2713
|
this.maxTotalAdRequestsPerBreak = 20;
|
|
2716
2714
|
this.pendingAdBreak = null;
|
|
2715
|
+
this.prefetchAdPromise = null;
|
|
2716
|
+
this.savedMutedStateBeforeScte = null;
|
|
2717
2717
|
this.consecutiveFailures = 0;
|
|
2718
2718
|
this.maxConsecutiveFailures = 5;
|
|
2719
2719
|
this.lastAdRequestTime = 0;
|
|
@@ -3189,6 +3189,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
3189
3189
|
}
|
|
3190
3190
|
}
|
|
3191
3191
|
console.error("[AD-ERROR]", errorMessage, errorPayload || "");
|
|
3192
|
+
_this.adController.stop().catch(function() {});
|
|
3192
3193
|
_this.handleAdFailure();
|
|
3193
3194
|
});
|
|
3194
3195
|
this.adController.on("content_pause", function() {
|
|
@@ -3231,6 +3232,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
3231
3232
|
_this.activeAdRequestToken = null;
|
|
3232
3233
|
_this.showAds = false;
|
|
3233
3234
|
if (!_this.inAdBreak) {
|
|
3235
|
+
if (_this.config.debugAdTiming) {
|
|
3236
|
+
console.log("[StormcloudVideoPlayer] content_resume: break already ended (e.g. by CUE-IN or handleAdPodComplete), skipping next-ad path");
|
|
3237
|
+
}
|
|
3234
3238
|
return;
|
|
3235
3239
|
}
|
|
3236
3240
|
_this.consecutiveFailures = 0;
|
|
@@ -3243,6 +3247,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
3243
3247
|
if (remaining > 500) {
|
|
3244
3248
|
_this.tryNextAvailableAdWithRateLimit();
|
|
3245
3249
|
} else {
|
|
3250
|
+
if (_this.config.debugAdTiming) {
|
|
3251
|
+
console.log("[StormcloudVideoPlayer] content_resume: remaining time too low to try next ad, ending ad pod");
|
|
3252
|
+
}
|
|
3246
3253
|
_this.handleAdPodComplete();
|
|
3247
3254
|
}
|
|
3248
3255
|
});
|
|
@@ -3251,6 +3258,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
3251
3258
|
{
|
|
3252
3259
|
key: "recreateAdController",
|
|
3253
3260
|
value: function recreateAdController() {
|
|
3261
|
+
this.prefetchAdPromise = null;
|
|
3254
3262
|
var shouldShowPlaceholder = this.inAdBreak && this.showAds;
|
|
3255
3263
|
if (shouldShowPlaceholder && this.adController) {
|
|
3256
3264
|
this.showPlaceholderLayer();
|
|
@@ -3579,6 +3587,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
3579
3587
|
if (marker.type === "start") {
|
|
3580
3588
|
var _this_config_immediateManifestAds;
|
|
3581
3589
|
var _this_pendingAdBreak;
|
|
3590
|
+
this.savedMutedStateBeforeScte = {
|
|
3591
|
+
muted: this.video.muted,
|
|
3592
|
+
volume: this.video.volume
|
|
3593
|
+
};
|
|
3594
|
+
this.adController.updateOriginalMutedState(this.video.muted, this.video.volume);
|
|
3582
3595
|
if (!this.video.muted) {
|
|
3583
3596
|
this.video.muted = true;
|
|
3584
3597
|
this.video.volume = 0;
|
|
@@ -3701,9 +3714,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
3701
3714
|
activeAdRequest: this.activeAdRequestToken !== null
|
|
3702
3715
|
});
|
|
3703
3716
|
}
|
|
3704
|
-
if (adPlaying || remaining >
|
|
3717
|
+
if (adPlaying || remaining > 500) {
|
|
3705
3718
|
if (this.config.debugAdTiming) {
|
|
3706
|
-
console.log("[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active");
|
|
3719
|
+
console.log("[StormcloudVideoPlayer] Ignoring premature SCTE-35 end marker - ads still active or time remaining");
|
|
3707
3720
|
}
|
|
3708
3721
|
return;
|
|
3709
3722
|
}
|
|
@@ -4020,6 +4033,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
4020
4033
|
{
|
|
4021
4034
|
key: "startAdPrefetch",
|
|
4022
4035
|
value: function startAdPrefetch(marker, fragmentSn) {
|
|
4036
|
+
var _this = this;
|
|
4023
4037
|
if (this.pendingAdBreak || this.inAdBreak) {
|
|
4024
4038
|
return;
|
|
4025
4039
|
}
|
|
@@ -4031,8 +4045,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
4031
4045
|
isFetching: false,
|
|
4032
4046
|
fetchStartTime: Date.now()
|
|
4033
4047
|
});
|
|
4048
|
+
this.prefetchAdPromise = this.adController.requestAds().catch(function() {
|
|
4049
|
+
if (_this.config.debugAdTiming) {
|
|
4050
|
+
console.log("[PREFETCH] Prebid auction prefetch failed, will request at playback time");
|
|
4051
|
+
}
|
|
4052
|
+
});
|
|
4034
4053
|
if (this.config.debugAdTiming) {
|
|
4035
|
-
console.log("[PREFETCH] Ad break marker registered, auction
|
|
4054
|
+
console.log("[PREFETCH] Ad break marker registered, auction prefetch started");
|
|
4036
4055
|
}
|
|
4037
4056
|
}
|
|
4038
4057
|
},
|
|
@@ -4043,6 +4062,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
4043
4062
|
clearTimeout(this.prefetchTimerId);
|
|
4044
4063
|
this.prefetchTimerId = void 0;
|
|
4045
4064
|
}
|
|
4065
|
+
this.prefetchAdPromise = null;
|
|
4046
4066
|
this.pendingAdBreak = null;
|
|
4047
4067
|
}
|
|
4048
4068
|
},
|
|
@@ -4050,7 +4070,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
4050
4070
|
key: "handleAdStart",
|
|
4051
4071
|
value: function handleAdStart(_marker) {
|
|
4052
4072
|
return _async_to_generator(function() {
|
|
4053
|
-
var adBreakDurationMs, mode,
|
|
4073
|
+
var _this_savedMutedStateBeforeScte, adBreakDurationMs, mode, state, unused, unused1, adLoadedInfo, adVolume, error;
|
|
4054
4074
|
return _ts_generator(this, function(_state) {
|
|
4055
4075
|
switch(_state.label){
|
|
4056
4076
|
case 0:
|
|
@@ -4063,9 +4083,12 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
4063
4083
|
this.continuousFetchingActive = true;
|
|
4064
4084
|
this.isShowingPlaceholder = false;
|
|
4065
4085
|
this.totalAdRequestsInBreak = 0;
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4086
|
+
state = (_this_savedMutedStateBeforeScte = this.savedMutedStateBeforeScte) !== null && _this_savedMutedStateBeforeScte !== void 0 ? _this_savedMutedStateBeforeScte : {
|
|
4087
|
+
muted: this.video.muted,
|
|
4088
|
+
volume: this.video.volume
|
|
4089
|
+
};
|
|
4090
|
+
this.adController.updateOriginalMutedState(state.muted, state.volume);
|
|
4091
|
+
this.savedMutedStateBeforeScte = null;
|
|
4069
4092
|
if (!this.video.muted) {
|
|
4070
4093
|
this.video.muted = true;
|
|
4071
4094
|
this.video.volume = 0;
|
|
@@ -4084,25 +4107,94 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
4084
4107
|
if (this.expectedAdBreakDurationMs == null && adBreakDurationMs != null) {
|
|
4085
4108
|
this.expectedAdBreakDurationMs = adBreakDurationMs;
|
|
4086
4109
|
}
|
|
4087
|
-
this.clearPendingAdBreak();
|
|
4088
4110
|
if (this.config.debugAdTiming) {
|
|
4089
|
-
console.log("[CONTINUOUS-FETCH] \uD83D\uDCCB Prebid auction
|
|
4111
|
+
console.log("[CONTINUOUS-FETCH] \uD83D\uDCCB Prebid auction (prefetch or requestAds)");
|
|
4090
4112
|
}
|
|
4091
4113
|
_state.label = 1;
|
|
4092
4114
|
case 1:
|
|
4093
4115
|
_state.trys.push([
|
|
4094
4116
|
1,
|
|
4095
|
-
|
|
4117
|
+
6,
|
|
4096
4118
|
,
|
|
4097
|
-
|
|
4119
|
+
12
|
|
4098
4120
|
]);
|
|
4099
4121
|
this.lastAdRequestTime = Date.now();
|
|
4122
|
+
if (!this.prefetchAdPromise) return [
|
|
4123
|
+
3,
|
|
4124
|
+
3
|
|
4125
|
+
];
|
|
4100
4126
|
return [
|
|
4101
4127
|
4,
|
|
4102
|
-
this.
|
|
4128
|
+
this.prefetchAdPromise
|
|
4103
4129
|
];
|
|
4104
4130
|
case 2:
|
|
4105
4131
|
_state.sent();
|
|
4132
|
+
this.prefetchAdPromise = null;
|
|
4133
|
+
return [
|
|
4134
|
+
3,
|
|
4135
|
+
5
|
|
4136
|
+
];
|
|
4137
|
+
case 3:
|
|
4138
|
+
return [
|
|
4139
|
+
4,
|
|
4140
|
+
this.adController.requestAds()
|
|
4141
|
+
];
|
|
4142
|
+
case 4:
|
|
4143
|
+
_state.sent();
|
|
4144
|
+
_state.label = 5;
|
|
4145
|
+
case 5:
|
|
4146
|
+
return [
|
|
4147
|
+
3,
|
|
4148
|
+
12
|
|
4149
|
+
];
|
|
4150
|
+
case 6:
|
|
4151
|
+
unused = _state.sent();
|
|
4152
|
+
_state.label = 7;
|
|
4153
|
+
case 7:
|
|
4154
|
+
_state.trys.push([
|
|
4155
|
+
7,
|
|
4156
|
+
9,
|
|
4157
|
+
,
|
|
4158
|
+
11
|
|
4159
|
+
]);
|
|
4160
|
+
return [
|
|
4161
|
+
4,
|
|
4162
|
+
this.adController.requestAds()
|
|
4163
|
+
];
|
|
4164
|
+
case 8:
|
|
4165
|
+
_state.sent();
|
|
4166
|
+
return [
|
|
4167
|
+
3,
|
|
4168
|
+
11
|
|
4169
|
+
];
|
|
4170
|
+
case 9:
|
|
4171
|
+
unused1 = _state.sent();
|
|
4172
|
+
this.clearPendingAdBreak();
|
|
4173
|
+
this.consecutiveFailures++;
|
|
4174
|
+
return [
|
|
4175
|
+
4,
|
|
4176
|
+
this.tryNextAvailableAdWithRateLimit()
|
|
4177
|
+
];
|
|
4178
|
+
case 10:
|
|
4179
|
+
_state.sent();
|
|
4180
|
+
return [
|
|
4181
|
+
2
|
|
4182
|
+
];
|
|
4183
|
+
case 11:
|
|
4184
|
+
return [
|
|
4185
|
+
3,
|
|
4186
|
+
12
|
|
4187
|
+
];
|
|
4188
|
+
case 12:
|
|
4189
|
+
this.clearPendingAdBreak();
|
|
4190
|
+
_state.label = 13;
|
|
4191
|
+
case 13:
|
|
4192
|
+
_state.trys.push([
|
|
4193
|
+
13,
|
|
4194
|
+
15,
|
|
4195
|
+
,
|
|
4196
|
+
17
|
|
4197
|
+
]);
|
|
4106
4198
|
if (this.config.licenseKey) {
|
|
4107
4199
|
adLoadedInfo = {
|
|
4108
4200
|
source: this.getAdSource(),
|
|
@@ -4119,19 +4211,19 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
4119
4211
|
4,
|
|
4120
4212
|
this.adController.play()
|
|
4121
4213
|
];
|
|
4122
|
-
case
|
|
4214
|
+
case 14:
|
|
4123
4215
|
_state.sent();
|
|
4124
4216
|
if (this.expectedAdBreakDurationMs != null) {
|
|
4125
4217
|
this.currentAdBreakStartWallClockMs = Date.now();
|
|
4126
4218
|
this.scheduleAdStopCountdown(this.expectedAdBreakDurationMs);
|
|
4127
4219
|
}
|
|
4128
|
-
adVolume =
|
|
4220
|
+
adVolume = state.muted ? 0 : state.volume;
|
|
4129
4221
|
this.adController.setAdVolume(adVolume);
|
|
4130
4222
|
return [
|
|
4131
4223
|
3,
|
|
4132
|
-
|
|
4224
|
+
17
|
|
4133
4225
|
];
|
|
4134
|
-
case
|
|
4226
|
+
case 15:
|
|
4135
4227
|
error = _state.sent();
|
|
4136
4228
|
if (this.config.debugAdTiming) {
|
|
4137
4229
|
console.warn("[CONTINUOUS-FETCH] \u26A0\uFE0F First ad request failed:", error);
|
|
@@ -4141,13 +4233,13 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
|
|
|
4141
4233
|
4,
|
|
4142
4234
|
this.tryNextAvailableAdWithRateLimit()
|
|
4143
4235
|
];
|
|
4144
|
-
case
|
|
4236
|
+
case 16:
|
|
4145
4237
|
_state.sent();
|
|
4146
4238
|
return [
|
|
4147
4239
|
3,
|
|
4148
|
-
|
|
4240
|
+
17
|
|
4149
4241
|
];
|
|
4150
|
-
case
|
|
4242
|
+
case 17:
|
|
4151
4243
|
return [
|
|
4152
4244
|
2
|
|
4153
4245
|
];
|