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,5 +1,5 @@
1
1
  import { Component } from 'react';
2
- import { S as StormcloudVideoPlayerConfig } from '../types-DSKC4ySr.cjs';
2
+ import { S as StormcloudVideoPlayerConfig } from '../types-FjAlGhAL.cjs';
3
3
 
4
4
  interface HlsPlayerProps extends StormcloudVideoPlayerConfig {
5
5
  onMount?: (player: any) => void;
@@ -2096,6 +2096,79 @@ function createVastAdLayer(contentVideo, options) {
2096
2096
  }
2097
2097
  };
2098
2098
  }
2099
+ // src/utils/mqttClient.ts
2100
+ var import_mqtt = __toESM(require("mqtt"), 1);
2101
+ var LOG2 = "[StormcloudVideoPlayer][MQTT]";
2102
+ var client = null;
2103
+ var status = "disconnected";
2104
+ var brokerUrl = "";
2105
+ function isMQTTConfigured() {
2106
+ return client !== null;
2107
+ }
2108
+ function initMQTTClient(url) {
2109
+ var _topicPrefix = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : "adstorm";
2110
+ if (client) return;
2111
+ brokerUrl = url;
2112
+ status = "connecting";
2113
+ var clientId = "stormcloud-vp-".concat(Math.random().toString(36).slice(2, 9));
2114
+ try {
2115
+ client = import_mqtt.default.connect(url, {
2116
+ clientId: clientId,
2117
+ keepalive: 60,
2118
+ clean: true,
2119
+ reconnectPeriod: 5e3,
2120
+ connectTimeout: 1e4,
2121
+ queueQoSZero: false
2122
+ });
2123
+ } catch (err) {
2124
+ status = "error";
2125
+ console.warn("".concat(LOG2, " connect() threw:"), err);
2126
+ return;
2127
+ }
2128
+ client.on("connect", function() {
2129
+ status = "connected";
2130
+ console.info("".concat(LOG2, " connected to ").concat(url));
2131
+ });
2132
+ client.on("reconnect", function() {
2133
+ status = "connecting";
2134
+ console.info("".concat(LOG2, " reconnecting…"));
2135
+ });
2136
+ client.on("offline", function() {
2137
+ status = "disconnected";
2138
+ console.warn("".concat(LOG2, " offline"));
2139
+ });
2140
+ client.on("error", function(err) {
2141
+ status = "error";
2142
+ console.warn("".concat(LOG2, " error:"), err.message);
2143
+ });
2144
+ client.on("close", function() {
2145
+ if (status === "connected") {
2146
+ status = "disconnected";
2147
+ }
2148
+ });
2149
+ }
2150
+ function publishMQTT(topic, payload) {
2151
+ if (!client) {
2152
+ return false;
2153
+ }
2154
+ try {
2155
+ client.publish(topic, JSON.stringify(payload), {
2156
+ qos: 1
2157
+ });
2158
+ return true;
2159
+ } catch (err) {
2160
+ console.warn("".concat(LOG2, " publish failed on ").concat(topic, ":"), err);
2161
+ return false;
2162
+ }
2163
+ }
2164
+ function disconnectMQTT() {
2165
+ if (client) {
2166
+ client.end(true);
2167
+ client = null;
2168
+ status = "disconnected";
2169
+ brokerUrl = "";
2170
+ }
2171
+ }
2099
2172
  // src/utils/tracking.ts
2100
2173
  var cachedBrowserId = null;
