stormcloud-video-player 0.8.35 → 0.8.37

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
@@ -2,6 +2,25 @@ import React, { CSSProperties, lazy as lazy$1 } from 'react';
2
2
  import * as csstype from 'csstype';
3
3
  import Hls from 'hls.js';
4
4
 
5
+ declare const MQTT_CA_CERT_FILE = "src/certs/emqxsl-ca.crt";
6
+ type MQTTConfig = {
7
+ enabled: boolean;
8
+ brokerAddress: string;
9
+ brokerPort: number;
10
+ wsPort: number;
11
+ username: string;
12
+ password: string;
13
+ topicPrefix: string;
14
+ qos: 0 | 1 | 2;
15
+ brokerUrl?: string;
16
+ };
17
+ declare const DEFAULT_MQTT_CONFIG: MQTTConfig;
18
+ declare const mqttConfig: MQTTConfig;
19
+ declare function applyMQTTConfig(overrides: Partial<MQTTConfig>): void;
20
+ declare function isMQTTEnabled(): boolean;
21
+ declare function buildMQTTBrokerUrl(): string;
22
+ declare function buildPlayerTopic(licenseKey: string, channel: "metrics" | "impressions" | "heartbeat"): string;
23
+
5
24
  type LateJoinPolicy = "play_remaining" | "skip_to_content";
