@thestatic-tv/dcl-sdk 2.5.1 → 2.5.2

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/index.d.mts CHANGED
@@ -995,6 +995,10 @@ declare class StaticTVClient {
995
995
  */
996
996
  getConfig(): StaticTVConfig;
997
997
  private _currentVideoUrl;
998
+ private _pendingVideoData;
999
+ private _streamVerified;
1000
+ private _verificationTimeoutId;
1001
+ private _videoEventsRegistered;
998
1002
  /**
999
1003
  * Play a video on the configured videoScreen entity.
1000
1004
  * Called by Guide UI and Admin Panel.
@@ -1013,15 +1017,41 @@ declare class StaticTVClient {
1013
1017
  * @internal
1014
1018
  */
1015
1019
  private _playVideoInternal;
1020
+ /**
1021
+ * Register video event handlers for stream verification
1022
+ * @internal
1023
+ */
1024
+ private _registerVideoEvents;
1025
+ /**
1026
+ * Start stream verification timeout
1027
+ * @internal
1028
+ */
1029
+ private _startStreamVerification;
1030
+ /**
1031
+ * Handle stream that's offline or failed to verify
1032
+ * @internal
1033
+ */
1034
+ private _handleStreamOffline;
1035
+ /**
1036
+ * Clear verification timeout
1037
+ * @internal
1038
+ */
1039
+ private _clearVerificationTimeout;
1016
1040
  /**
1017
1041
  * Get the currently playing video URL
1018
1042
  */
1019
1043
  get currentVideoUrl(): string;
1020
1044
  /**
1021
1045
  * Internal handler for Guide video selection
1046
+ * Tries to play the stream and verifies it's working (like M1D-HQ behavior)
1022
1047
  * @internal
1023
1048
  */
1024
1049
  _handleGuideVideoSelect(video: GuideVideo): void;
1050
+ /**
1051
+ * Play video with stream verification for live content
1052
+ * @internal
1053
+ */
1054
+ private _playVideoWithVerification;
1025
1055
  /**
1026
1056
  * Internal handler for broadcast messages
1027
1057
  * @internal
package/dist/index.d.ts CHANGED
@@ -995,6 +995,10 @@ declare class StaticTVClient {
995
995
  */
996
996
  getConfig(): StaticTVConfig;
997
997
  private _currentVideoUrl;
998
+ private _pendingVideoData;
999
+ private _streamVerified;
1000
+ private _verificationTimeoutId;
1001
+ private _videoEventsRegistered;
998
1002
  /**
999
1003
  * Play a video on the configured videoScreen entity.
1000
1004
  * Called by Guide UI and Admin Panel.
@@ -1013,15 +1017,41 @@ declare class StaticTVClient {
1013
1017
  * @internal
1014
1018
  */
1015
1019
  private _playVideoInternal;
1020
+ /**
1021
+ * Register video event handlers for stream verification
1022
+ * @internal
1023
+ */
1024
+ private _registerVideoEvents;
1025
+ /**
1026
+ * Start stream verification timeout
1027
+ * @internal
1028
+ */
1029
+ private _startStreamVerification;
1030
+ /**
1031
+ * Handle stream that's offline or failed to verify
1032
+ * @internal
1033
+ */
1034
+ private _handleStreamOffline;
1035
+ /**
1036
+ * Clear verification timeout
1037
+ * @internal
1038
+ */
1039
+ private _clearVerificationTimeout;
1016
1040
  /**
1017
1041
  * Get the currently playing video URL
1018
1042
  */
1019
1043
  get currentVideoUrl(): string;
1020
1044
  /**
1021
1045
  * Internal handler for Guide video selection
1046
+ * Tries to play the stream and verifies it's working (like M1D-HQ behavior)
1022
1047
  * @internal
1023
1048
  */
1024
1049
  _handleGuideVideoSelect(video: GuideVideo): void;
1050
+ /**
1051
+ * Play video with stream verification for live content
1052
+ * @internal
1053
+ */
1054
+ private _playVideoWithVerification;
1025
1055
  /**
1026
1056
  * Internal handler for broadcast messages
1027
1057
  * @internal
package/dist/index.js CHANGED
@@ -3557,6 +3557,10 @@ var StaticTVClient = class {
3557
3557
  // --- VIDEO PLAYBACK (Internal handler for videoScreen) ---
3558
3558
  // =============================================================================
3559
3559
  this._currentVideoUrl = "";
3560
+ this._pendingVideoData = null;
3561
+ this._streamVerified = false;
3562
+ this._verificationTimeoutId = null;
3563
+ this._videoEventsRegistered = false;
3560
3564
  this._featuresReadyPromise = new Promise((resolve) => {
3561
3565
  this._featuresReadyResolve = resolve;
3562
3566
  });
@@ -3779,9 +3783,11 @@ var StaticTVClient = class {
3779
3783
  * Internal video player - handles both regular videos and fallback
3780
3784
  * @internal
3781
3785
  */
3782
- _playVideoInternal(url, isFallback = false) {
3786
+ _playVideoInternal(url, isFallback = false, isLiveStream = false) {
3783
3787
  const screen = this.config.videoScreen;
3784
3788
  if (screen === void 0) return;
3789
+ this._clearVerificationTimeout();
3790
+ this._streamVerified = false;
3785
3791
  if (import_ecs3.VideoPlayer.has(screen)) {
3786
3792
  import_ecs3.VideoPlayer.deleteFrom(screen);
3787
3793
  }
@@ -3795,6 +3801,74 @@ var StaticTVClient = class {
3795
3801
  import_ecs3.Material.setBasicMaterial(screen, {
3796
3802
  texture: import_ecs3.Material.Texture.Video({ videoPlayerEntity: screen })
3797
3803
  });
3804
+ if (!this._videoEventsRegistered) {
3805
+ this._registerVideoEvents();
3806
+ }
3807
+ if (isLiveStream && !isFallback) {
3808
+ this._startStreamVerification();
3809
+ }
3810
+ }
3811
+ /**
3812
+ * Register video event handlers for stream verification
3813
+ * @internal
3814
+ */
3815
+ _registerVideoEvents() {
3816
+ const screen = this.config.videoScreen;
3817
+ if (screen === void 0) return;
3818
+ this._videoEventsRegistered = true;
3819
+ import_ecs3.videoEventsSystem.registerVideoEventsEntity(screen, (videoEvent) => {
3820
+ if (videoEvent.state === import_ecs3.VideoState.VS_READY || videoEvent.state === import_ecs3.VideoState.VS_PLAYING) {
3821
+ if (this._pendingVideoData && !this._streamVerified) {
3822
+ this._streamVerified = true;
3823
+ this._clearVerificationTimeout();
3824
+ this.log(`Stream verified: ${this._pendingVideoData.name}`);
3825
+ }
3826
+ }
3827
+ if (videoEvent.state === import_ecs3.VideoState.VS_ERROR) {
3828
+ if (this._pendingVideoData) {
3829
+ this.log(`Stream error for: ${this._pendingVideoData.name}`);
3830
+ this._handleStreamOffline();
3831
+ }
3832
+ }
3833
+ });
3834
+ }
3835
+ /**
3836
+ * Start stream verification timeout
3837
+ * @internal
3838
+ */
3839
+ _startStreamVerification() {
3840
+ if (this._pendingVideoData) {
3841
+ this.showNotification(`Connecting to ${this._pendingVideoData.name}...`, 1e4);
3842
+ }
3843
+ this._verificationTimeoutId = setTimeout(() => {
3844
+ if (!this._streamVerified && this._pendingVideoData) {
3845
+ this.log(`Stream verification timeout for: ${this._pendingVideoData.name}`);
3846
+ this._handleStreamOffline();
3847
+ }
3848
+ }, 8e3);
3849
+ }
3850
+ /**
3851
+ * Handle stream that's offline or failed to verify
3852
+ * @internal
3853
+ */
3854
+ _handleStreamOffline() {
3855
+ const videoData = this._pendingVideoData;
3856
+ this._pendingVideoData = null;
3857
+ this._clearVerificationTimeout();
3858
+ if (videoData) {
3859
+ this.showNotification(`${videoData.name} is offline`, 4e3);
3860
+ }
3861
+ this.stopVideo();
3862
+ }
3863
+ /**
3864
+ * Clear verification timeout
3865
+ * @internal
3866
+ */
3867
+ _clearVerificationTimeout() {
3868
+ if (this._verificationTimeoutId) {
3869
+ clearTimeout(this._verificationTimeoutId);
3870
+ this._verificationTimeoutId = null;
3871
+ }
3798
3872
  }
3799
3873
  /**
3800
3874
  * Get the currently playing video URL
@@ -3804,16 +3878,31 @@ var StaticTVClient = class {
3804
3878
  }
3805
3879
  /**
3806
3880
  * Internal handler for Guide video selection
3881
+ * Tries to play the stream and verifies it's working (like M1D-HQ behavior)
3807
3882
  * @internal
3808
3883
  */
3809
3884
  _handleGuideVideoSelect(video) {
3810
- if (video.channelId && video.isLive === false) {
3811
- this.showNotification(`${video.name} is offline`);
3812
- this.stopVideo();
3813
- return;
3885
+ if (!video.src) return;
3886
+ this._pendingVideoData = video;
3887
+ const isLiveStream = video.channelId !== void 0 || video.src.includes(".m3u8") || video.src.includes("media.thestatic.tv");
3888
+ this._playVideoWithVerification(video, isLiveStream);
3889
+ }
3890
+ /**
3891
+ * Play video with stream verification for live content
3892
+ * @internal
3893
+ */
3894
+ _playVideoWithVerification(video, isLiveStream) {
3895
+ const screen = this.config.videoScreen;
3896
+ if (screen !== void 0) {
3897
+ this.log(`Playing video: ${video.src} (live: ${isLiveStream})`);
3898
+ this._currentVideoUrl = video.src;
3899
+ this._playVideoInternal(video.src, false, isLiveStream);
3900
+ if (this.guideUI) {
3901
+ this.guideUI.currentVideoId = video.id;
3902
+ }
3814
3903
  }
3815
- if (video.src) {
3816
- this.playVideo(video.src);
3904
+ if (this.config.onVideoPlay) {
3905
+ this.config.onVideoPlay(video.src);
3817
3906
  }
3818
3907
  }
3819
3908
  /**
package/dist/index.mjs CHANGED
@@ -3449,7 +3449,7 @@ function setupStaticUI(client) {
3449
3449
  }
3450
3450
 
3451
3451
  // src/StaticTVClient.ts
3452
- import { VideoPlayer, Material } from "@dcl/sdk/ecs";
3452
+ import { VideoPlayer, Material, videoEventsSystem, VideoState } from "@dcl/sdk/ecs";
3453
3453
  var DEFAULT_BASE_URL = "https://thestatic.tv/api/v1/dcl";
3454
3454
  var DEFAULT_FALLBACK_VIDEO = "https://media.thestatic.tv/fallback-loop.mp4";
3455
3455
  var KEY_TYPE_CHANNEL = "channel";
@@ -3514,6 +3514,10 @@ var StaticTVClient = class {
3514
3514
  // --- VIDEO PLAYBACK (Internal handler for videoScreen) ---
3515
3515
  // =============================================================================
3516
3516
  this._currentVideoUrl = "";
3517
+ this._pendingVideoData = null;
3518
+ this._streamVerified = false;
3519
+ this._verificationTimeoutId = null;
3520
+ this._videoEventsRegistered = false;
3517
3521
  this._featuresReadyPromise = new Promise((resolve) => {
3518
3522
  this._featuresReadyResolve = resolve;
3519
3523
  });
@@ -3736,9 +3740,11 @@ var StaticTVClient = class {
3736
3740
  * Internal video player - handles both regular videos and fallback
3737
3741
  * @internal
3738
3742
  */
3739
- _playVideoInternal(url, isFallback = false) {
3743
+ _playVideoInternal(url, isFallback = false, isLiveStream = false) {
3740
3744
  const screen = this.config.videoScreen;
3741
3745
  if (screen === void 0) return;
3746
+ this._clearVerificationTimeout();
3747
+ this._streamVerified = false;
3742
3748
  if (VideoPlayer.has(screen)) {
3743
3749
  VideoPlayer.deleteFrom(screen);
3744
3750
  }
@@ -3752,6 +3758,74 @@ var StaticTVClient = class {
3752
3758
  Material.setBasicMaterial(screen, {
3753
3759
  texture: Material.Texture.Video({ videoPlayerEntity: screen })
3754
3760
  });
3761
+ if (!this._videoEventsRegistered) {
3762
+ this._registerVideoEvents();
3763
+ }
3764
+ if (isLiveStream && !isFallback) {
3765
+ this._startStreamVerification();
3766
+ }
3767
+ }
3768
+ /**
3769
+ * Register video event handlers for stream verification
3770
+ * @internal
3771
+ */
3772
+ _registerVideoEvents() {
3773
+ const screen = this.config.videoScreen;
3774
+ if (screen === void 0) return;
3775
+ this._videoEventsRegistered = true;
3776
+ videoEventsSystem.registerVideoEventsEntity(screen, (videoEvent) => {
3777
+ if (videoEvent.state === VideoState.VS_READY || videoEvent.state === VideoState.VS_PLAYING) {
3778
+ if (this._pendingVideoData && !this._streamVerified) {
3779
+ this._streamVerified = true;
3780
+ this._clearVerificationTimeout();
3781
+ this.log(`Stream verified: ${this._pendingVideoData.name}`);
3782
+ }
3783
+ }
3784
+ if (videoEvent.state === VideoState.VS_ERROR) {
3785
+ if (this._pendingVideoData) {
3786
+ this.log(`Stream error for: ${this._pendingVideoData.name}`);
3787
+ this._handleStreamOffline();
3788
+ }
3789
+ }
3790
+ });
3791
+ }
3792
+ /**
3793
+ * Start stream verification timeout
3794
+ * @internal
3795
+ */
3796
+ _startStreamVerification() {
3797
+ if (this._pendingVideoData) {
3798
+ this.showNotification(`Connecting to ${this._pendingVideoData.name}...`, 1e4);
3799
+ }
3800
+ this._verificationTimeoutId = setTimeout(() => {
3801
+ if (!this._streamVerified && this._pendingVideoData) {
3802
+ this.log(`Stream verification timeout for: ${this._pendingVideoData.name}`);
3803
+ this._handleStreamOffline();
3804
+ }
3805
+ }, 8e3);
3806
+ }
3807
+ /**
3808
+ * Handle stream that's offline or failed to verify
3809
+ * @internal
3810
+ */
3811
+ _handleStreamOffline() {
3812
+ const videoData = this._pendingVideoData;
3813
+ this._pendingVideoData = null;
3814
+ this._clearVerificationTimeout();
3815
+ if (videoData) {
3816
+ this.showNotification(`${videoData.name} is offline`, 4e3);
3817
+ }
3818
+ this.stopVideo();
3819
+ }
3820
+ /**
3821
+ * Clear verification timeout
3822
+ * @internal
3823
+ */
3824
+ _clearVerificationTimeout() {
3825
+ if (this._verificationTimeoutId) {
3826
+ clearTimeout(this._verificationTimeoutId);
3827
+ this._verificationTimeoutId = null;
3828
+ }
3755
3829
  }
3756
3830
  /**
3757
3831
  * Get the currently playing video URL
@@ -3761,16 +3835,31 @@ var StaticTVClient = class {
3761
3835
  }
3762
3836
  /**
3763
3837
  * Internal handler for Guide video selection
3838
+ * Tries to play the stream and verifies it's working (like M1D-HQ behavior)
3764
3839
  * @internal
3765
3840
  */
3766
3841
  _handleGuideVideoSelect(video) {
3767
- if (video.channelId && video.isLive === false) {
3768
- this.showNotification(`${video.name} is offline`);
3769
- this.stopVideo();
3770
- return;
3842
+ if (!video.src) return;
3843
+ this._pendingVideoData = video;
3844
+ const isLiveStream = video.channelId !== void 0 || video.src.includes(".m3u8") || video.src.includes("media.thestatic.tv");
3845
+ this._playVideoWithVerification(video, isLiveStream);
3846
+ }
3847
+ /**
3848
+ * Play video with stream verification for live content
3849
+ * @internal
3850
+ */
3851
+ _playVideoWithVerification(video, isLiveStream) {
3852
+ const screen = this.config.videoScreen;
3853
+ if (screen !== void 0) {
3854
+ this.log(`Playing video: ${video.src} (live: ${isLiveStream})`);
3855
+ this._currentVideoUrl = video.src;
3856
+ this._playVideoInternal(video.src, false, isLiveStream);
3857
+ if (this.guideUI) {
3858
+ this.guideUI.currentVideoId = video.id;
3859
+ }
3771
3860
  }
3772
- if (video.src) {
3773
- this.playVideo(video.src);
3861
+ if (this.config.onVideoPlay) {
3862
+ this.config.onVideoPlay(video.src);
3774
3863
  }
3775
3864
  }
3776
3865
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thestatic-tv/dcl-sdk",
3
- "version": "2.5.1",
3
+ "version": "2.5.2",
4
4
  "description": "Connect your Decentraland scene to thestatic.tv - full channel lineup, metrics tracking, and interactions",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",