stormcloud-video-player 0.8.4 → 0.8.5

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/lib/index.d.cts CHANGED
@@ -38,6 +38,10 @@ interface StormcloudVideoPlayerConfig {
38
38
  vmapUrl?: string;
39
39
  vastMode?: 'adstorm' | 'default';
40
40
  minSegmentsBeforePlay?: number;
41
+ deviceId?: string;
42
+ deviceIdType?: string;
43
+ limitAdTracking?: boolean;
44
+ adTest?: boolean;
41
45
  }
42
46
  interface AdController {
43
47
  initialize: () => void;
@@ -215,6 +219,11 @@ declare class StormcloudVideoPlayer {
215
219
  private adDetectSentForCurrentBreak;
216
220
  private palNonce;
217
221
  private palPlaybackStarted;
222
+ private readonly streamCorrelator;
223
+ private consentSignals;
224
+ private podCounter;
225
+ private podAssignedByPrefetch;
226
+ private adRequestPositionInBreak;
218
227
  constructor(config: StormcloudVideoPlayerConfig);
219
228
  private createAdPlayer;
220
229
  load(): Promise<void>;
@@ -278,6 +287,7 @@ declare class StormcloudVideoPlayer {
278
287
  getCurrentAdIndex(): number;
279
288
  getTotalAdsInBreak(): number;
280
289
  getAdRemainingMs(): number;
290
+ private beginNewAdPod;
281
291
  private generateVastUrlsWithCorrelators;
282
292
  isAdPlaying(): boolean;
283
293
  isShowingAds(): boolean;
package/lib/index.d.ts CHANGED
@@ -38,6 +38,10 @@ interface StormcloudVideoPlayerConfig {
38
38
  vmapUrl?: string;
39
39
  vastMode?: 'adstorm' | 'default';
40
40
  minSegmentsBeforePlay?: number;
41
+ deviceId?: string;
42
+ deviceIdType?: string;
43
+ limitAdTracking?: boolean;
44
+ adTest?: boolean;
41
45
  }
42
46
  interface AdController {
43
47
  initialize: () => void;
@@ -215,6 +219,11 @@ declare class StormcloudVideoPlayer {
215
219
  private adDetectSentForCurrentBreak;
216
220
  private palNonce;
217
221
  private palPlaybackStarted;
222
+ private readonly streamCorrelator;
223
+ private consentSignals;
224
+ private podCounter;
225
+ private podAssignedByPrefetch;
226
+ private adRequestPositionInBreak;
218
227
  constructor(config: StormcloudVideoPlayerConfig);
219
228
  private createAdPlayer;
220
229
  load(): Promise<void>;
@@ -278,6 +287,7 @@ declare class StormcloudVideoPlayer {
278
287
  getCurrentAdIndex(): number;
279
288
  getTotalAdsInBreak(): number;
280
289
  getAdRemainingMs(): number;
290
+ private beginNewAdPod;
281
291
  private generateVastUrlsWithCorrelators;
282
292
  isAdPlaying(): boolean;
283
293
  isShowingAds(): boolean;
package/lib/index.js CHANGED
@@ -2236,6 +2236,166 @@ function initializePolyfills() {
2236
2236
  polyfillTextEncoder();
2237
2237
  polyfillPromiseFinally();
2238
2238
  }
2239
+ // src/utils/vastMacros.ts
2240
+ function generateCorrelator() {
2241
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
2242
+ try {
2243
+ var _buf_, _buf_1;
2244
+ var buf = new Uint32Array(2);
2245
+ crypto.getRandomValues(buf);
2246
+ var value = ((_buf_ = buf[0]) !== null && _buf_ !== void 0 ? _buf_ : 0) * 2097152 + (((_buf_1 = buf[1]) !== null && _buf_1 !== void 0 ? _buf_1 : 0) & 2097151);
2247
+ if (value > 0) {
2248
+ return String(value);
2249
+ }
2250
+ } catch (unused) {}
2251
+ }
2252
+ return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER) + 1);
2253
+ }
2254
+ var UNEXPANDED_MACRO_PATTERN = /^(\[[^\]]*\]|\{[^}]*\}|%%[^%]*%%)$/;
2255
+ function applyVastMacros(baseUrl, ctx) {
2256
+ var url;
2257
+ try {
2258
+ url = new URL(baseUrl);
2259
+ } catch (unused) {
2260
+ return replaceCorrelatorFallback(baseUrl, ctx.correlator);
2261
+ }
2262
+ var params = url.searchParams;
2263
+ params.set("correlator", ctx.correlator);
2264
+ params.set("scor", ctx.streamCorrelator);
2265
+ if (ctx.pod != null) {
2266
+ params.set("pod", String(ctx.pod));
2267
+ }
2268
+ if (ctx.adPosition != null) {
2269
+ params.set("ppos", String(ctx.adPosition));
2270
+ }
2271
+ if (ctx.pageUrl) {
2272
+ params.set("url", ctx.pageUrl);
2273
+ params.set("description_url", ctx.pageUrl);
2274
+ }
2275
+ if (ctx.adWillPlayMuted != null) {
2276
+ params.set("vpmute", ctx.adWillPlayMuted ? "1" : "0");
2277
+ }
2278
+ if (ctx.adWillAutoPlay != null) {
2279
+ params.set("vpa", ctx.adWillAutoPlay ? "auto" : "click");
2280
+ }
2281
+ if (ctx.deviceId && ctx.deviceIdType) {
2282
+ params.set("rdid", ctx.deviceId);
2283
+ params.set("idtype", ctx.deviceIdType);
2284
+ params.set("is_lat", ctx.limitAdTracking ? "1" : "0");
2285
+ } else {
2286
+ params.delete("rdid");
2287
+ params.delete("idtype");
2288
+ params.delete("is_lat");
2289
+ }
2290
+ var consent = ctx.consent;
2291
+ if ((consent === null || consent === void 0 ? void 0 : consent.gdpr) != null) {
2292
+ params.set("gdpr", consent.gdpr);
2293
+ }
2294
+ if ((consent === null || consent === void 0 ? void 0 : consent.gdprConsent) != null) {
2295
+ params.set("gdpr_consent", consent.gdprConsent);
2296
+ }
2297
+ if ((consent === null || consent === void 0 ? void 0 : consent.usPrivacy) != null) {
2298
+ params.set("us_privacy", consent.usPrivacy);
2299
+ }
2300
+ if (ctx.adTest) {
2301
+ params.set("adtest", "on");
2302
+ }
2303
+ var staleKeys = [];
2304
+ params.forEach(function(value, key) {
2305
+ if (UNEXPANDED_MACRO_PATTERN.test(value)) {
2306
+ staleKeys.push(key);
2307
+ }
2308
+ });
2309
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
2310
+ try {
2311
+ for(var _iterator = staleKeys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
2312
+ var key = _step.value;
2313
+ params.delete(key);
2314
+ }
2315
+ } catch (err) {
2316
+ _didIteratorError = true;
2317
+ _iteratorError = err;
2318
+ } finally{
2319
+ try {
2320
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
2321
+ _iterator.return();
2322
+ }
2323
+ } finally{
2324
+ if (_didIteratorError) {
2325
+ throw _iteratorError;
2326
+ }
2327
+ }
2328
+ }
2329
+ return url.toString();
2330
+ }
2331
+ function replaceCorrelatorFallback(baseUrl, correlator) {
2332
+ var correlatorRegex = /([?&])correlator=([^&]*)/;
2333
+ if (correlatorRegex.test(baseUrl)) {
2334
+ return baseUrl.replace(correlatorRegex, "$1correlator=".concat(correlator));
2335
+ }
2336
+ var sep = baseUrl.includes("?") ? "&" : "?";
2337
+ return "".concat(baseUrl).concat(sep, "correlator=").concat(correlator);
2338
+ }
2339
+ function fetchConsentSignals() {
2340
+ var timeoutMs = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 1500;
2341
+ var signals = {};
2342
+ if (typeof window === "undefined") {
2343
+ return Promise.resolve(signals);
2344
+ }
2345
+ var tasks = [];
2346
+ var tcfApi = window.__tcfapi;
2347
+ if (typeof tcfApi === "function") {
2348
+ tasks.push(new Promise(function(resolve) {
2349
+ var settled = false;
2350
+ try {
2351
+ tcfApi("addEventListener", 2, function(tcData, success) {
2352
+ if (settled) return;
2353
+ if (success && tcData && (tcData.eventStatus === "tcloaded" || tcData.eventStatus === "useractioncomplete")) {
2354
+ settled = true;
2355
+ signals.gdpr = tcData.gdprApplies ? "1" : "0";
2356
+ if (typeof tcData.tcString === "string" && tcData.tcString) {
2357
+ signals.gdprConsent = tcData.tcString;
2358
+ }
2359
+ try {
2360
+ tcfApi("removeEventListener", 2, function() {}, tcData.listenerId);
2361
+ } catch (unused) {}
2362
+ resolve();
2363
+ }
2364
+ });
2365
+ } catch (unused) {
2366
+ resolve();
2367
+ }
2368
+ setTimeout(function() {
2369
+ if (!settled) {
2370
+ settled = true;
2371
+ resolve();
2372
+ }
2373
+ }, timeoutMs);
2374
+ }));
2375
+ }
2376
+ var uspApi = window.__uspapi;
2377
+ if (typeof uspApi === "function") {
2378
+ tasks.push(new Promise(function(resolve) {
2379
+ try {
2380
+ uspApi("getUSPData", 1, function(data, success) {
2381
+ if (success && typeof (data === null || data === void 0 ? void 0 : data.uspString) === "string" && data.uspString) {
2382
+ signals.usPrivacy = data.uspString;
2383
+ }
2384
+ resolve();
2385
+ });
2386
+ } catch (unused) {
2387
+ resolve();
2388
+ }
2389
+ setTimeout(resolve, timeoutMs);
2390
+ }));
2391
+ }
2392
+ if (tasks.length === 0) {
2393
+ return Promise.resolve(signals);
2394
+ }
2395
+ return Promise.all(tasks).then(function() {
2396
+ return signals;
2397
+ });
2398
+ }
2239
2399
  // src/utils/browserCompat.ts
