@guardvideo/player-sdk 3.4.0 → 3.6.0

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.
@@ -21,6 +21,8 @@ export declare class EventTracker {
21
21
  private accumulator;
22
22
  private destroyed;
23
23
  private _onBeforeUnload;
24
+ private flushBackoff;
25
+ private flushing;
24
26
  constructor(config: EventTrackerConfig);
25
27
  track(type: string, positionSeconds?: number, payload?: Record<string, unknown>): void;
26
28
  startChunk(position: number): void;
@@ -30,6 +32,7 @@ export declare class EventTracker {
30
32
  flush(): Promise<void>;
31
33
  destroy(): void;
32
34
  private startAutoFlush;
35
+ private restartAutoFlush;
33
36
  private hookPageUnload;
34
37
  private sendBatch;
35
38
  private randomNonce;
@@ -1 +1 @@
1
- {"version":3,"file":"EventTracker.d.ts","sourceRoot":"","sources":["../../src/core/EventTracker.ts"],"names":[],"mappings":"AAmBA,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IAEjC,QAAQ,EAAE,MAAM,CAAC;IAEjB,OAAO,EAAE,MAAM,CAAC;IAEhB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,YAAY,EAAE,MAAM,CAAC;IAErB,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAKD,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAA6B;gBAExC,MAAM,EAAE,kBAAkB;IAkBtC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IActF,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKlC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKjC,QAAQ,IAAI,IAAI;IAKhB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAK/B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB5B,OAAO,IAAI,IAAI;IAYf,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,cAAc;YA+BR,SAAS;IAsCvB,OAAO,CAAC,WAAW;YASL,IAAI;CAenB"}
1
+ {"version":3,"file":"EventTracker.d.ts","sourceRoot":"","sources":["../../src/core/EventTracker.ts"],"names":[],"mappings":"AAiCA,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IAEjC,QAAQ,EAAE,MAAM,CAAC;IAEjB,OAAO,EAAE,MAAM,CAAC;IAEhB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,YAAY,EAAE,MAAM,CAAC;IAErB,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAMD,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAA6B;IAEpD,OAAO,CAAC,YAAY,CAAK;IAEzB,OAAO,CAAC,QAAQ,CAAS;gBAEb,MAAM,EAAE,kBAAkB;IAoBtC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAqBtF,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKlC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKjC,QAAQ,IAAI,IAAI;IAKhB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAK/B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB5B,OAAO,IAAI,IAAI;IAYf,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,cAAc;YA+BR,SAAS;IA4DvB,OAAO,CAAC,WAAW;YASL,IAAI;CAenB"}
@@ -13,6 +13,15 @@ export declare class GuardVideoPlayer implements PlayerInstance {
13
13
  private sessionId;
14
14
  private playlistNonce;
15
15
  private nonceRefreshInProgress;
16
+ private nonceRefreshTimer;
17
+ private retryBackoff;
18
+ private readonly MAX_BACKOFF;
19
+ private rateLimitCooldownUntil;
20
+ private nonceRefreshPromise;
21
+ private destroyed;
22
+ private networkRetryCount;
23
+ private readonly MAX_NETWORK_RETRIES;
24
+ private pendingRetryTimer;
16
25
  private _onRateChange;
17
26
  constructor(videoElement: HTMLVideoElement, videoId: string, config: PlayerConfig);
18
27
  private log;
@@ -27,7 +36,11 @@ export declare class GuardVideoPlayer implements PlayerInstance {
27
36
  private fetchEmbedToken;
28
37
  private solveChallenge;
29
38
  private acquireNonce;
39
+ private scheduleNonceRefresh;
30
40
  private refreshNonce;
41
+ private enterRateLimitCooldown;
42
+ private scheduleRetry;
43
+ stopLoading(): void;
31
44
  private initializePlayer;
32
45
  private initializeHls;
33
46
  private setupVideoEventListeners;
@@ -1 +1 @@
1
- {"version":3,"file":"player.d.ts","sourceRoot":"","sources":["../../src/core/player.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,YAAY,EAEZ,WAAW,EACX,cAAc,EACd,YAAY,EAIb,MAAM,SAAS,CAAC;AA8BjB,qBAAa,gBAAiB,YAAW,cAAc;IAqBnD,OAAO,CAAC,OAAO;IApBjB,OAAO,CAAC,YAAY,CAAmB;IACvC,OAAO,CAAC,GAAG,CAAoB;IAC/B,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,UAAU,CAAmC;IACrD,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,SAAS,CAAqB;IAEtC,OAAO,CAAC,aAAa,CAAuB;IAE5C,OAAO,CAAC,sBAAsB,CAAS;IAGvC,OAAO,CAAC,aAAa,CAAkC;gBAGrD,YAAY,EAAE,gBAAgB,EACtB,OAAO,EAAE,MAAM,EACvB,MAAM,EAAE,YAAY;IAqDtB,OAAO,CAAC,GAAG;IAMX,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,QAAQ;IAWhB,OAAO,CAAC,kBAAkB;IA2B1B,OAAO,CAAC,aAAa;IAyBrB,OAAO,CAAC,cAAc;YAWR,UAAU;YAkCV,sBAAsB;IA6CpC,OAAO,CAAC,gBAAgB;YA0CV,eAAe;YAgDf,cAAc;YAqDd,YAAY;YAsCZ,YAAY;YAYZ,gBAAgB;IAiC9B,OAAO,CAAC,aAAa;IAoGrB,OAAO,CAAC,wBAAwB;IAuBhC,OAAO,CAAC,WAAW;IASN,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B,KAAK,IAAI,IAAI;IAEb,cAAc,IAAI,MAAM;IAExB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAExB,WAAW,IAAI,MAAM;IAErB,SAAS,IAAI,MAAM;IAEnB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,gBAAgB,IAAI,YAAY,EAAE;IAWlC,iBAAiB,IAAI,YAAY,GAAG,IAAI;IAExC,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAOpC,QAAQ,IAAI,WAAW;IAEvB,OAAO,IAAI,IAAI;CA0BvB"}
1
+ {"version":3,"file":"player.d.ts","sourceRoot":"","sources":["../../src/core/player.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,YAAY,EAEZ,WAAW,EACX,cAAc,EACd,YAAY,EAIb,MAAM,SAAS,CAAC;AA8BjB,qBAAa,gBAAiB,YAAW,cAAc;IAuCnD,OAAO,CAAC,OAAO;IAtCjB,OAAO,CAAC,YAAY,CAAmB;IACvC,OAAO,CAAC,GAAG,CAAoB;IAC/B,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,UAAU,CAAmC;IACrD,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,SAAS,CAAqB;IAEtC,OAAO,CAAC,aAAa,CAAuB;IAE5C,OAAO,CAAC,sBAAsB,CAAS;IAEvC,OAAO,CAAC,iBAAiB,CAA8C;IAEvE,OAAO,CAAC,YAAY,CAAQ;IAE5B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IAErC,OAAO,CAAC,sBAAsB,CAAK;IAEnC,OAAO,CAAC,mBAAmB,CAA8B;IAEzD,OAAO,CAAC,SAAS,CAAS;IAE1B,OAAO,CAAC,iBAAiB,CAAK;IAE9B,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAK;IAEzC,OAAO,CAAC,iBAAiB,CAA8C;IAGvE,OAAO,CAAC,aAAa,CAAkC;gBAGrD,YAAY,EAAE,gBAAgB,EACtB,OAAO,EAAE,MAAM,EACvB,MAAM,EAAE,YAAY;IAqDtB,OAAO,CAAC,GAAG;IAMX,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,QAAQ;IAWhB,OAAO,CAAC,kBAAkB;IA2B1B,OAAO,CAAC,aAAa;IAyBrB,OAAO,CAAC,cAAc;YAWR,UAAU;YAkCV,sBAAsB;IA6CpC,OAAO,CAAC,gBAAgB;YA0CV,eAAe;YAgDf,cAAc;YAmEd,YAAY;IAsD1B,OAAO,CAAC,oBAAoB;YAgBd,YAAY;IAmB1B,OAAO,CAAC,sBAAsB;IAS9B,OAAO,CAAC,aAAa;IASd,WAAW,IAAI,IAAI;YAUZ,gBAAgB;IAiC9B,OAAO,CAAC,aAAa;IA6JrB,OAAO,CAAC,wBAAwB;IAsChC,OAAO,CAAC,WAAW;IASN,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAY3B,KAAK,IAAI,IAAI;IAEb,cAAc,IAAI,MAAM;IAExB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAExB,WAAW,IAAI,MAAM;IAErB,SAAS,IAAI,MAAM;IAEnB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,gBAAgB,IAAI,YAAY,EAAE;IAWlC,iBAAiB,IAAI,YAAY,GAAG,IAAI;IAExC,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAOpC,QAAQ,IAAI,WAAW;IAEvB,OAAO,IAAI,IAAI;CAuCvB"}
@@ -100,6 +100,7 @@ export interface PlayerInstance {
100
100
  getCurrentQuality(): QualityLevel | null;
101
101
  setQuality(levelIndex: number): void;
102
102
  getState(): PlayerState;
103
+ stopLoading(): void;
103
104
  destroy(): void;
104
105
  }
105
106
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
package/dist/index.esm.js CHANGED
@@ -68,8 +68,19 @@ class WatchChunkAccumulator {
68
68
  }
69
69
  }
70
70
 
71
+ const VALID_EVENT_TYPES = [
72
+ 'watch_chunk',
73
+ 'play',
74
+ 'pause',
75
+ 'seek',
76
+ 'ended',
77
+ 'quality_change',
78
+ 'error',
79
+ 'security_event',
80
+ ];
71
81
  const MAX_BATCH_SIZE = 25;
72
82
  const DEFAULT_FLUSH_INTERVAL = 5000;
83
+ const MAX_FLUSH_BACKOFF = 60000;
73
84
  class EventTracker {
74
85
  constructor(config) {
75
86
  this.buffer = [];
@@ -77,6 +88,8 @@ class EventTracker {
77
88
  this.accumulator = new WatchChunkAccumulator();
78
89
  this.destroyed = false;
79
90
  this._onBeforeUnload = null;
91
+ this.flushBackoff = 0;
92
+ this.flushing = false;
80
93
  this.config = {
81
94
  endpoint: config.endpoint,
82
95
  tokenId: config.tokenId,
@@ -92,6 +105,12 @@ class EventTracker {
92
105
  track(type, positionSeconds, payload) {
93
106
  if (this.destroyed)
94
107
  return;
108
+ if (!VALID_EVENT_TYPES.includes(type)) {
109
+ if (this.config.debug) {
110
+ console.warn('[GuardVideo EventTracker] Skipping unknown event type:', type);
111
+ }
112
+ return;
113
+ }
95
114
  this.buffer.push({
96
115
  event_type: type,
97
116
  event_at: new Date().toISOString(),
@@ -115,7 +134,7 @@ class EventTracker {
115
134
  this.config.sessionId = sessionId;
116
135
  }
117
136
  async flush() {
118
- if (this.destroyed)
137
+ if (this.destroyed || this.flushing)
119
138
  return;
120
139
  const chunks = this.accumulator.drain();
121
140
  for (const c of chunks) {
@@ -123,8 +142,14 @@ class EventTracker {
123
142
  }
124
143
  if (this.buffer.length === 0)
125
144
  return;
126
- const batch = this.buffer.splice(0, MAX_BATCH_SIZE);
127
- await this.sendBatch(batch);
145
+ this.flushing = true;
146
+ try {
147
+ const batch = this.buffer.splice(0, MAX_BATCH_SIZE);
148
+ await this.sendBatch(batch);
149
+ }
150
+ finally {
151
+ this.flushing = false;
152
+ }
128
153
  }
129
154
  destroy() {
130
155
  this.destroyed = true;
@@ -139,6 +164,11 @@ class EventTracker {
139
164
  startAutoFlush() {
140
165
  this.flushTimer = setInterval(() => this.flush(), this.config.flushIntervalMs);
141
166
  }
167
+ restartAutoFlush(intervalMs) {
168
+ if (this.flushTimer)
169
+ clearInterval(this.flushTimer);
170
+ this.flushTimer = setInterval(() => this.flush(), intervalMs);
171
+ }
142
172
  hookPageUnload() {
143
173
  if (typeof window === 'undefined')
144
174
  return;
@@ -184,8 +214,25 @@ class EventTracker {
184
214
  body,
185
215
  credentials: 'omit',
186
216
  });
187
- if (!resp.ok && this.config.debug) {
188
- console.warn('[GuardVideo EventTracker] Flush failed:', resp.status);
217
+ if (!resp.ok) {
218
+ if (resp.status === 429) {
219
+ this.flushBackoff = Math.min((this.flushBackoff || this.config.flushIntervalMs) * 2, MAX_FLUSH_BACKOFF);
220
+ if (this.config.debug) {
221
+ console.warn('[GuardVideo EventTracker] 429 — backing off to', this.flushBackoff, 'ms');
222
+ }
223
+ this.buffer.unshift(...events);
224
+ this.restartAutoFlush(this.flushBackoff);
225
+ return;
226
+ }
227
+ if (this.config.debug) {
228
+ console.warn('[GuardVideo EventTracker] Flush failed:', resp.status);
229
+ }
230
+ }
231
+ else {
232
+ if (this.flushBackoff > 0) {
233
+ this.flushBackoff = 0;
234
+ this.restartAutoFlush(this.config.flushIntervalMs);
235
+ }
189
236
  }
190
237
  }
191
238
  catch (err) {
@@ -401,6 +448,15 @@ class GuardVideoPlayer {
401
448
  this._onSecurityEvent = null;
402
449
  this.playlistNonce = null;
403
450
  this.nonceRefreshInProgress = false;
451
+ this.nonceRefreshTimer = null;
452
+ this.retryBackoff = 1000;
453
+ this.MAX_BACKOFF = 30000;
454
+ this.rateLimitCooldownUntil = 0;
455
+ this.nonceRefreshPromise = null;
456
+ this.destroyed = false;
457
+ this.networkRetryCount = 0;
458
+ this.MAX_NETWORK_RETRIES = 6;
459
+ this.pendingRetryTimer = null;
404
460
  this._onRateChange = this.enforceMaxRate.bind(this);
405
461
  this.videoElement = videoElement;
406
462
  this.config = {
@@ -611,9 +667,18 @@ class GuardVideoPlayer {
611
667
  async solveChallenge(tokenId) {
612
668
  if (!this.config.apiBaseUrl)
613
669
  return undefined;
670
+ if (Date.now() < this.rateLimitCooldownUntil) {
671
+ this.log('Challenge skipped — rate limit cooldown active');
672
+ return undefined;
673
+ }
614
674
  try {
615
675
  const url = this.config.apiBaseUrl + '/videos/challenge/' + encodeURIComponent(tokenId);
616
676
  const resp = await fetch(url, { credentials: 'omit' });
677
+ if (resp.status === 429) {
678
+ this.enterRateLimitCooldown();
679
+ this.log('Challenge hit 429 — entering cooldown');
680
+ return undefined;
681
+ }
617
682
  if (!resp.ok) {
618
683
  this.log('Challenge fetch failed (challenge may be disabled)', resp.status);
619
684
  return undefined;
@@ -639,6 +704,10 @@ class GuardVideoPlayer {
639
704
  async acquireNonce(tokenId) {
640
705
  if (!this.config.apiBaseUrl)
641
706
  return null;
707
+ if (Date.now() < this.rateLimitCooldownUntil) {
708
+ this.log('Nonce acquisition skipped — rate limit cooldown active');
709
+ return this.playlistNonce;
710
+ }
642
711
  try {
643
712
  const challengeResult = await this.solveChallenge(tokenId);
644
713
  const url = this.config.apiBaseUrl + '/videos/playlist-session';
@@ -652,12 +721,20 @@ class GuardVideoPlayer {
652
721
  body: JSON.stringify(body),
653
722
  credentials: 'omit',
654
723
  });
724
+ if (resp.status === 429) {
725
+ this.enterRateLimitCooldown();
726
+ this.log('Nonce acquisition hit 429 — entering cooldown');
727
+ return this.playlistNonce;
728
+ }
655
729
  if (!resp.ok) {
656
730
  this.log('Playlist session nonce acquisition failed', resp.status);
657
731
  return null;
658
732
  }
659
733
  const data = await resp.json();
660
734
  this.log('Playlist nonce acquired, expires in ' + data.expiresIn + 's');
735
+ this.retryBackoff = 1000;
736
+ this.networkRetryCount = 0;
737
+ this.scheduleNonceRefresh(data.expiresIn);
661
738
  return data.nonce;
662
739
  }
663
740
  catch (err) {
@@ -665,19 +742,58 @@ class GuardVideoPlayer {
665
742
  return null;
666
743
  }
667
744
  }
745
+ scheduleNonceRefresh(expiresInSeconds) {
746
+ if (this.nonceRefreshTimer)
747
+ clearTimeout(this.nonceRefreshTimer);
748
+ const refreshMs = Math.max(5000, expiresInSeconds * 750);
749
+ this.nonceRefreshTimer = setTimeout(() => {
750
+ if (this.destroyed)
751
+ return;
752
+ this.refreshNonce().catch(() => {
753
+ this.log('Proactive nonce refresh failed');
754
+ });
755
+ }, refreshMs);
756
+ }
668
757
  async refreshNonce() {
669
- if (this.nonceRefreshInProgress)
670
- return;
758
+ if (this.nonceRefreshInProgress && this.nonceRefreshPromise) {
759
+ return this.nonceRefreshPromise;
760
+ }
671
761
  if (!this.embedToken)
672
762
  return;
673
763
  this.nonceRefreshInProgress = true;
674
- try {
675
- const nonce = await this.acquireNonce(this.embedToken.tokenId);
676
- this.playlistNonce = nonce;
677
- }
678
- finally {
679
- this.nonceRefreshInProgress = false;
764
+ this.nonceRefreshPromise = (async () => {
765
+ try {
766
+ const nonce = await this.acquireNonce(this.embedToken.tokenId);
767
+ this.playlistNonce = nonce;
768
+ }
769
+ finally {
770
+ this.nonceRefreshInProgress = false;
771
+ this.nonceRefreshPromise = null;
772
+ }
773
+ })();
774
+ return this.nonceRefreshPromise;
775
+ }
776
+ enterRateLimitCooldown() {
777
+ this.rateLimitCooldownUntil = Date.now() + this.retryBackoff;
778
+ this.retryBackoff = Math.min(this.retryBackoff * 2, this.MAX_BACKOFF);
779
+ }
780
+ scheduleRetry(fn, delayMs) {
781
+ if (this.pendingRetryTimer)
782
+ clearTimeout(this.pendingRetryTimer);
783
+ this.pendingRetryTimer = setTimeout(() => {
784
+ this.pendingRetryTimer = null;
785
+ if (!this.destroyed && this.hls)
786
+ fn();
787
+ }, delayMs);
788
+ }
789
+ stopLoading() {
790
+ if (this.pendingRetryTimer) {
791
+ clearTimeout(this.pendingRetryTimer);
792
+ this.pendingRetryTimer = null;
680
793
  }
794
+ this.hls?.stopLoad();
795
+ this.networkRetryCount = 0;
796
+ this.retryBackoff = 1000;
681
797
  }
682
798
  async initializePlayer() {
683
799
  if (!this.embedToken) {
@@ -717,8 +833,12 @@ class GuardVideoPlayer {
717
833
  enableWorker: true,
718
834
  lowLatencyMode: false,
719
835
  liveSyncDurationCount: 3,
720
- manifestLoadingMaxRetry: 6,
721
- levelLoadingMaxRetry: 6,
836
+ manifestLoadingMaxRetry: 3,
837
+ manifestLoadingRetryDelay: 2000,
838
+ levelLoadingMaxRetry: 3,
839
+ levelLoadingRetryDelay: 2000,
840
+ fragLoadingMaxRetry: 4,
841
+ fragLoadingRetryDelay: 1000,
722
842
  xhrSetup(xhr, url) {
723
843
  if (url.includes('/watermark-stream/') && url.includes('.m3u8')) {
724
844
  if (self.playlistNonce) {
@@ -726,10 +846,6 @@ class GuardVideoPlayer {
726
846
  const nonceUrl = url + separator + 'nonce=' + encodeURIComponent(self.playlistNonce);
727
847
  xhr.open('GET', nonceUrl, true);
728
848
  self.log('Injected nonce into playlist request');
729
- self.playlistNonce = null;
730
- self.refreshNonce().catch(() => {
731
- self.log('Background nonce refresh failed');
732
- });
733
849
  }
734
850
  }
735
851
  },
@@ -741,6 +857,8 @@ class GuardVideoPlayer {
741
857
  this.log('HLS manifest parsed', { levels: data.levels.map((l) => l.height + 'p') });
742
858
  this.setState(PlayerState.READY);
743
859
  this.config.onReady();
860
+ this.retryBackoff = 1000;
861
+ this.networkRetryCount = 0;
744
862
  if (this.config.autoplay)
745
863
  this.play();
746
864
  });
@@ -756,28 +874,77 @@ class GuardVideoPlayer {
756
874
  this.currentQuality = quality;
757
875
  this.log('Quality switched to ' + quality.name);
758
876
  this.config.onQualityChange(quality.name);
877
+ this.eventTracker?.track('quality_change', this.videoElement.currentTime, {
878
+ level: data.level,
879
+ height: level.height,
880
+ bitrate: level.bitrate,
881
+ });
759
882
  });
760
883
  this.hls.on(Hls.Events.ERROR, (_event, data) => {
761
884
  this.error('HLS Error', data);
885
+ this.eventTracker?.track('error', this.videoElement.currentTime, {
886
+ type: data.type,
887
+ details: data.details,
888
+ fatal: data.fatal,
889
+ });
890
+ if (this.destroyed)
891
+ return;
892
+ if (Date.now() < this.rateLimitCooldownUntil) {
893
+ this.log('Suppressing retry — rate limit cooldown active (' +
894
+ Math.ceil((this.rateLimitCooldownUntil - Date.now()) / 1000) + 's remaining)');
895
+ if (data.fatal) {
896
+ const delay = this.rateLimitCooldownUntil - Date.now() + 500;
897
+ this.scheduleRetry(() => this.hls?.startLoad(), delay);
898
+ }
899
+ return;
900
+ }
901
+ const httpStatus = data.response?.code;
902
+ if (httpStatus === 429) {
903
+ this.enterRateLimitCooldown();
904
+ this.log('429 detected — entering cooldown for ' + this.retryBackoff + 'ms');
905
+ this.scheduleRetry(() => {
906
+ if (this.embedToken?.forensicWatermark) {
907
+ this.refreshNonce().then(() => this.hls?.startLoad()).catch(() => this.hls?.startLoad());
908
+ }
909
+ else {
910
+ this.hls?.startLoad();
911
+ }
912
+ }, this.retryBackoff);
913
+ return;
914
+ }
762
915
  if (data.type === Hls.ErrorTypes.NETWORK_ERROR &&
763
916
  data.details === Hls.ErrorDetails.LEVEL_LOAD_ERROR &&
764
917
  this.embedToken?.forensicWatermark) {
765
- this.log('Playlist load failed — refreshing nonce before retry');
918
+ this.networkRetryCount++;
919
+ if (this.networkRetryCount > this.MAX_NETWORK_RETRIES) {
920
+ this.error('Max network retries exceeded for playlist load');
921
+ this.handleError({ code: 'NETWORK_ERROR', message: 'Playlist load failed after multiple retries', fatal: true, details: data });
922
+ return;
923
+ }
924
+ this.log('Playlist load failed — refreshing nonce before retry (' + this.networkRetryCount + '/' + this.MAX_NETWORK_RETRIES + ')');
766
925
  this.refreshNonce().then(() => {
767
- setTimeout(() => this.hls?.startLoad(), 500);
926
+ this.scheduleRetry(() => this.hls?.startLoad(), this.retryBackoff);
768
927
  }).catch(() => {
769
- setTimeout(() => this.hls?.startLoad(), 1000);
928
+ this.scheduleRetry(() => this.hls?.startLoad(), this.retryBackoff);
770
929
  });
930
+ this.retryBackoff = Math.min(this.retryBackoff * 1.5, this.MAX_BACKOFF);
771
931
  return;
772
932
  }
773
933
  if (data.fatal) {
774
934
  switch (data.type) {
775
935
  case Hls.ErrorTypes.NETWORK_ERROR:
776
- this.error('Network error, attempting recovery...');
936
+ this.networkRetryCount++;
937
+ if (this.networkRetryCount > this.MAX_NETWORK_RETRIES) {
938
+ this.error('Max network retries exceeded — giving up');
939
+ this.handleError({ code: 'NETWORK_ERROR', message: 'Network error after multiple retries. Please check your connection.', fatal: true, details: data });
940
+ return;
941
+ }
942
+ this.error('Network error, attempting recovery (' + this.networkRetryCount + '/' + this.MAX_NETWORK_RETRIES + ')...');
777
943
  if (this.embedToken?.forensicWatermark) {
778
944
  this.refreshNonce().catch(() => { });
779
945
  }
780
- setTimeout(() => this.hls?.startLoad(), 1000);
946
+ this.scheduleRetry(() => this.hls?.startLoad(), this.retryBackoff);
947
+ this.retryBackoff = Math.min(this.retryBackoff * 1.5, this.MAX_BACKOFF);
781
948
  break;
782
949
  case Hls.ErrorTypes.MEDIA_ERROR:
783
950
  this.error('Media error, attempting recovery...');
@@ -791,8 +958,21 @@ class GuardVideoPlayer {
791
958
  this.setupVideoEventListeners();
792
959
  }
793
960
  setupVideoEventListeners() {
794
- this.videoElement.addEventListener('playing', () => this.setState(PlayerState.PLAYING));
795
- this.videoElement.addEventListener('pause', () => this.setState(PlayerState.PAUSED));
961
+ this.videoElement.addEventListener('playing', () => {
962
+ this.setState(PlayerState.PLAYING);
963
+ if (this.hls)
964
+ this.hls.startLoad(-1);
965
+ });
966
+ this.videoElement.addEventListener('pause', () => {
967
+ this.setState(PlayerState.PAUSED);
968
+ if (this.hls && !this.videoElement.seeking) {
969
+ this.hls.stopLoad();
970
+ if (this.pendingRetryTimer) {
971
+ clearTimeout(this.pendingRetryTimer);
972
+ this.pendingRetryTimer = null;
973
+ }
974
+ }
975
+ });
796
976
  this.videoElement.addEventListener('waiting', () => this.setState(PlayerState.BUFFERING));
797
977
  this.videoElement.addEventListener('error', () => {
798
978
  const error = this.videoElement.error;
@@ -819,6 +999,8 @@ class GuardVideoPlayer {
819
999
  }
820
1000
  async play() {
821
1001
  try {
1002
+ this.networkRetryCount = 0;
1003
+ this.retryBackoff = 1000;
822
1004
  await this.videoElement.play();
823
1005
  }
824
1006
  catch (err) {
@@ -855,6 +1037,15 @@ class GuardVideoPlayer {
855
1037
  getState() { return this.state; }
856
1038
  destroy() {
857
1039
  this.log('Destroying player');
1040
+ this.destroyed = true;
1041
+ if (this.pendingRetryTimer) {
1042
+ clearTimeout(this.pendingRetryTimer);
1043
+ this.pendingRetryTimer = null;
1044
+ }
1045
+ if (this.nonceRefreshTimer) {
1046
+ clearTimeout(this.nonceRefreshTimer);
1047
+ this.nonceRefreshTimer = null;
1048
+ }
858
1049
  if (this.eventTracker) {
859
1050
  this.eventTracker.destroy();
860
1051
  this.eventTracker = null;
@@ -2565,6 +2756,7 @@ class PlayerUI {
2565
2756
  }
2566
2757
  play() { return this.corePlayer.play(); }
2567
2758
  pause() { return this.corePlayer.pause(); }
2759
+ stopLoading() { return this.corePlayer.stopLoading(); }
2568
2760
  seek(t) { return this.corePlayer.seek(t); }
2569
2761
  getCurrentTime() { return this.corePlayer.getCurrentTime(); }
2570
2762
  getDuration() { return this.corePlayer.getDuration(); }
@@ -2624,6 +2816,7 @@ const GuardVideoPlayerComponent = forwardRef((props, ref) => {
2624
2816
  useImperativeHandle(ref, () => ({
2625
2817
  play: () => uiRef.current?.play() ?? Promise.resolve(),
2626
2818
  pause: () => uiRef.current?.pause(),
2819
+ stopLoading: () => uiRef.current?.stopLoading(),
2627
2820
  seek: (t) => uiRef.current?.seek(t),
2628
2821
  getCurrentTime: () => uiRef.current?.getCurrentTime() ?? 0,
2629
2822
  getDuration: () => uiRef.current?.getDuration() ?? 0,