6
25
  interface AdBreak {
7
26
  id?: string;
@@ -3944,25 +3963,6 @@ declare function sendAdLoadedTracking(licenseKey: string | undefined, adLoadedIn
3944
3963
  declare function sendAdImpressionTracking(licenseKey: string | undefined, adImpressionInfo: AdImpressionInfo, context?: PlayerAnalyticsContext): Promise<void>;
3945
3964
  declare function sendHeartbeat(licenseKey?: string, context?: PlayerAnalyticsContext, flags?: PlayerMetricFlags): Promise<void>;
3946
3965
 
3947
- declare const MQTT_CA_CERT_FILE = "src/certs/emqxsl-ca.crt";
3948
- type MQTTConfig = {
3949
- enabled: boolean;
3950
- brokerAddress: string;
3951
- brokerPort: number;
3952
- wsPort: number;
3953
- username: string;
3954
- password: string;
3955
- topicPrefix: string;
3956
- qos: 0 | 1 | 2;
3957
- brokerUrl?: string;
3958
- };
3959
- declare const DEFAULT_MQTT_CONFIG: MQTTConfig;
3960
- declare const mqttConfig: MQTTConfig;
3961
- declare function applyMQTTConfig(overrides: Partial<MQTTConfig>): void;
3962
- declare function isMQTTEnabled(): boolean;
3963
- declare function buildMQTTBrokerUrl(): string;
3964
- declare function buildPlayerTopic(licenseKey: string, channel: "metrics" | "impressions" | "heartbeat"): string;
3965
-
3966
3966
  type MQTTStatus = "disconnected" | "connecting" | "connected" | "error";
3967
3967
  declare function getMQTTStatus(): MQTTStatus;
3968
3968
  declare function isMQTTConnected(): boolean;
package/lib/index.d.ts CHANGED
@@ -2,6 +2,25 @@ import React, { CSSProperties, lazy as lazy$1 } from 'react';
2
2
  import * as csstype from 'csstype';
3
3
  import Hls from 'hls.js';
4
4
 
5
+ declare const MQTT_CA_CERT_FILE = "src/certs/emqxsl-ca.crt";
6
+ type MQTTConfig = {
7
+ enabled: boolean;
8
+ brokerAddress: string;
9
+ brokerPort: number;
10
+ wsPort: number;
11
+ username: string;
12
+ password: string;
13
+ topicPrefix: string;
14
+ qos: 0 | 1 | 2;
15
+ brokerUrl?: string;
16
+ };
17
+ declare const DEFAULT_MQTT_CONFIG: MQTTConfig;
18
+ declare const mqttConfig: MQTTConfig;
19
+ declare function applyMQTTConfig(overrides: Partial<MQTTConfig>): void;
20
+ declare function isMQTTEnabled(): boolean;
21
+ declare function buildMQTTBrokerUrl(): string;
22
+ declare function buildPlayerTopic(licenseKey: string, channel: "metrics" | "impressions" | "heartbeat"): string;
23
+
5
24
  type LateJoinPolicy = "play_remaining" | "skip_to_content";
6
25
  interface AdBreak {
7
26
  id?: string;
@@ -3944,25 +3963,6 @@ declare function sendAdLoadedTracking(licenseKey: string | undefined, adLoadedIn
3944
3963
  declare function sendAdImpressionTracking(licenseKey: string | undefined, adImpressionInfo: AdImpressionInfo, context?: PlayerAnalyticsContext): Promise<void>;
3945
3964
  declare function sendHeartbeat(licenseKey?: string, context?: PlayerAnalyticsContext, flags?: PlayerMetricFlags): Promise<void>;
3946
3965
 
3947
- declare const MQTT_CA_CERT_FILE = "src/certs/emqxsl-ca.crt";
3948
- type MQTTConfig = {
3949
- enabled: boolean;
3950
- brokerAddress: string;
3951
- brokerPort: number;
3952
- wsPort: number;
3953
- username: string;
3954
- password: string;
3955
- topicPrefix: string;
3956
- qos: 0 | 1 | 2;
3957
- brokerUrl?: string;
3958
- };
3959
- declare const DEFAULT_MQTT_CONFIG: MQTTConfig;
3960
- declare const mqttConfig: MQTTConfig;
3961
- declare function applyMQTTConfig(overrides: Partial<MQTTConfig>): void;
3962
- declare function isMQTTEnabled(): boolean;
3963
- declare function buildMQTTBrokerUrl(): string;
3964
- declare function buildPlayerTopic(licenseKey: string, channel: "metrics" | "impressions" | "heartbeat"): string;
3965
-
3966
3966
  type MQTTStatus = "disconnected" | "connecting" | "connected" | "error";
3967
3967
  declare function getMQTTStatus(): MQTTStatus;
3968
3968
  declare function isMQTTConnected(): boolean;
package/lib/index.js CHANGED
@@ -1120,7 +1120,7 @@ function createHlsAdPlayer(contentVideo, options) {
1120
1120
  adHls.destroy();
1121
1121
  }
1122
1122
  adHls = new Hls({
1123
- enableWorker: true,
1123
+ enableWorker: typeof globalThis !== "undefined",
1124
1124
  lowLatencyMode: false
1125
1125
  });
1126
1126
  adHls.loadSource(mediaFile.url);
@@ -3507,7 +3507,7 @@ function removeBrokenAppNameOrphans(params, appName) {
3507
3507
  try {
3508
3508
  for(var _iterator = appName.split("&").slice(1)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
3509
3509
  var suffix = _step.value;
3510
- var trimmed = suffix.trimStart();
3510
+ var trimmed = suffix.replace(/^\s+/, "");
3511
3511
  if (!trimmed) continue;
3512
3512
  toDelete.push(suffix, " ".concat(trimmed), trimmed);
3513
3513
  }
@@ -3561,7 +3561,7 @@ function normalizeVastTagUrl(raw) {
3561
3561
  });
3562
3562
  if (orphanFragments.length > 0) {
3563
3563
  var reconstructed = [
3564
- anValue.trimEnd()
3564
+ anValue.replace(/\s+$/, "")
3565
3565
  ].concat(_to_consumable_array(orphanFragments)).filter(Boolean).join(" & ");
3566
3566
  url.searchParams.forEach(function(_value, key) {
3567
3567
  if (key && INVALID_VAST_PARAM_KEY.test(key)) {
@@ -5099,6 +5099,7 @@ var AdConfigManager = /*#__PURE__*/ function() {
5099
5099
  ];
5100
5100
  case 4:
5101
5101
  data = _state.sent();
5102
+ this.applyMqttConfigFromResponse(data);
5102
5103
  imaPayload = (_data_response = data.response) === null || _data_response === void 0 ? void 0 : (_data_response_ima = _data_response.ima) === null || _data_response_ima === void 0 ? void 0 : (_data_response_ima_publisherdeskima = _data_response_ima["publisherdesk.ima"]) === null || _data_response_ima_publisherdeskima === void 0 ? void 0 : _data_response_ima_publisherdeskima.payload;
5103
5104
  if (imaPayload) {
5104
5105
  decodedPayload = imaPayload;
@@ -5132,6 +5133,20 @@ var AdConfigManager = /*#__PURE__*/ function() {
5132
5133
  }).call(this);
5133
5134
  }
5134
5135
  },
5136
+ {
5137
+ key: "applyMqttConfigFromResponse",
5138
+ value: function applyMqttConfigFromResponse(data) {
5139
+ var _data_response;
5140
+ var mqttConfig2 = (_data_response = data.response) === null || _data_response === void 0 ? void 0 : _data_response.mqtt_config;
5141
+ if (!mqttConfig2 || (typeof mqttConfig2 === "undefined" ? "undefined" : _type_of(mqttConfig2)) !== "object") {
5142
+ return;
5143
+ }
5144
+ applyMQTTConfig(mqttConfig2);
5145
+ if (this.debug) {
5146
+ console.log("[StormcloudVideoPlayer] Applied MQTT config from /ads/web:", mqttConfig2);
5147
+ }
5148
+ }
5149
+ },
5135
5150
  {
5136
5151
  key: "fetchAndParseVmap",
5137
5152
  value: function fetchAndParseVmap(vmapUrl) {
@@ -6263,7 +6278,7 @@ var HlsEngine = /*#__PURE__*/ function() {
6263
6278
  value: function setupHls() {
6264
6279
  var _this = this;
6265
6280
  this.hls = new Hls2(_object_spread_props(_object_spread({
6266
- enableWorker: true,
6281
+ enableWorker: typeof globalThis !== "undefined",
6267
6282
  backBufferLength: 30,
6268
6283
  liveDurationInfinity: true,
6269
6284
  lowLatencyMode: !!this.config.lowLatencyMode,
@@ -6652,6 +6667,22 @@ var HlsEngine = /*#__PURE__*/ function() {
6652
6667
  return typeof pos === "number" && Number.isFinite(pos) ? pos : void 0;
6653
6668
  }
6654
6669
  },
6670
+ {
6671
+ key: "restartLoadAt",
6672
+ value: function restartLoadAt(position) {
6673
+ if (!this.hls) {
6674
+ return;
6675
+ }
6676
+ try {
6677
+ this.hls.stopLoad();
6678
+ this.hls.startLoad(position);
6679
+ } catch (error) {
6680
+ if (this.debug) {
6681
+ console.warn("[StormcloudVideoPlayer] Failed to restart HLS load at live edge:", error);
6682
+ }
6683
+ }
6684
+ }
6685
+ },
6655
6686
  {
6656
6687
  key: "destroy",
6657
6688
  value: function destroy() {
@@ -7969,11 +8000,56 @@ var AdBreakOrchestrator = /*#__PURE__*/ function() {
7969
8000
  console.log("[StormcloudVideoPlayer] Live break end — snapping to live edge: ".concat(this.host.video.currentTime.toFixed(2), "s → ").concat(liveSyncPos.toFixed(2), "s"));
7970
8001
  }
7971
8002
  this.host.video.currentTime = liveSyncPos;
8003
+ this.host.restartHlsLoad(liveSyncPos);
7972
8004
  }
8005
+ this.resumeContentPlayback();
8006
+ this.monitorLiveResumeStall(0, this.host.video.currentTime);
8007
+ return;
7973
8008
  }
7974
8009
  this.resumeContentPlayback();
7975
8010
  }
7976
8011
  },
8012
+ {
8013
+ key: "monitorLiveResumeStall",
8014
+ value: function monitorLiveResumeStall(attempt, lastTime) {
8015
+ var _this = this;
8016
+ var maxAttempts = 3;
8017
+ var checkDelayMs = 2500;
8018
+ window.setTimeout(function() {
8019
+ if (_this.inAdBreak) {
8020
+ return;
8021
+ }
8022
+ var currentTime = _this.host.video.currentTime;
8023
+ var advanced = currentTime > lastTime + 0.25;
8024
+ if (advanced && !_this.host.video.paused) {
8025
+ if (_this.debug) {
8026
+ console.log("[StormcloudVideoPlayer] Live stream resumed successfully after ad break");
8027
+ }
8028
+ return;
8029
+ }
8030
+ if (attempt >= maxAttempts) {
8031
+ if (_this.debug) {
8032
+ console.warn("[StormcloudVideoPlayer] Live stream failed to resume after ".concat(maxAttempts, " recovery attempts (t=").concat(currentTime.toFixed(2), "s)"));
8033
+ }
8034
+ return;
8035
+ }
8036
+ if (_this.debug) {
8037
+ console.warn("[StormcloudVideoPlayer] Content stalled after ad break (t=".concat(currentTime.toFixed(2), "s) — forcing HLS reload at live edge (attempt ").concat(attempt + 1, "/").concat(maxAttempts, ")"));
8038
+ }
8039
+ var liveSyncPos = _this.host.getLiveSyncPosition();
8040
+ var reloadPos = liveSyncPos != null && liveSyncPos > currentTime ? liveSyncPos : currentTime;
8041
+ if (liveSyncPos != null && liveSyncPos > currentTime) {
8042
+ _this.host.video.currentTime = liveSyncPos;
8043
+ }
8044
+ _this.host.restartHlsLoad(reloadPos);
8045
+ if (_this.host.video.paused) {
8046
+ var _this_host_video_play;
8047
+ (_this_host_video_play = _this.host.video.play()) === null || _this_host_video_play === void 0 ? void 0 : _this_host_video_play.catch(function() {});
8048
+ }
8049
+ _this.monitorLiveResumeStall(attempt + 1, _this.host.video.currentTime);
8050
+ }, checkDelayMs);
8051
+ }
8052
+ },
7977
8053
  {
7978
8054
  key: "resumeContentPlayback",
7979
8055
  value: function resumeContentPlayback() {
@@ -8123,6 +8199,9 @@ var StormcloudVideoPlayer = /*#__PURE__*/ function() {
8123
8199
  getLiveSyncPosition: function getLiveSyncPosition() {
8124
8200
  return _this.hlsEngine.getLiveSyncPosition();
8125
8201
  },
8202
+ restartHlsLoad: function restartHlsLoad(position) {
8203
+ return _this.hlsEngine.restartLoadAt(position);
8204
+ },
8126
8205
  generatePodVastUrl: function generatePodVastUrl(base, breakDurationMs) {
8127
8206
  return _this.generatePodVastUrl(base, breakDurationMs);
8128
8207
  }