2240
2400
  function getChromeVersion(ua) {
2241
2401
  var match = ua.match(/Chrome\/(\d+)/);
@@ -2485,6 +2645,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2485
2645
  this.preloadPoolLoopRunning = false;
2486
2646
  this.adDetectSentForCurrentBreak = false;
2487
2647
  this.palPlaybackStarted = false;
2648
+ this.streamCorrelator = generateCorrelator();
2649
+ this.consentSignals = {};
2650
+ this.podCounter = 0;
2651
+ this.podAssignedByPrefetch = false;
2652
+ this.adRequestPositionInBreak = 0;
2488
2653
  this.continuousFetchLoopRunning = false;
2489
2654
  initializePolyfills();
2490
2655
  var browserOverrides = getBrowserConfigOverrides();
@@ -2557,6 +2722,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
2557
2722
  adWillPlayMuted: !!this.config.muted,
2558
2723
  continuousPlayback: (_this_config_lowLatencyMode = this.config.lowLatencyMode) !== null && _this_config_lowLatencyMode !== void 0 ? _this_config_lowLatencyMode : false
2559
2724
  }).catch(function() {});
2725
+ fetchConsentSignals().then(function(signals) {
2726
+ _this.consentSignals = signals;
2727
+ }).catch(function() {});
2560
2728
  this.initializeTracking();
