@@ -51,6 +51,7 @@ def __init__(self, config: DeepgramClientOptions):
5151 self ._socket = None
5252 self ._event_handlers = {event : [] for event in LiveTranscriptionEvents }
5353 self .websocket_url = convert_to_websocket_url (self .config .url , self .endpoint )
54+ self .exit_event = None
5455
5556 # starts the WebSocket connection for live transcription
5657 async def start (
@@ -61,10 +62,10 @@ async def start(
6162 ** kwargs ,
6263 ) -> bool :
6364 self .logger .debug ("AsyncLiveClient.start ENTER" )
64- self .logger .info ("kwargs : %s" , options )
65+ self .logger .info ("options : %s" , options )
6566 self .logger .info ("addons: %s" , addons )
6667 self .logger .info ("members: %s" , members )
67- self .logger .info ("options : %s" , kwargs )
68+ self .logger .info ("kwargs : %s" , kwargs )
6869
6970 if isinstance (options , LiveOptions ) and not options .check ():
7071 self .logger .error ("options.check failed" )
@@ -83,7 +84,7 @@ async def start(
8384 if members is not None :
8485 self .__dict__ .update (members )
8586
86- # add " kwargs" as members of the class
87+ # set kwargs as members of the class
8788 if kwargs is not None :
8889 self .kwargs = kwargs
8990 else :
@@ -101,6 +102,8 @@ async def start(
101102 self .logger .debug ("combined_options: %s" , combined_options )
102103
103104 url_with_params = append_query_params (self .websocket_url , combined_options )
105+ self .exit_event = asyncio .Event ()
106+
104107 try :
105108 self ._socket = await _socket_connect (url_with_params , self .config .headers )
106109
@@ -135,8 +138,24 @@ async def _emit(self, event: LiveTranscriptionEvents, *args, **kwargs) -> None:
135138 async def _listening (self ) -> None :
136139 self .logger .debug ("AsyncLiveClient._listening ENTER" )
137140
138- try :
139- async for message in self ._socket :
141+ while True :
142+ try :
143+ if self .exit_event .is_set ():
144+ self .logger .notice ("_listening exiting gracefully" )
145+ self .logger .debug ("AsyncLiveClient._listening LEAVE" )
146+ return
147+
148+ if self ._socket is None :
149+ self .logger .warning ("socket is empty" )
150+ self .logger .debug ("AsyncLiveClient._listening LEAVE" )
151+ return
152+
153+ message = await self ._socket .recv ()
154+
155+ if message is None :
156+ self .logger .spam ("message is None" )
157+ continue
158+
140159 data = json .loads (message )
141160 response_type = data .get ("type" )
142161 self .logger .debug ("response_type: %s, data: %s" , response_type , data )
@@ -206,48 +225,48 @@ async def _listening(self) -> None:
206225 )
207226 await self ._emit (LiveTranscriptionEvents .Error , error = error )
208227
209- except websockets .exceptions .ConnectionClosedOK as e :
210- self .logger .notice (f"_listening({ e .code } ) exiting gracefully" )
211- self .logger .debug ("AsyncLiveClient._listening LEAVE" )
212- return
213-
214- except websockets .exceptions .WebSocketException as e :
215- error : ErrorResponse = {
216- "type" : "Exception" ,
217- "description" : "WebSocketException in _listening" ,
218- "message" : f"{ e } " ,
219- "variant" : "" ,
220- }
221- self .logger .notice (
222- f"WebSocket exception in _listening with code { e .code } : { e .reason } "
223- )
224- await self ._emit (LiveTranscriptionEvents .Error , error )
225-
226- self .logger .debug ("AsyncLiveClient._listening LEAVE" )
227-
228- if (
229- "termination_exception" in self .options
230- and self .options ["termination_exception" ] == "true"
231- ):
232- raise
233-
234- except Exception as e :
235- error : ErrorResponse = {
236- "type" : "Exception" ,
237- "description" : "Exception in _listening" ,
238- "message" : f"{ e } " ,
239- "variant" : "" ,
240- }
241- self .logger .error ("Exception in _listening: %s" , str (e ))
242- await self ._emit (LiveTranscriptionEvents .Error , error )
243-
244- self .logger .debug ("AsyncLiveClient._listening LEAVE" )
245-
246- if (
247- "termination_exception" in self .options
248- and self .options ["termination_exception" ] == "true"
249- ):
250- raise
228+ except websockets .exceptions .ConnectionClosedOK as e :
229+ self .logger .notice (f"_listening({ e .code } ) exiting gracefully" )
230+ self .logger .debug ("AsyncLiveClient._listening LEAVE" )
231+ return
232+
233+ except websockets .exceptions .WebSocketException as e :
234+ error : ErrorResponse = {
235+ "type" : "Exception" ,
236+ "description" : "WebSocketException in AsyncLiveClient. _listening" ,
237+ "message" : f"{ e } " ,
238+ "variant" : "" ,
239+ }
240+ self .logger .notice (
241+ f"WebSocket exception in AsyncLiveClient. _listening with code { e .code } : { e .reason } "
242+ )
243+ await self ._emit (LiveTranscriptionEvents .Error , error )
244+
245+ self .logger .debug ("AsyncLiveClient._listening LEAVE" )
246+
247+ if (
248+ "termination_exception" in self .options
249+ and self .options ["termination_exception" ] == "true"
250+ ):
251+ raise
252+
253+ except Exception as e :
254+ error : ErrorResponse = {
255+ "type" : "Exception" ,
256+ "description" : "Exception in AsyncLiveClient. _listening" ,
257+ "message" : f"{ e } " ,
258+ "variant" : "" ,
259+ }
260+ self .logger .error ("Exception in AsyncLiveClient. _listening: %s" , str (e ))
261+ await self ._emit (LiveTranscriptionEvents .Error , error )
262+
263+ self .logger .debug ("AsyncLiveClient._listening LEAVE" )
264+
265+ if (
266+ "termination_exception" in self .options
267+ and self .options ["termination_exception" ] == "true"
268+ ):
269+ raise
251270
252271 # keep the connection alive by sending keepalive messages
253272 async def _keep_alive (self ) -> None :
@@ -259,6 +278,11 @@ async def _keep_alive(self) -> None:
259278 counter += 1
260279 await asyncio .sleep (ONE_SECOND )
261280
281+ if self .exit_event .is_set ():
282+ self .logger .notice ("_keep_alive exiting gracefully" )
283+ self .logger .debug ("AsyncLiveClient._keep_alive LEAVE" )
284+ return
285+
262286 if self ._socket is None :
263287 self .logger .notice ("socket is None, exiting keep_alive" )
264288 self .logger .debug ("AsyncLiveClient._keep_alive LEAVE" )
@@ -270,25 +294,22 @@ async def _keep_alive(self) -> None:
270294 and self .config .options .get ("keepalive" ) == "true"
271295 ):
272296 self .logger .verbose ("Sending KeepAlive..." )
273- try :
274- await self .send (json .dumps ({"type" : "KeepAlive" }))
275- except websockets .exceptions .WebSocketException as e :
276- self .logger .error ("KeepAlive failed: %s" , e )
297+ await self .send (json .dumps ({"type" : "KeepAlive" }))
277298
278299 except websockets .exceptions .ConnectionClosedOK as e :
279300 self .logger .notice (f"_keep_alive({ e .code } ) exiting gracefully" )
280301 self .logger .debug ("AsyncLiveClient._keep_alive LEAVE" )
281302 return
282303
283- except websockets .exceptions .ConnectionClosedError as e :
304+ except websockets .exceptions .WebSocketException as e :
284305 error : ErrorResponse = {
285306 "type" : "Exception" ,
286- "description" : "ConnectionClosedError in _keep_alive" ,
307+ "description" : "WebSocketException in AsyncLiveClient. _keep_alive" ,
287308 "message" : f"{ e } " ,
288309 "variant" : "" ,
289310 }
290311 self .logger .error (
291- f"WebSocket connection closed in _keep_alive with code { e .code } : { e .reason } "
312+ f"WebSocket connection closed in AsyncLiveClient. _keep_alive with code { e .code } : { e .reason } "
292313 )
293314 await self ._emit (LiveTranscriptionEvents .Error , error )
294315
@@ -308,8 +329,10 @@ async def _keep_alive(self) -> None:
308329 "message" : f"{ e } " ,
309330 "variant" : "" ,
310331 }
332+ self .logger .error (
333+ "Exception in AsyncLiveClient._keep_alive: %s" , str (e )
334+ )
311335 await self ._emit (LiveTranscriptionEvents .Error , error )
312- self .logger .error ("Exception in _keep_alive: %s" , str (e ))
313336
314337 self .logger .debug ("AsyncLiveClient._keep_alive LEAVE" )
315338
@@ -323,31 +346,45 @@ async def _keep_alive(self) -> None:
323346 self .logger .debug ("AsyncLiveClient._keep_alive LEAVE" )
324347
325348 # sends data over the WebSocket connection
326- async def send (self , data : Union [str , bytes ]) -> int :
349+ async def send (self , data : Union [str , bytes ]) -> bool :
327350 """
328351 Sends data over the WebSocket connection.
329352 """
330353 self .logger .spam ("AsyncLiveClient.send ENTER" )
331- self .logger .spam ("data: %s" , data )
332354
333355 if self ._socket is not None :
334- cnt = await self ._socket .send (data )
335- self .logger .spam (f"send() succeeded. bytes: { cnt } " )
356+ try :
357+ await self ._socket .send (data )
358+ except websockets .exceptions .WebSocketException as e :
359+ self .logger .error ("send() failed - WebSocketException: %s" , str (e ))
360+ self .logger .spam ("AsyncLiveClient.send LEAVE" )
361+ return False
362+ except Exception as e :
363+ self .logger .error ("send() failed - Exception: %s" , str (e ))
364+ self .logger .spam ("AsyncLiveClient.send LEAVE" )
365+ return False
366+
367+ self .logger .spam (f"send() succeeded" )
336368 self .logger .spam ("AsyncLiveClient.send LEAVE" )
337- return cnt
369+ return True
338370
339371 self .logger .error ("send() failed. socket is None" )
340372 self .logger .spam ("AsyncLiveClient.send LEAVE" )
341- return 0
373+ return False
342374
343375 async def finish (self ) -> bool :
344376 """
345377 Closes the WebSocket connection gracefully.
346378 """
347379 self .logger .debug ("AsyncLiveClient.finish ENTER" )
348380
349- if self ._socket :
350- self .logger .notice ("send CloseStream..." )
381+ # signal exit
382+ self .exit_event .set ()
383+
384+ # close the stream
385+ self .logger .verbose ("closing socket..." )
386+ if self ._socket is not None :
387+ self .logger .verbose ("send CloseStream..." )
351388 await self ._socket .send (json .dumps ({"type" : "CloseStream" }))
352389
353390 await asyncio .sleep (0.5 )
@@ -358,14 +395,14 @@ async def finish(self) -> bool:
358395 CloseResponse (type = LiveTranscriptionEvents .Close .value ),
359396 )
360397
361- self .logger .notice ("socket.wait_closed..." )
398+ self .logger .verbose ("socket.wait_closed..." )
362399 try :
363400 await self ._socket .wait_closed ()
364401 except websockets .exceptions .WebSocketException as e :
365402 self .logger .error ("socket.wait_closed failed: %s" , e )
366- self .logger . notice ( "socket.wait_closed succeeded" )
403+ self ._socket = None
367404
368- self .logger .notice ("cancelling tasks..." )
405+ self .logger .verbose ("cancelling tasks..." )
369406 try :
370407 # Before cancelling, check if the tasks were created
371408 if self ._listen_thread is not None :
@@ -380,13 +417,7 @@ async def finish(self) -> bool:
380417 except asyncio .CancelledError as e :
381418 self .logger .error ("tasks cancelled error: %s" , e )
382419
383- if self ._socket is not None :
384- self .logger .notice ("closing socket..." )
385- await self ._socket .close ()
386-
387- self ._socket = None
388-
389- self .logger .notice ("finish succeeded" )
420+ self .logger .info ("finish succeeded" )
390421 self .logger .debug ("AsyncLiveClient.finish LEAVE" )
391422 return True
392423
0 commit comments