stormcloud-video-player 0.6.11 → 0.6.12

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.
@@ -1,4 +1,4 @@
1
- import { S as StormcloudVideoPlayerConfig } from '../types-DSKC4ySr.cjs';
1
+ import { S as StormcloudVideoPlayerConfig } from '../types-FjAlGhAL.cjs';
2
2
 
3
3
  declare class StormcloudVideoPlayer {
4
4
  private readonly video;
@@ -2060,6 +2060,79 @@ function createVastAdLayer(contentVideo, options) {
2060
2060
  }
2061
2061
  };
2062
2062
  }
2063
+ // src/utils/mqttClient.ts
2064
+ var import_mqtt = __toESM(require("mqtt"), 1);
2065
+ var LOG2 = "[StormcloudVideoPlayer][MQTT]";
2066
+ var client = null;
2067
+ var status = "disconnected";
2068
+ var brokerUrl = "";
2069
+ function isMQTTConfigured() {
2070
+ return client !== null;
2071
+ }
2072
+ function initMQTTClient(url) {
2073
+ var _topicPrefix = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "adstorm";
2074
+ if (client) return;
2075
+ brokerUrl = url;
2076
+ status = "connecting";
2077
+ var clientId = "stormcloud-vp-".concat(Math.random().toString(36).slice(2, 9));
2078
+ try {
2079
+ client = import_mqtt.default.connect(url, {
2080
+ clientId: clientId,
2081
+ keepalive: 60,
2082
+ clean: true,
2083
+ reconnectPeriod: 5e3,
2084
+ connectTimeout: 1e4,
2085
+ queueQoSZero: false
2086
+ });
2087
+ } catch (err) {
2088
+ status = "error";
2089
+ console.warn("".concat(LOG2, " connect() threw:"), err);
2090
+ return;
2091
+ }
2092
+ client.on("connect", function() {
2093
+ status = "connected";
2094
+ console.info("".concat(LOG2, " connected to ").concat(url));
2095
+ });
2096
+ client.on("reconnect", function() {
2097
+ status = "connecting";
2098
+ console.info("".concat(LOG2, " reconnecting…"));
2099
+ });
2100
+ client.on("offline", function() {
2101
+ status = "disconnected";
2102
+ console.warn("".concat(LOG2, " offline"));
2103
+ });
2104
+ client.on("error", function(err) {
2105
+ status = "error";
2106
+ console.warn("".concat(LOG2, " error:"), err.message);
2107
+ });
2108
+ client.on("close", function() {
2109
+ if (status === "connected") {
2110
+ status = "disconnected";
2111
+ }
2112
+ });
2113
+ }
2114
+ function publishMQTT(topic, payload) {
2115
+ if (!client) {
2116
+ return false;
2117
+ }
2118
+ try {
2119
+ client.publish(topic, JSON.stringify(payload), {
2120
+ qos: 1
2121
+ });
2122
+ return true;
2123
+ } catch (err) {
2124
+ console.warn("".concat(LOG2, " publish failed on ").concat(topic, ":"), err);
2125
+ return false;
2126
+ }
2127
+ }
2128
+ function disconnectMQTT() {
2129
+ if (client) {
2130
+ client.end(true);
2131
+ client = null;
2132
+ status = "disconnected";
2133
+ brokerUrl = "";
2134
+ }
2135
+ }
2063
2136
  // src/utils/tracking.ts
2064
2137
  var cachedBrowserId = null;
