@guardvideo/player-sdk 3.5.0 → 3.7.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.
@@ -18,6 +18,10 @@ export declare class GuardVideoPlayer implements PlayerInstance {
18
18
  private readonly MAX_BACKOFF;
19
19
  private rateLimitCooldownUntil;
20
20
  private nonceRefreshPromise;
21
+ private destroyed;
22
+ private networkRetryCount;
23
+ private readonly MAX_NETWORK_RETRIES;
24
+ private pendingRetryTimer;
21
25
  private _onRateChange;
22
26
  constructor(videoElement: HTMLVideoElement, videoId: string, config: PlayerConfig);
23
27
  private log;
@@ -35,6 +39,8 @@ export declare class GuardVideoPlayer implements PlayerInstance {
35
39
  private scheduleNonceRefresh;
36
40
  private refreshNonce;
37
41
  private enterRateLimitCooldown;
42
+ private scheduleRetry;
43
+ stopLoading(): void;
38
44
  private initializePlayer;
39
45
  private initializeHls;
40
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;IA+BnD,OAAO,CAAC,OAAO;IA9BjB,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;IAGzD,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;IAqD1B,OAAO,CAAC,oBAAoB;YAed,YAAY;IAmB1B,OAAO,CAAC,sBAAsB;YAKhB,gBAAgB;IAiC9B,OAAO,CAAC,aAAa;IA6IrB,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;CAgCvB"}
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
@@ -453,6 +453,10 @@ class GuardVideoPlayer {
453
453
  this.MAX_BACKOFF = 30000;
454
454
  this.rateLimitCooldownUntil = 0;
455
455
  this.nonceRefreshPromise = null;
456
+ this.destroyed = false;
457
+ this.networkRetryCount = 0;
458
+ this.MAX_NETWORK_RETRIES = 6;
459
+ this.pendingRetryTimer = null;
456
460
  this._onRateChange = this.enforceMaxRate.bind(this);
457
461
  this.videoElement = videoElement;
458
462
  this.config = {
@@ -729,6 +733,7 @@ class GuardVideoPlayer {
729
733
  const data = await resp.json();
730
734
  this.log('Playlist nonce acquired, expires in ' + data.expiresIn + 's');
731
735
  this.retryBackoff = 1000;
736
+ this.networkRetryCount = 0;
732
737
  this.scheduleNonceRefresh(data.expiresIn);
733
738
  return data.nonce;
734
739
  }
@@ -742,6 +747,8 @@ class GuardVideoPlayer {
742
747
  clearTimeout(this.nonceRefreshTimer);
743
748
  const refreshMs = Math.max(5000, expiresInSeconds * 750);
744
749
  this.nonceRefreshTimer = setTimeout(() => {
750
+ if (this.destroyed)
751
+ return;
745
752
  this.refreshNonce().catch(() => {
746
753
  this.log('Proactive nonce refresh failed');
747
754
  });
@@ -770,6 +777,24 @@ class GuardVideoPlayer {
770
777
  this.rateLimitCooldownUntil = Date.now() + this.retryBackoff;
771
778
  this.retryBackoff = Math.min(this.retryBackoff * 2, this.MAX_BACKOFF);
772
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;
793
+ }
794
+ this.hls?.stopLoad();
795
+ this.networkRetryCount = 0;
796
+ this.retryBackoff = 1000;
797
+ }
773
798
  async initializePlayer() {
774
799
  if (!this.embedToken) {
775
800
  throw new Error('No embed token available');
@@ -833,6 +858,7 @@ class GuardVideoPlayer {
833
858
  this.setState(PlayerState.READY);
834
859
  this.config.onReady();
835
860
  this.retryBackoff = 1000;
861
+ this.networkRetryCount = 0;
836
862
  if (this.config.autoplay)
837
863
  this.play();
838
864
  });
@@ -861,12 +887,14 @@ class GuardVideoPlayer {
861
887
  details: data.details,
862
888
  fatal: data.fatal,
863
889
  });
890
+ if (this.destroyed)
891
+ return;
864
892
  if (Date.now() < this.rateLimitCooldownUntil) {
865
893
  this.log('Suppressing retry — rate limit cooldown active (' +
866
894
  Math.ceil((this.rateLimitCooldownUntil - Date.now()) / 1000) + 's remaining)');
867
895
  if (data.fatal) {
868
896
  const delay = this.rateLimitCooldownUntil - Date.now() + 500;
869
- setTimeout(() => this.hls?.startLoad(), delay);
897
+ this.scheduleRetry(() => this.hls?.startLoad(), delay);
870
898
  }
871
899
  return;
872
900
  }
@@ -874,7 +902,7 @@ class GuardVideoPlayer {
874
902
  if (httpStatus === 429) {
875
903
  this.enterRateLimitCooldown();
876
904
  this.log('429 detected — entering cooldown for ' + this.retryBackoff + 'ms');
877
- setTimeout(() => {
905
+ this.scheduleRetry(() => {
878
906
  if (this.embedToken?.forensicWatermark) {
879
907
  this.refreshNonce().then(() => this.hls?.startLoad()).catch(() => this.hls?.startLoad());
880
908
  }
@@ -887,11 +915,17 @@ class GuardVideoPlayer {
887
915
  if (data.type === Hls.ErrorTypes.NETWORK_ERROR &&
888
916
  data.details === Hls.ErrorDetails.LEVEL_LOAD_ERROR &&
889
917
  this.embedToken?.forensicWatermark) {
890
- 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 + ')');
891
925
  this.refreshNonce().then(() => {
892
- setTimeout(() => this.hls?.startLoad(), this.retryBackoff);
926
+ this.scheduleRetry(() => this.hls?.startLoad(), this.retryBackoff);
893
927
  }).catch(() => {
894
- setTimeout(() => this.hls?.startLoad(), this.retryBackoff);
928
+ this.scheduleRetry(() => this.hls?.startLoad(), this.retryBackoff);
895
929
  });
896
930
  this.retryBackoff = Math.min(this.retryBackoff * 1.5, this.MAX_BACKOFF);
897
931
  return;
@@ -899,11 +933,17 @@ class GuardVideoPlayer {
899
933
  if (data.fatal) {
900
934
  switch (data.type) {
901
935
  case Hls.ErrorTypes.NETWORK_ERROR:
902
- 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 + ')...');
903
943
  if (this.embedToken?.forensicWatermark) {
904
944
  this.refreshNonce().catch(() => { });
905
945
  }
906
- setTimeout(() => this.hls?.startLoad(), this.retryBackoff);
946
+ this.scheduleRetry(() => this.hls?.startLoad(), this.retryBackoff);
907
947
  this.retryBackoff = Math.min(this.retryBackoff * 1.5, this.MAX_BACKOFF);
908
948
  break;
909
949
  case Hls.ErrorTypes.MEDIA_ERROR:
@@ -918,8 +958,21 @@ class GuardVideoPlayer {
918
958
  this.setupVideoEventListeners();
919
959
  }
920
960
  setupVideoEventListeners() {
921
- this.videoElement.addEventListener('playing', () => this.setState(PlayerState.PLAYING));
922
- 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
+ });
923
976
  this.videoElement.addEventListener('waiting', () => this.setState(PlayerState.BUFFERING));
924
977
  this.videoElement.addEventListener('error', () => {
925
978
  const error = this.videoElement.error;
@@ -946,6 +999,8 @@ class GuardVideoPlayer {
946
999
  }
947
1000
  async play() {
948
1001
  try {
1002
+ this.networkRetryCount = 0;
1003
+ this.retryBackoff = 1000;
949
1004
  await this.videoElement.play();
950
1005
  }
951
1006
  catch (err) {
@@ -982,6 +1037,11 @@ class GuardVideoPlayer {
982
1037
  getState() { return this.state; }
983
1038
  destroy() {
984
1039
  this.log('Destroying player');
1040
+ this.destroyed = true;
1041
+ if (this.pendingRetryTimer) {
1042
+ clearTimeout(this.pendingRetryTimer);
1043
+ this.pendingRetryTimer = null;
1044
+ }
985
1045
  if (this.nonceRefreshTimer) {
986
1046
  clearTimeout(this.nonceRefreshTimer);
987
1047
  this.nonceRefreshTimer = null;
@@ -1815,6 +1875,7 @@ class PlayerUI {
1815
1875
  this._ctxTargetBound = () => { };
1816
1876
  this._ctxKeyDownBound = () => { };
1817
1877
  this._watermarkObserver = null;
1878
+ this._watermarkStylePollTimer = null;
1818
1879
  this._watermarkText = '';
1819
1880
  this._watermarkDriftTimer = null;
1820
1881
  const accent = config.branding?.accentColor ?? '#00e5a0';
@@ -2492,6 +2553,7 @@ class PlayerUI {
2492
2553
  tampered = true;
2493
2554
  }
2494
2555
  if (m.type === 'attributes' && m.target === this.watermarkCanvas) {
2556
+ this.watermarkCanvas.removeAttribute('style');
2495
2557
  this.watermarkCanvas.className = 'gvp-watermark-canvas';
2496
2558
  this.watermarkCanvas.setAttribute('aria-hidden', 'true');
2497
2559
  this._renderCanvasWatermark(this._watermarkText);
@@ -2505,14 +2567,51 @@ class PlayerUI {
2505
2567
  }
2506
2568
  }
2507
2569
  if (tampered) {
2508
- this.root.dispatchEvent(new CustomEvent('gv:security', {
2509
- bubbles: true,
2510
- detail: { type: 'watermark_tamper', timestamp: Date.now() },
2511
- }));
2570
+ this._onWatermarkTamper();
2512
2571
  }
2513
2572
  });
2514
2573
  this._watermarkObserver.observe(this.root, { childList: true });
2515
2574
  this._watermarkObserver.observe(this.watermarkDiv, { attributes: true, childList: true });
2575
+ this._watermarkObserver.observe(this.watermarkCanvas, { attributes: true });
2576
+ if (this._watermarkStylePollTimer)
2577
+ clearInterval(this._watermarkStylePollTimer);
2578
+ this._watermarkStylePollTimer = setInterval(() => {
2579
+ if (!this._watermarkText)
2580
+ return;
2581
+ const divHidden = this._isElementHidden(this.watermarkDiv);
2582
+ const canvasHidden = this._isElementHidden(this.watermarkCanvas);
2583
+ if (divHidden || canvasHidden) {
2584
+ this.watermarkDiv.removeAttribute('style');
2585
+ this.watermarkDiv.className = 'gvp-watermark';
2586
+ this.watermarkCanvas.removeAttribute('style');
2587
+ this.watermarkCanvas.className = 'gvp-watermark-canvas';
2588
+ this._purgeWatermarkOverrideStyles();
2589
+ this._onWatermarkTamper();
2590
+ }
2591
+ }, 500);
2592
+ }
2593
+ _isElementHidden(el) {
2594
+ const cs = getComputedStyle(el);
2595
+ return (cs.display === 'none' ||
2596
+ cs.visibility === 'hidden' ||
2597
+ parseFloat(cs.opacity) < 0.01 ||
2598
+ (el.offsetWidth === 0 && el.offsetHeight === 0));
2599
+ }
2600
+ _purgeWatermarkOverrideStyles() {
2601
+ const styles = this.root.querySelectorAll('style');
2602
+ styles.forEach((s) => {
2603
+ const text = s.textContent ?? '';
2604
+ if (/gvp-watermark/i.test(text)) {
2605
+ s.remove();
2606
+ }
2607
+ });
2608
+ }
2609
+ _onWatermarkTamper() {
2610
+ this.corePlayer.pause();
2611
+ this.root.dispatchEvent(new CustomEvent('gv:security', {
2612
+ bubbles: true,
2613
+ detail: { type: 'watermark_tamper', timestamp: Date.now() },
2614
+ }));
2516
2615
  }
2517
2616
  _refillWatermark() {
2518
2617
  const seed = this._hashCode(this._watermarkText);
@@ -2696,6 +2795,7 @@ class PlayerUI {
2696
2795
  }
2697
2796
  play() { return this.corePlayer.play(); }
2698
2797
  pause() { return this.corePlayer.pause(); }
2798
+ stopLoading() { return this.corePlayer.stopLoading(); }
2699
2799
  seek(t) { return this.corePlayer.seek(t); }
2700
2800
  getCurrentTime() { return this.corePlayer.getCurrentTime(); }
2701
2801
  getDuration() { return this.corePlayer.getDuration(); }
@@ -2723,6 +2823,8 @@ class PlayerUI {
2723
2823
  this._watermarkObserver?.disconnect();
2724
2824
  if (this._watermarkDriftTimer)
2725
2825
  clearInterval(this._watermarkDriftTimer);
2826
+ if (this._watermarkStylePollTimer)
2827
+ clearInterval(this._watermarkStylePollTimer);
2726
2828
  this.corePlayer.destroy();
2727
2829
  this.root.remove();
2728
2830
  }
@@ -2755,6 +2857,7 @@ const GuardVideoPlayerComponent = forwardRef((props, ref) => {
2755
2857
  useImperativeHandle(ref, () => ({
2756
2858
  play: () => uiRef.current?.play() ?? Promise.resolve(),
2757
2859
  pause: () => uiRef.current?.pause(),
2860
+ stopLoading: () => uiRef.current?.stopLoading(),
2758
2861
  seek: (t) => uiRef.current?.seek(t),
2759
2862
  getCurrentTime: () => uiRef.current?.getCurrentTime() ?? 0,
2760
2863
  getDuration: () => uiRef.current?.getDuration() ?? 0,