@@ -60,29 +60,75 @@ export class MultiRoomLiveKitClient {
6060 }
6161
6262 /**
63- * Connect to individual talkgroup room
63+ * Connect to individual talkgroup room with retry logic
6464 */
6565 private async connectToRoom ( roomInfo : TalkgroupRoom , token : string , serverUrl : string ) : Promise < void > {
66- const room = new Room ( {
67- adaptiveStream : true ,
68- dynacast : true ,
69- audioCaptureDefaults : {
70- echoCancellation : true ,
71- noiseSuppression : true ,
72- autoGainControl : true ,
73- } ,
74- } ) ;
75-
76- // Set up room event handlers
77- this . setupRoomEventHandlers ( room , roomInfo ) ;
78-
79- // Connect to room
80- await room . connect ( serverUrl , token ) ;
81-
82- // Store room reference
83- this . rooms . set ( roomInfo . roomName , room ) ;
66+ const maxRetries = 3 ;
67+ let retryCount = 0 ;
8468
85- console . log ( `📞 Connected to room: ${ roomInfo . talkgroupName } (${ roomInfo . type } )` ) ;
69+ while ( retryCount < maxRetries ) {
70+ try {
71+ console . log ( `🔗 Attempting to connect to ${ roomInfo . talkgroupName } (attempt ${ retryCount + 1 } /${ maxRetries } )` ) ;
72+
73+ const room = new Room ( {
74+ adaptiveStream : true ,
75+ dynacast : true ,
76+ audioCaptureDefaults : {
77+ echoCancellation : true ,
78+ noiseSuppression : true ,
79+ autoGainControl : true ,
80+ } ,
81+ // Add connection timeout and retry options
82+ reconnectPolicy : {
83+ nextRetryDelayInMs : ( context ) => {
84+ const delay = Math . min ( 1000 * Math . pow ( 2 , context . retryCount ) , 10000 ) ;
85+ console . log ( `⏱️ Next retry for ${ roomInfo . talkgroupName } in ${ delay } ms` ) ;
86+ return delay ;
87+ } ,
88+ maxReconnectAttempts : 5 ,
89+ } ,
90+ } ) ;
91+
92+ // Set up room event handlers first
93+ this . setupRoomEventHandlers ( room , roomInfo ) ;
94+
95+ // Add pre-connection error handling
96+ const connectPromise = room . connect ( serverUrl , token ) ;
97+
98+ // Set a reasonable timeout for connection
99+ const timeoutPromise = new Promise < void > ( ( _ , reject ) => {
100+ setTimeout ( ( ) => {
101+ reject ( new Error ( `Connection timeout after 15 seconds for ${ roomInfo . talkgroupName } ` ) ) ;
102+ } , 15000 ) ;
103+ } ) ;
104+
105+ await Promise . race ( [ connectPromise , timeoutPromise ] ) ;
106+
107+ // Verify connection state
108+ if ( room . state !== 'connected' ) {
109+ throw new Error ( `Room connection failed - state: ${ room . state } ` ) ;
110+ }
111+
112+ // Store room reference
113+ this . rooms . set ( roomInfo . roomName , room ) ;
114+
115+ console . log ( `✅ Successfully connected to room: ${ roomInfo . talkgroupName } (${ roomInfo . type } )` ) ;
116+ return ; // Success, exit retry loop
117+
118+ } catch ( error ) {
119+ console . error ( `❌ Connection attempt ${ retryCount + 1 } failed for ${ roomInfo . talkgroupName } :` , error ) ;
120+ retryCount ++ ;
121+
122+ if ( retryCount < maxRetries ) {
123+ const delay = Math . min ( 1000 * Math . pow ( 2 , retryCount ) , 5000 ) ;
124+ console . log ( `⏳ Retrying connection to ${ roomInfo . talkgroupName } in ${ delay } ms...` ) ;
125+ await new Promise ( resolve => setTimeout ( resolve , delay ) ) ;
126+ } else {
127+ console . error ( `💥 Failed to connect to ${ roomInfo . talkgroupName } after ${ maxRetries } attempts` ) ;
128+ throw error ;
129+ }
130+ }
131+ }
86132 }
87133
88134 /**
@@ -183,25 +229,57 @@ export class MultiRoomLiveKitClient {
183229 */
184230 private handleIncomingAudioTrack ( track : AudioTrack , roomInfo : TalkgroupRoom , participant : RemoteParticipant ) : void {
185231 console . log ( `🔊 Audio track subscribed from ${ roomInfo . talkgroupName } :` , participant . identity ) ;
232+ console . log ( '🎵 Track details:' , {
233+ kind : track . kind ,
234+ enabled : track . enabled ,
235+ muted : track . muted ,
236+ mediaStreamTrack : track . mediaStreamTrack ?. id ,
237+ readyState : track . mediaStreamTrack ?. readyState
238+ } ) ;
186239
187240 // Get the audio element
188241 const audioElement = track . attach ( ) as HTMLAudioElement ;
189242 audioElement . autoplay = true ;
190- // playsInline is for video elements, not needed for audio
243+ audioElement . volume = 1.0 ; // Ensure full volume
244+ audioElement . muted = false ; // Ensure not muted
245+
246+ console . log ( '🎧 Audio element created:' , {
247+ volume : audioElement . volume ,
248+ muted : audioElement . muted ,
249+ autoplay : audioElement . autoplay ,
250+ srcObject : ! ! audioElement . srcObject
251+ } ) ;
252+
253+ // Add event listeners for debugging
254+ audioElement . addEventListener ( 'loadstart' , ( ) => console . log ( `🎵 Audio loading started for ${ participant . identity } ` ) ) ;
255+ audioElement . addEventListener ( 'canplay' , ( ) => console . log ( `🎵 Audio can play for ${ participant . identity } ` ) ) ;
256+ audioElement . addEventListener ( 'playing' , ( ) => console . log ( `🎵 Audio playing for ${ participant . identity } ` ) ) ;
257+ audioElement . addEventListener ( 'error' , ( e ) => console . error ( `❌ Audio error for ${ participant . identity } :` , e ) ) ;
258+ audioElement . addEventListener ( 'stalled' , ( ) => console . warn ( `⚠️ Audio stalled for ${ participant . identity } ` ) ) ;
191259
192260 // Connect to ducking engine
193261 if ( this . duckingEngine ) {
262+ console . log ( `🔀 Connecting audio to ducking engine for ${ roomInfo . talkgroupName } ` ) ;
194263 this . duckingEngine . connectRoomAudio ( roomInfo . roomName , audioElement ) ;
195264 }
196265
197266 // Add to DOM (hidden)
198267 audioElement . style . display = 'none' ;
268+ audioElement . setAttribute ( 'data-room' , roomInfo . roomName ) ;
269+ audioElement . setAttribute ( 'data-participant' , participant . identity ) ;
199270 document . body . appendChild ( audioElement ) ;
200271
272+ console . log ( `🎯 Audio element added to DOM for ${ roomInfo . talkgroupName } /${ participant . identity } ` ) ;
273+
201274 // Clean up when track ends
202275 track . on ( 'ended' , ( ) => {
276+ console . log ( `🔚 Audio track ended for ${ participant . identity } ` ) ;
203277 audioElement . remove ( ) ;
204278 } ) ;
279+
280+ // Log audio elements count
281+ const totalAudioElements = document . querySelectorAll ( 'audio' ) . length ;
282+ console . log ( `📊 Total audio elements in DOM: ${ totalAudioElements } ` ) ;
205283 }
206284
207285 /**
0 commit comments