@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.
- package/dist/core/EventTracker.d.ts +3 -0
- package/dist/core/EventTracker.d.ts.map +1 -1
- package/dist/core/player.d.ts +13 -0
- package/dist/core/player.d.ts.map +1 -1
- package/dist/core/types.d.ts +1 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.esm.js +219 -26
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +219 -26
- package/dist/index.js.map +1 -1
- package/dist/react/GuardVideoPlayer.d.ts.map +1 -1
- package/dist/ui/PlayerUI.d.ts +1 -0
- package/dist/ui/PlayerUI.d.ts.map +1 -1
- package/dist/vanilla/guardvideo-player.js +219 -27
- package/dist/vanilla/guardvideo-player.js.map +1 -1
- package/dist/vanilla/guardvideo-player.min.js +1 -1
- package/dist/vanilla/guardvideo-player.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -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":"
|
|
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"}
|
package/dist/core/player.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/core/types.d.ts
CHANGED
package/dist/core/types.d.ts.map
CHANGED
|
@@ -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
|
-
|
|
127
|
-
|
|
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
|
|
188
|
-
|
|
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
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
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:
|
|
721
|
-
|
|
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.
|
|
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
|
-
|
|
926
|
+
this.scheduleRetry(() => this.hls?.startLoad(), this.retryBackoff);
|
|
768
927
|
}).catch(() => {
|
|
769
|
-
|
|
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.
|
|
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
|
-
|
|
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', () =>
|
|
795
|
-
|
|
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,
|