1414
1515
1616class ConnectionManager :
17- connections : dict [ str , MeetingConnection ]
17+ connections : list [ MeetingConnection ]
1818 flush_audio_task : Task | None
1919
2020 def __init__ (self ):
21- self .connections : dict [ str , MeetingConnection ] = {}
21+ self .connections : list [ MeetingConnection ] = []
2222 self .flush_audio_task = None
2323
2424 async def connect (self , websocket : WebSocket , meeting_id : str , auth_token : str | None ):
@@ -29,37 +29,48 @@ async def connect(self, websocket: WebSocket, meeting_id: str, auth_token: str |
2929 await websocket .close (401 , 'Bad JWT token' )
3030 return
3131 await websocket .accept ()
32- self .connections [meeting_id ] = MeetingConnection (websocket )
32+ connection = MeetingConnection (websocket , meeting_id )
33+ self .connections .append (connection )
3334 if self .flush_audio_task is None :
3435 loop = asyncio .get_running_loop ()
3536 self .flush_audio_task = loop .create_task (self .flush_working_audio_worker ())
3637 inc_ws_conn_count ()
3738 log .info (f'Meeting with id { meeting_id } started. Ongoing meetings { len (self .connections )} ' )
3839
39- async def process (self , meeting_id : str , chunk : bytes , chunk_timestamp : int ):
40- log .debug (f'Processing chunk for meeting { meeting_id } ' )
41- if meeting_id not in self .connections :
42- log .warning (f'No such meeting id { meeting_id } , the connection was probably closed.' )
43- return
44- results = await self .connections [meeting_id ].process (chunk , chunk_timestamp )
45- await self .send (meeting_id , results )
40+ return connection
4641
47- async def send (self , meeting_id : str , results : list [utils .TranscriptionResponse ] | None ):
42+ async def process (self , connection : MeetingConnection , chunk : bytes , chunk_timestamp : int ):
43+ log .debug (f'Processing chunk for meeting { connection .meeting_id } ' )
44+
45+ try :
46+ results = await connection .process (chunk , chunk_timestamp )
47+ await self .send (connection , results )
48+ except Exception as e :
49+ log .error (f'Error processing chunk for meeting { connection .meeting_id } : { e } ' )
50+ await self .disconnect (connection )
51+
52+ async def send (self , connection : MeetingConnection , results : list [utils .TranscriptionResponse ] | None ):
4853 if results is not None :
4954 for result in results :
5055 try :
51- await self . connections [ meeting_id ] .ws .send_json (result .model_dump ())
56+ await connection .ws .send_json (result .model_dump ())
5257 except WebSocketDisconnect as e :
53- log .warning (f'Meeting { meeting_id } : the connection was closed before sending all results: { e } ' )
54- self .disconnect (meeting_id )
58+ log .warning (f'Meeting { connection .meeting_id } : the connection was closed before sending all results: { e } ' )
59+ await self .disconnect (connection , True )
60+ break
5561 except Exception as ex :
56- log .error (f'Meeting { meeting_id } : exception while sending transcription results { ex } ' )
62+ log .error (f'Meeting { connection . meeting_id } : exception while sending transcription results { ex } ' )
5763
58- def disconnect (self , meeting_id : str ):
64+ async def disconnect (self , connection : MeetingConnection , already_closed = False ):
5965 try :
60- del self .connections [meeting_id ]
61- except KeyError :
62- log .warning (f'The meeting { meeting_id } doesn\' t exist anymore.' )
66+ self .connections .remove (connection )
67+ except ValueError :
68+ log .warning (f'The connection for meeting { connection .meeting_id } doesn\' t exist in the list anymore.' )
69+ if not already_closed :
70+ await connection .close ()
71+ else :
72+ # mark connection as disconnected
73+ connection .disconnect ()
6374 dec_ws_conn_count ()
6475
6576 async def flush_working_audio_worker (self ):
@@ -69,15 +80,15 @@ async def flush_working_audio_worker(self):
6980 to the next utterance when the participant resumes speaking.
7081 """
7182 while True :
72- for meeting_id in self .connections :
73- for participant in self . connections [ meeting_id ] .participants :
74- state = self . connections [ meeting_id ] .participants [participant ]
83+ for connection in self .connections :
84+ for participant in connection .participants :
85+ state = connection .participants [participant ]
7586 diff = utils .now () - state .last_received_chunk
7687 log .debug (
77- f'Participant { participant } in meeting { meeting_id } has been silent for { diff } ms and has { len (state .working_audio )} bytes of audio'
88+ f'Participant { participant } in meeting { connection . meeting_id } has been silent for { diff } ms and has { len (state .working_audio )} bytes of audio'
7889 )
7990 if diff > whisper_flush_interval and len (state .working_audio ) > 0 and not state .is_transcribing :
80- log .info (f'Forcing a transcription in meeting { meeting_id } for { participant } ' )
81- results = await self . connections [ meeting_id ] .force_transcription (participant )
82- await self .send (meeting_id , results )
91+ log .info (f'Forcing a transcription in meeting { connection . meeting_id } for { participant } ' )
92+ results = await connection .force_transcription (participant )
93+ await self .send (connection , results )
8394 await asyncio .sleep (1 )
0 commit comments