2065
2138
  function getClientInfo() {
@@ -2091,8 +2164,8 @@ function getClientInfo() {
2091
2164
  os = "webOS";
2092
2165
  isSmartTV = true;
2093
2166
  deviceType = "tv";
2094
- var webosMatch = ua.match(/Web0S\/([^\s]+)/);
2095
- model = webosMatch ? "webOS ".concat(webosMatch[1]) : "webOS TV";
2167
+ var m = ua.match(/Web0S\/([^\s]+)/);
2168
+ model = m ? "webOS ".concat(m[1]) : "webOS TV";
2096
2169
  } else if (ua.includes("Tizen")) {
2097
2170
  brand = "Samsung";
2098
2171
  os = "Tizen";
@@ -2136,23 +2209,19 @@ function getClientInfo() {
2136
2209
  isAndroid = true;
2137
2210
  os = "Android";
2138
2211
  deviceType = /Mobile/.test(ua) ? "mobile" : "tablet";
2139
- if (ua.includes("Android") && (maxTouchPoints === 0 || ua.includes("Google TV") || ua.includes("XiaoMi"))) {
2212
+ if (maxTouchPoints === 0 || ua.includes("Google TV") || ua.includes("XiaoMi")) {
2140
2213
  deviceType = "tv";
2141
2214
  isSmartTV = true;
2142
2215
  brand = brand === "Unknown" ? "Android TV" : brand;
2143
2216
  }
2144
2217
  var androidModelMatch = ua.match(/\(([^)]*Android[^)]*)\)/);
2145
- if (androidModelMatch && androidModelMatch[1]) {
2146
- model = androidModelMatch[1];
2147
- }
2218
+ if (androidModelMatch === null || androidModelMatch === void 0 ? void 0 : androidModelMatch[1]) model = androidModelMatch[1];
2148
2219
  }
2149
2220
  if (/iPad|iPhone|iPod/.test(ua)) {
2150
2221
  os = "iOS";
2151
2222
  deviceType = "mobile";
2152
2223
  brand = "Apple";
2153
- if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {
2154
- deviceType = "tablet";
2155
- }
2224
+ if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) deviceType = "tablet";
2156
2225
  }