2101
2174
  function getClientInfo() {
@@ -2127,8 +2200,8 @@ function getClientInfo() {
2127
2200
  os = "webOS";
2128
2201
  isSmartTV = true;
2129
2202
  deviceType = "tv";
2130
- var webosMatch = ua.match(/Web0S\/([^\s]+)/);
2131
- model = webosMatch ? "webOS ".concat(webosMatch[1]) : "webOS TV";
2203
+ var m = ua.match(/Web0S\/([^\s]+)/);
2204
+ model = m ? "webOS ".concat(m[1]) : "webOS TV";
2132
2205
  } else if (ua.includes("Tizen")) {
2133
2206
  brand = "Samsung";
2134
2207
  os = "Tizen";
@@ -2172,23 +2245,19 @@ function getClientInfo() {
2172
2245
  isAndroid = true;
2173
2246
  os = "Android";
2174
2247
  deviceType = /Mobile/.test(ua) ? "mobile" : "tablet";
2175
- if (ua.includes("Android") && (maxTouchPoints === 0 || ua.includes("Google TV") || ua.includes("XiaoMi"))) {
2248
+ if (maxTouchPoints === 0 || ua.includes("Google TV") || ua.includes("XiaoMi")) {
2176
2249
  deviceType = "tv";
2177
2250
  isSmartTV = true;
2178
2251
  brand = brand === "Unknown" ? "Android TV" : brand;
2179
2252
  }
2180
2253
  var androidModelMatch = ua.match(/\(([^)]*Android[^)]*)\)/);
2181
- if (androidModelMatch && androidModelMatch[1]) {
2182
- model = androidModelMatch[1];
2183
- }
2254
+ if (androidModelMatch === null || androidModelMatch === void 0 ? void 0 : androidModelMatch[1]) model = androidModelMatch[1];
2184
2255
  }
2185
2256
  if (/iPad|iPhone|iPod/.test(ua)) {
2186
2257
  os = "iOS";
2187
2258
  deviceType = "mobile";
2188
2259
  brand = "Apple";
2189
- if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) {
2190
- deviceType = "tablet";
2191
- }
2260
+ if (navigator.maxTouchPoints > 1 && /iPad/.test(ua)) deviceType = "tablet";
2192
2261
  }