2561
2729
  if (!this.shouldUseNativeHls()) return [
2562
2730
  3,
@@ -4853,25 +5021,35 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4853
5021
  return this.getRemainingAdMs();
4854
5022
  }
4855
5023
  },
5024
+ {
5025
+ key: "beginNewAdPod",
5026
+ value: function beginNewAdPod() {
5027
+ this.podCounter++;
5028
+ this.adRequestPositionInBreak = 0;
5029
+ }
5030
+ },
4856
5031
  {
4857
5032
  key: "generateVastUrlsWithCorrelators",
4858
5033
  value: function generateVastUrlsWithCorrelators(baseUrl, count) {
4859
5034
  var urls = [];
4860
- var baseTimestamp = Date.now();
4861
5035
  for(var i = 0; i < count; i++){
4862
- var timestamp = baseTimestamp + i;
4863
- var random = Math.floor(Math.random() * 1e12);
4864
- var uniqueCorrelator = "".concat(timestamp, "_").concat(random, "_").concat(i);
4865
- var urlWithCorrelator = void 0;
4866
- var correlatorRegex = /([?&])correlator=([^&]*)/;
4867
- if (correlatorRegex.test(baseUrl)) {
4868
- urlWithCorrelator = baseUrl.replace(correlatorRegex, "$1correlator=".concat(uniqueCorrelator));
4869
- } else if (baseUrl.includes("?")) {
4870
- urlWithCorrelator = "".concat(baseUrl, "&correlator=").concat(uniqueCorrelator);
4871
- } else {
4872
- urlWithCorrelator = "".concat(baseUrl, "?correlator=").concat(uniqueCorrelator);
4873
- }
4874
- urls.push(this.palNonce.injectNonce(urlWithCorrelator));
5036
+ this.adRequestPositionInBreak++;
5037
+ var adWillPlayMuted = this.inAdBreak ? this.adPlayer.getOriginalMutedState() : this.video.muted;
5038
+ var urlWithMacros = applyVastMacros(baseUrl, {
5039
+ correlator: generateCorrelator(),
5040
+ streamCorrelator: this.streamCorrelator,
5041
+ pod: this.podCounter > 0 ? this.podCounter : void 0,
5042
+ adPosition: this.adRequestPositionInBreak,
5043
+ pageUrl: typeof window !== "undefined" ? window.location.href : void 0,
5044
+ adWillPlayMuted: adWillPlayMuted,
5045
+ adWillAutoPlay: !!this.config.autoplay,
5046
+ deviceId: this.config.deviceId,
5047
+ deviceIdType: this.config.deviceIdType,
5048
+ limitAdTracking: this.config.limitAdTracking,
5049
+ adTest: this.config.adTest,
5050
+ consent: this.consentSignals
5051
+ });
5052
+ urls.push(this.palNonce.injectNonce(urlWithMacros));
4875
5053
  }
4876
5054
  return urls;
4877
5055
  }
@@ -4941,6 +5119,8 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4941
5119
  }