2157
2226
  if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {
2158
2227
  if (ua.includes("Windows")) {
@@ -2173,9 +2242,7 @@ function getClientInfo() {
2173
2242
  if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
2174
2243
  }
2175
2244
  isWebView = /wv|WebView|Linux; U;/.test(ua);
2176
- if (((_window = window) === null || _window === void 0 ? void 0 : _window.outerHeight) === 0 && ((_window1 = window) === null || _window1 === void 0 ? void 0 : _window1.outerWidth) === 0) {
2177
- isWebView = true;
2178
- }
2245
+ if (((_window = window) === null || _window === void 0 ? void 0 : _window.outerHeight) === 0 && ((_window1 = window) === null || _window1 === void 0 ? void 0 : _window1.outerWidth) === 0) isWebView = true;
2179
2246
  isWebApp = window.matchMedia("(display-mode: standalone)").matches || window.navigator.standalone === true || ((_window_screen = window.screen) === null || _window_screen === void 0 ? void 0 : (_window_screen_orientation = _window_screen.orientation) === null || _window_screen_orientation === void 0 ? void 0 : _window_screen_orientation.angle) !== void 0;
2180
2247
  return {
2181
2248
  brand: brand,
@@ -2206,18 +2273,16 @@ function getClientInfo() {
2206
2273
  }
2207
2274
  function getBrowserID(clientInfo) {
2208
2275
  return _async_to_generator(function() {
2209
- var fingerprintString, encodedData, utf8, buffer, i, hashBuffer, hashArray, hashHex, error, hash, i1, char, fallbackHash, timestamp, random;
2276
+ var _crypto_subtle, fingerprintString, encodedData, utf8, buffer, i, hashBuffer, hashHex, unused, hash, i1, char, fallbackHash, timestamp, random;
2210
2277
  return _ts_generator(this, function(_state) {
2211
2278
  switch(_state.label){
2212
2279
  case 0:
2213
- if (cachedBrowserId) {
2214
- return [
2215
- 2,
2216
- cachedBrowserId
2217
- ];
2218
- }
2280
+ if (cachedBrowserId) return [
2281
+ 2,
2282
+ cachedBrowserId
2283
+ ];
2219
2284
  fingerprintString = JSON.stringify(clientInfo);
2220
- if (!(typeof crypto !== "undefined" && crypto.subtle && crypto.subtle.digest)) return [
2285
+ if (!(typeof crypto !== "undefined" && ((_crypto_subtle = crypto.subtle) === null || _crypto_subtle === void 0 ? void 0 : _crypto_subtle.digest))) return [
2221
2286
  3,
2222
2287
  5
2223
2288
  ];
@@ -2244,9 +2309,7 @@ function getBrowserID(clientInfo) {
2244
2309
  } else {
2245
2310
  utf8 = unescape(encodeURIComponent(fingerprintString));
2246
2311
  buffer = new Uint8Array(utf8.length);
2247
- for(i = 0; i < utf8.length; i++){
2248
- buffer[i] = utf8.charCodeAt(i);
2249
- }
2312
+ for(i = 0; i < utf8.length; i++)buffer[i] = utf8.charCodeAt(i);
2250
2313
  encodedData = buffer;
2251
2314
  }
2252
2315
  return [
@@ -2255,8 +2318,7 @@ function getBrowserID(clientInfo) {
2255
2318
  ];
2256
2319
  case 3:
2257
2320
  hashBuffer = _state.sent();
2258
- hashArray = Array.from(new Uint8Array(hashBuffer));
2259
- hashHex = hashArray.map(function(b) {
2321
+ hashHex = Array.from(new Uint8Array(hashBuffer)).map(function(b) {
2260
2322
  return b.toString(16).padStart(2, "0");
2261
2323
  }).join("");
2262
2324
  cachedBrowserId = hashHex;
@@ -2265,8 +2327,8 @@ function getBrowserID(clientInfo) {
2265
2327
  hashHex
2266
2328
  ];
2267
2329
  case 4:
2268
- error = _state.sent();
2269
- console.warn("[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash");
2330
+ unused = _state.sent();
2331
+ console.warn("[StormcloudVideoPlayer] crypto.subtle not supported, using fallback hash");
2270
2332
  return [
2271
2333
  3,
2272
2334
  5
@@ -2290,6 +2352,10 @@ function getBrowserID(clientInfo) {
2290
2352
  });
2291
2353
  })();
2292
2354
  }
2355
+ var mqttTopicPrefix = "adstorm";
2356
+ function setMQTTTopicPrefix(prefix) {
2357
+ mqttTopicPrefix = prefix || "adstorm";
2358
+ }
2293
2359
  var PLAYER_TRACKING_BASE_URL = "https://adstorm.co/api-adstorm-dev/adstorm/player-tracking";
2294
2360
  var TRACK_URL = "".concat(PLAYER_TRACKING_BASE_URL, "/metrics/ingest");
2295
2361
  var HEARTBEAT_URL = "".concat(PLAYER_TRACKING_BASE_URL, "/heartbeat");
@@ -2298,43 +2364,9 @@ function buildHeaders(licenseKey) {
2298
2364
  var headers = {
2299
2365
  "Content-Type": "application/json"
2300
2366
  };
2301
- if (licenseKey) {
2302
- headers["Authorization"] = "Bearer ".concat(licenseKey);
2303
- }
2367
+ if (licenseKey) headers["Authorization"] = "Bearer ".concat(licenseKey);
2304
2368
  return headers;
2305
2369
  }
2306
- function sendTrackRequest(licenseKey, body) {
2307
- return _async_to_generator(function() {
2308
- var response;
2309
- return _ts_generator(this, function(_state) {
2310
- switch(_state.label){
2311
- case 0:
2312
- return [
2313
- 4,
2314
- fetch(TRACK_URL, {
2315
- method: "POST",
2316
- headers: buildHeaders(licenseKey),
2317
- body: JSON.stringify(body)
2318
- })
2319
- ];
2320
- case 1:
2321
- response = _state.sent();
2322
- if (!response.ok) {
2323
- throw new Error("HTTP error! status: ".concat(response.status));
2324
- }
2325
- return [
2326
- 4,
2327
- response.json()
2328
- ];
2329
- case 2:
2330
- _state.sent();
2331
- return [
2332
- 2
2333
- ];
2334
- }
2335
- });
2336
- })();
2337
- }
2338
2370
  function postJson(url, licenseKey, body) {
2339
2371
  return _async_to_generator(function() {
2340
2372
  var response;
@@ -2351,9 +2383,7 @@ function postJson(url, licenseKey, body) {
2351
2383
  ];
2352
2384
  case 1:
2353
2385
  response = _state.sent();
2354
- if (!response.ok) {
2355
- throw new Error("HTTP error! status: ".concat(response.status));
2356
- }
2386
+ if (!response.ok) throw new Error("HTTP error! status: ".concat(response.status));
2357
2387
  return [
2358
2388
  4,
2359
2389
  response.json()
@@ -2403,9 +2433,33 @@ function buildPlayerMetricEvent(_0) {
2403
2433
  });
2404
2434
  }).apply(this, arguments);
2405
2435
  }
2436
+ function publishOrPost(mqttTopic, httpUrl, licenseKey, body) {
2437
+ return _async_to_generator(function() {
2438
+ return _ts_generator(this, function(_state) {
2439
+ switch(_state.label){
2440
+ case 0:
2441
+ if (isMQTTConfigured()) {
2442
+ publishMQTT(mqttTopic, body);
2443
+ return [
2444
+ 2
2445
+ ];
2446
+ }
2447
+ return [
2448
+ 4,
2449
+ postJson(httpUrl, licenseKey, body)
2450
+ ];
2451
+ case 1:
2452
+ _state.sent();
2453
+ return [
2454
+ 2
2455
+ ];
2456
+ }
2457
+ });
2458
+ })();
2459
+ }
2406
2460
  function sendInitialTracking(_0) {
2407
2461
  return _async_to_generator(function(licenseKey) {
2408
- var context, clientInfo, browserId, trackingData, error;
2462
+ var context, clientInfo, browserId, captureAt, trackingData, metricsBody, error;
2409
2463
  var _arguments = arguments;
2410
2464
  return _ts_generator(this, function(_state) {
2411
2465
  switch(_state.label){
@@ -2426,26 +2480,28 @@ function sendInitialTracking(_0) {
2426
2480
  ];
2427
2481
  case 2:
2428
2482
  browserId = _state.sent();
2483
+ captureAt = /* @__PURE__ */ new Date().toISOString();
2429
2484
  trackingData = _object_spread({
2430
2485
  browserId: browserId
2431
2486
  }, clientInfo);
2487
+ metricsBody = {
2488
+ events: [
2489
+ {
2490
+ player_id: browserId,
2491
+ device_type: clientInfo.deviceType,
2492
+ input_stream_type: context.inputStreamType,
2493
+ os: clientInfo.os,
2494
+ ad_loaded: false,
2495
+ ad_detect: false,
2496
+ license_key: licenseKey,
2497
+ capture_at: captureAt
2498
+ }
2499
+ ],
2500
+ trackingData: trackingData
2501
+ };
2432
2502
  return [
2433
2503
  4,
2434
- sendTrackRequest(licenseKey, {
2435
- events: [
2436
- {
2437
- player_id: browserId,
2438
- device_type: clientInfo.deviceType,
2439
- input_stream_type: context.inputStreamType,
2440
- os: clientInfo.os,
2441
- ad_loaded: false,
2442
- ad_detect: false,
2443
- license_key: licenseKey,
2444
- capture_at: /* @__PURE__ */ new Date().toISOString()
2445
- }
2446
- ],
2447
- trackingData: trackingData
2448
- })
2504
+ publishOrPost("".concat(mqttTopicPrefix, "/tracking/metrics"), TRACK_URL, licenseKey, metricsBody)
2449
2505
  ];
2450
2506
  case 3:
2451
2507
  _state.sent();
@@ -2558,7 +2614,7 @@ function sendAdLoadedTracking(_0, _1) {
2558
2614
  }
2559
2615
  function sendAdImpressionTracking(_0, _1) {
2560
2616
  return _async_to_generator(function(licenseKey, adImpressionInfo) {
2561
- var context, metricEvent, error;
2617
+ var context, metricEvent, heartbeatBody, impressionsBody, error;
2562
2618
  var _arguments = arguments;
2563
2619
  return _ts_generator(this, function(_state) {
2564
2620
  switch(_state.label){
@@ -2580,21 +2636,23 @@ function sendAdImpressionTracking(_0, _1) {
2580
2636
  ];
2581
2637
  case 2:
2582
2638
  metricEvent = _state.sent();
2639
+ heartbeatBody = metricEvent;
2640
+ impressionsBody = {
2641
+ events: [
2642
+ {
2643
+ player_id: metricEvent.player_id,
2644
+ ad_played_count: 1,
2645
+ ad_url: adImpressionInfo.adUrl,
2646
+ license_key: licenseKey,
2647
+ capture_at: adImpressionInfo.timestamp
2648
+ }
2649
+ ]
2650
+ };
2583
2651
  return [
2584
2652
  4,
2585
2653
  Promise.all([
2586
- postJson(HEARTBEAT_URL, licenseKey, metricEvent),
2587
- postJson(IMPRESSIONS_URL, licenseKey, {
2588
- events: [
2589
- {
2590
- player_id: metricEvent.player_id,
2591
- ad_played_count: 1,
2592
- ad_url: adImpressionInfo.adUrl,
2593
- license_key: licenseKey,
2594
- capture_at: adImpressionInfo.timestamp
2595
- }
2596
- ]
2597
- })
2654
+ publishOrPost("".concat(mqttTopicPrefix, "/tracking/heartbeat"), HEARTBEAT_URL, licenseKey, heartbeatBody),
2655
+ publishOrPost("".concat(mqttTopicPrefix, "/tracking/impressions"), IMPRESSIONS_URL, licenseKey, impressionsBody)
2598
2656
  ])
2599
2657
  ];
2600
2658
  case 3:
@@ -2642,7 +2700,7 @@ function sendHeartbeat(_0) {
2642
2700
  heartbeatData = _state.sent();
2643
2701
  return [
2644
2702
  4,
2645
- postJson(HEARTBEAT_URL, licenseKey, heartbeatData)
2703
+ publishOrPost("".concat(mqttTopicPrefix, "/tracking/heartbeat"), HEARTBEAT_URL, licenseKey, heartbeatData)
2646
2704
  ];
2647
2705
  case 3:
2648
2706
  _state.sent();
@@ -4571,6 +4629,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4571
4629
  key: "initializeTracking",
4572
4630
  value: function initializeTracking() {
4573
4631
  var _this = this;
4632
+ if (this.config.mqttBrokerUrl) {
4633
+ var topicPrefix = "adstorm";
4634
+ setMQTTTopicPrefix(topicPrefix);
4635
+ initMQTTClient(this.config.mqttBrokerUrl, topicPrefix);
4636
+ }
4574
4637
  sendInitialTracking(this.config.licenseKey, this.getAnalyticsContext()).then(function() {
4575
4638
  _this.heartbeatInterval = window.setInterval(function() {
4576
4639
  _this.sendHeartbeatIfNeeded();
@@ -6250,6 +6313,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6250
6313
  clearInterval(this.heartbeatInterval);
6251
6314
  this.heartbeatInterval = void 0;
6252
6315
  }
6316
+ if (this.config.mqttBrokerUrl) {
6317
+ disconnectMQTT();
6318
+ }
6253
6319
  (_this_hls = this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.destroy();
6254
6320
  (_this_adLayer = this.adLayer) === null || _this_adLayer === void 0 ? void 0 : _this_adLayer.destroy();
6255
6321
  this.consecutiveFailures = 0;