2193
2262
  if (!isAndroid && !isSmartTV && !/Mobile/.test(ua)) {
2194
2263
  if (ua.includes("Windows")) {
@@ -2209,9 +2278,7 @@ function getClientInfo() {
2209
2278
  if (vendor.includes("Samsung") || ua.includes("SM-")) brand = "Samsung";
2210
2279
  }
2211
2280
  isWebView = /wv|WebView|Linux; U;/.test(ua);
2212
- if (((_window = window) === null || _window === void 0 ? void 0 : _window.outerHeight) === 0 && ((_window1 = window) === null || _window1 === void 0 ? void 0 : _window1.outerWidth) === 0) {
2213
- isWebView = true;
2214
- }
2281
+ 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;
2215
2282
  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;
2216
2283
  return {
2217
2284
  brand: brand,
@@ -2242,18 +2309,16 @@ function getClientInfo() {
2242
2309
  }
2243
2310
  function getBrowserID(clientInfo) {
2244
2311
  return _async_to_generator(function() {
2245
- var fingerprintString, encodedData, utf8, buffer, i, hashBuffer, hashArray, hashHex, error, hash, i1, char, fallbackHash, timestamp, random;
2312
+ var _crypto_subtle, fingerprintString, encodedData, utf8, buffer, i, hashBuffer, hashHex, unused, hash, i1, char, fallbackHash, timestamp, random;
2246
2313
  return _ts_generator(this, function(_state) {
2247
2314
  switch(_state.label){
2248
2315
  case 0:
2249
- if (cachedBrowserId) {
2250
- return [
2251
- 2,
2252
- cachedBrowserId
2253
- ];
2254
- }
2316
+ if (cachedBrowserId) return [
2317
+ 2,
2318
+ cachedBrowserId
2319
+ ];
2255
2320
  fingerprintString = JSON.stringify(clientInfo);
2256
- if (!(typeof crypto !== "undefined" && crypto.subtle && crypto.subtle.digest)) return [
2321
+ if (!(typeof crypto !== "undefined" && ((_crypto_subtle = crypto.subtle) === null || _crypto_subtle === void 0 ? void 0 : _crypto_subtle.digest))) return [
2257
2322
  3,
2258
2323
  5
2259
2324
  ];
@@ -2280,9 +2345,7 @@ function getBrowserID(clientInfo) {
2280
2345
  } else {
2281
2346
  utf8 = unescape(encodeURIComponent(fingerprintString));
2282
2347
  buffer = new Uint8Array(utf8.length);
2283
- for(i = 0; i < utf8.length; i++){
2284
- buffer[i] = utf8.charCodeAt(i);
2285
- }
2348
+ for(i = 0; i < utf8.length; i++)buffer[i] = utf8.charCodeAt(i);
2286
2349
  encodedData = buffer;
2287
2350
  }
2288
2351
  return [
@@ -2291,8 +2354,7 @@ function getBrowserID(clientInfo) {
2291
2354
  ];
2292
2355
  case 3:
2293
2356
  hashBuffer = _state.sent();
2294
- hashArray = Array.from(new Uint8Array(hashBuffer));
2295
- hashHex = hashArray.map(function(b) {
2357
+ hashHex = Array.from(new Uint8Array(hashBuffer)).map(function(b) {
2296
2358
  return b.toString(16).padStart(2, "0");
2297
2359
  }).join("");
2298
2360
  cachedBrowserId = hashHex;
@@ -2301,8 +2363,8 @@ function getBrowserID(clientInfo) {
2301
2363
  hashHex
2302
2364
  ];
2303
2365
  case 4:
2304
- error = _state.sent();
2305
- console.warn("[StormcloudVideoPlayer] crypto.subtle.digest not supported, using fallback hash");
2366
+ unused = _state.sent();
2367
+ console.warn("[StormcloudVideoPlayer] crypto.subtle not supported, using fallback hash");
2306
2368
  return [
2307
2369
  3,
2308
2370
  5
@@ -2326,6 +2388,10 @@ function getBrowserID(clientInfo) {
2326
2388
  });
2327
2389
  })();
2328
2390
  }
2391
+ var mqttTopicPrefix = "adstorm";
2392
+ function setMQTTTopicPrefix(prefix) {
2393
+ mqttTopicPrefix = prefix || "adstorm";
2394
+ }
2329
2395
  var PLAYER_TRACKING_BASE_URL = "https://adstorm.co/api-adstorm-dev/adstorm/player-tracking";
2330
2396
  var TRACK_URL = "".concat(PLAYER_TRACKING_BASE_URL, "/metrics/ingest");
2331
2397
  var HEARTBEAT_URL = "".concat(PLAYER_TRACKING_BASE_URL, "/heartbeat");
@@ -2334,43 +2400,9 @@ function buildHeaders(licenseKey) {
2334
2400
  var headers = {
2335
2401
  "Content-Type": "application/json"
2336
2402
  };
2337
- if (licenseKey) {
2338
- headers["Authorization"] = "Bearer ".concat(licenseKey);
2339
- }
2403
+ if (licenseKey) headers["Authorization"] = "Bearer ".concat(licenseKey);
2340
2404
  return headers;
2341
2405
  }
2342
- function sendTrackRequest(licenseKey, body) {
2343
- return _async_to_generator(function() {
2344
- var response;
2345
- return _ts_generator(this, function(_state) {
2346
- switch(_state.label){
2347
- case 0:
2348
- return [
2349
- 4,
2350
- fetch(TRACK_URL, {
2351
- method: "POST",
2352
- headers: buildHeaders(licenseKey),
2353
- body: JSON.stringify(body)
2354
- })
2355
- ];
2356
- case 1:
2357
- response = _state.sent();
2358
- if (!response.ok) {
2359
- throw new Error("HTTP error! status: ".concat(response.status));
2360
- }
2361
- return [
2362
- 4,
2363
- response.json()
2364
- ];
2365
- case 2:
2366
- _state.sent();
2367
- return [
2368
- 2
2369
- ];
2370
- }
2371
- });
2372
- })();
2373
- }
2374
2406
  function postJson(url, licenseKey, body) {
2375
2407
  return _async_to_generator(function() {
2376
2408
  var response;
@@ -2387,9 +2419,7 @@ function postJson(url, licenseKey, body) {
2387
2419
  ];
2388
2420
  case 1:
2389
2421
  response = _state.sent();
2390
- if (!response.ok) {
2391
- throw new Error("HTTP error! status: ".concat(response.status));
2392
- }
2422
+ if (!response.ok) throw new Error("HTTP error! status: ".concat(response.status));
2393
2423
  return [
2394
2424
  4,
2395
2425
  response.json()
@@ -2439,9 +2469,33 @@ function buildPlayerMetricEvent(_0) {
2439
2469
  });
2440
2470
  }).apply(this, arguments);
2441
2471
  }
2472
+ function publishOrPost(mqttTopic, httpUrl, licenseKey, body) {
2473
+ return _async_to_generator(function() {
2474
+ return _ts_generator(this, function(_state) {
2475
+ switch(_state.label){
2476
+ case 0:
2477
+ if (isMQTTConfigured()) {
2478
+ publishMQTT(mqttTopic, body);
2479
+ return [
2480
+ 2
2481
+ ];
2482
+ }
2483
+ return [
2484
+ 4,
2485
+ postJson(httpUrl, licenseKey, body)
2486
+ ];
2487
+ case 1:
2488
+ _state.sent();
2489
+ return [
2490
+ 2
2491
+ ];
2492
+ }
2493
+ });
2494
+ })();
2495
+ }
2442
2496
  function sendInitialTracking(_0) {
2443
2497
  return _async_to_generator(function(licenseKey) {
2444
- var context, clientInfo, browserId, trackingData, error;
2498
+ var context, clientInfo, browserId, captureAt, trackingData, metricsBody, error;
2445
2499
  var _arguments = arguments;
2446
2500
  return _ts_generator(this, function(_state) {
2447
2501
  switch(_state.label){
@@ -2462,26 +2516,28 @@ function sendInitialTracking(_0) {
2462
2516
  ];
2463
2517
  case 2:
2464
2518
  browserId = _state.sent();
2519
+ captureAt = /* @__PURE__ */ new Date().toISOString();
2465
2520
  trackingData = _object_spread({
2466
2521
  browserId: browserId
2467
2522
  }, clientInfo);
2523
+ metricsBody = {
2524
+ events: [
2525
+ {
2526
+ player_id: browserId,
2527
+ device_type: clientInfo.deviceType,
2528
+ input_stream_type: context.inputStreamType,
2529
+ os: clientInfo.os,
2530
+ ad_loaded: false,
2531
+ ad_detect: false,
2532
+ license_key: licenseKey,
2533
+ capture_at: captureAt
2534
+ }
2535
+ ],
2536
+ trackingData: trackingData
2537
+ };
2468
2538
  return [
2469
2539
  4,
2470
- sendTrackRequest(licenseKey, {
2471
- events: [
2472
- {
2473
- player_id: browserId,
2474
- device_type: clientInfo.deviceType,
2475
- input_stream_type: context.inputStreamType,
2476
- os: clientInfo.os,
2477
- ad_loaded: false,
2478
- ad_detect: false,
2479
- license_key: licenseKey,
2480
- capture_at: /* @__PURE__ */ new Date().toISOString()
2481
- }
2482
- ],
2483
- trackingData: trackingData
2484
- })
2540
+ publishOrPost("".concat(mqttTopicPrefix, "/tracking/metrics"), TRACK_URL, licenseKey, metricsBody)
2485
2541
  ];
2486
2542
  case 3:
2487
2543
  _state.sent();
@@ -2594,7 +2650,7 @@ function sendAdLoadedTracking(_0, _1) {
2594
2650
  }
2595
2651
  function sendAdImpressionTracking(_0, _1) {
2596
2652
  return _async_to_generator(function(licenseKey, adImpressionInfo) {
2597
- var context, metricEvent, error;
2653
+ var context, metricEvent, heartbeatBody, impressionsBody, error;
2598
2654
  var _arguments = arguments;
2599
2655
  return _ts_generator(this, function(_state) {
2600
2656
  switch(_state.label){
@@ -2616,21 +2672,23 @@ function sendAdImpressionTracking(_0, _1) {
2616
2672
  ];
2617
2673
  case 2:
2618
2674
  metricEvent = _state.sent();
2675
+ heartbeatBody = metricEvent;
2676
+ impressionsBody = {
2677
+ events: [
2678
+ {
2679
+ player_id: metricEvent.player_id,
2680
+ ad_played_count: 1,
2681
+ ad_url: adImpressionInfo.adUrl,
2682
+ license_key: licenseKey,
2683
+ capture_at: adImpressionInfo.timestamp
2684
+ }
2685
+ ]
2686
+ };
2619
2687
  return [
2620
2688
  4,
2621
2689
  Promise.all([
2622
- postJson(HEARTBEAT_URL, licenseKey, metricEvent),
2623
- postJson(IMPRESSIONS_URL, licenseKey, {
2624
- events: [
2625
- {
2626
- player_id: metricEvent.player_id,
2627
- ad_played_count: 1,
2628
- ad_url: adImpressionInfo.adUrl,
2629
- license_key: licenseKey,
2630
- capture_at: adImpressionInfo.timestamp
2631
- }
2632
- ]
2633
- })
2690
+ publishOrPost("".concat(mqttTopicPrefix, "/tracking/heartbeat"), HEARTBEAT_URL, licenseKey, heartbeatBody),
2691
+ publishOrPost("".concat(mqttTopicPrefix, "/tracking/impressions"), IMPRESSIONS_URL, licenseKey, impressionsBody)
2634
2692
  ])
2635
2693
  ];
2636
2694
  case 3:
@@ -2678,7 +2736,7 @@ function sendHeartbeat(_0) {
2678
2736
  heartbeatData = _state.sent();
2679
2737
  return [
2680
2738
  4,
2681
- postJson(HEARTBEAT_URL, licenseKey, heartbeatData)
2739
+ publishOrPost("".concat(mqttTopicPrefix, "/tracking/heartbeat"), HEARTBEAT_URL, licenseKey, heartbeatData)
2682
2740
  ];
2683
2741
  case 3:
2684
2742
  _state.sent();
@@ -4607,6 +4665,11 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
4607
4665
  key: "initializeTracking",
4608
4666
  value: function initializeTracking() {
4609
4667
  var _this = this;
4668
+ if (this.config.mqttBrokerUrl) {
4669
+ var topicPrefix = "adstorm";
4670
+ setMQTTTopicPrefix(topicPrefix);
4671
+ initMQTTClient(this.config.mqttBrokerUrl, topicPrefix);
4672
+ }
4610
4673
  sendInitialTracking(this.config.licenseKey, this.getAnalyticsContext()).then(function() {
4611
4674
  _this.heartbeatInterval = window.setInterval(function() {
4612
4675
  _this.sendHeartbeatIfNeeded();
@@ -6286,6 +6349,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
6286
6349
  clearInterval(this.heartbeatInterval);
6287
6350
  this.heartbeatInterval = void 0;
6288
6351
  }
6352
+ if (this.config.mqttBrokerUrl) {
6353
+ disconnectMQTT();
6354
+ }
6289
6355
  (_this_hls = this.hls) === null || _this_hls === void 0 ? void 0 : _this_hls.destroy();
6290
6356
  (_this_adLayer = this.adLayer) === null || _this_adLayer === void 0 ? void 0 : _this_adLayer.destroy();
6291
6357
  this.consecutiveFailures = 0;