4942
5120
  return;
4943
5121
  }
5122
+ this.beginNewAdPod();
5123
+ this.podAssignedByPrefetch = true;
4944
5124
  var urlsToPregenerate = 5;
4945
5125
  var generatedUrls = this.generateVastUrlsWithCorrelators(baseVastUrl, urlsToPregenerate);
4946
5126
  this.pendingAdBreak = _object_spread_props(_object_spread({
@@ -4978,6 +5158,7 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4978
5158
  }
4979
5159
  this.pendingAdBreak = null;
4980
5160
  this.pendingScte35CueKey = void 0;
5161
+ this.podAssignedByPrefetch = false;
4981
5162
  }
4982
5163
  },
4983
5164
  {
@@ -5414,6 +5595,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
5414
5595
  this.continuousFetchingActive = true;
5415
5596
  this.isShowingPlaceholder = false;
5416
5597
  this.totalAdRequestsInBreak = 0;
5598
+ if (this.podAssignedByPrefetch) {
5599
+ this.podAssignedByPrefetch = false;
5600
+ } else {
5601
+ this.beginNewAdPod();
5602
+ }
5417
5603
  currentMuted = this.video.muted;
5418
5604
  currentVolume = this.video.volume;
5419
5605
  this.adPlayer.updateOriginalMutedState(currentMuted, currentVolume);