Chris4K commited on
Commit
1e952bf
·
verified ·
1 Parent(s): c851a9c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +57 -40
app.py CHANGED
@@ -68,36 +68,71 @@ async def detect_wakeword(audio_chunk: bytes) -> bool:
68
  # You might want to use libraries like Porcupine or build your own wake word detector
69
  return True
70
 
71
- async def process_audio_stream(websocket: WebSocket) -> AsyncGenerator[str, None]:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  buffer = []
73
  is_speaking = False
74
  silence_frames = 0
75
 
76
  while True:
77
  try:
78
- # Add a timeout to prevent indefinite waiting
79
  try:
80
- audio_data = await asyncio.wait_for(websocket.receive_bytes(), timeout=5.0)
81
  except asyncio.TimeoutError:
82
- print("WebSocket receive timeout")
 
 
 
83
  continue
84
- except Exception as receive_error:
85
- print(f"Error receiving audio data: {receive_error}")
86
- # Break the loop if there's a persistent receive error
87
- break
88
 
89
  # Validate audio data
90
- if not audio_data or len(audio_data) == 0:
91
- print("Received empty audio data")
92
- continue
93
-
94
- # Ensure audio data meets minimum size for VAD processing
95
- if len(audio_data) < CHUNK_SIZE:
96
- print(f"Audio chunk too small: {len(audio_data)} bytes")
97
  continue
98
 
99
  try:
100
- # Convert audio data to the right format for VAD
101
  is_speech = vad.is_speech(audio_data, SAMPLE_RATE)
102
  except Exception as vad_error:
103
  print(f"VAD processing error: {vad_error}")
@@ -133,7 +168,7 @@ async def process_audio_stream(websocket: WebSocket) -> AsyncGenerator[str, None
133
  user_speech_text = stt(wav_buffer, desired_language)
134
  if "computer" in user_speech_text.lower():
135
  translated_text = to_en_translation(user_speech_text, desired_language)
136
- response = await agent.arun(translated_text) # Assuming agent.run is made async
137
  bot_response_de = from_en_translation(response, desired_language)
138
 
139
  # Stream the response
@@ -153,38 +188,20 @@ async def process_audio_stream(websocket: WebSocket) -> AsyncGenerator[str, None
153
  except Exception as processing_error:
154
  print(f"Error processing speech utterance: {processing_error}")
155
 
 
 
 
156
  except Exception as e:
157
  print(f"Unexpected error in audio stream processing: {e}")
158
- # Add a small delay to prevent rapid reconnection attempts
159
  await asyncio.sleep(1)
160
- break
161
 
162
  @app.get("/", response_class=HTMLResponse)
163
  async def get_index():
164
  with open("static/index.html") as f:
165
  return f.read()
166
 
167
- @app.websocket("/ws")
168
- async def websocket_endpoint(websocket: WebSocket):
169
- await websocket.accept()
170
- try:
171
- # Keep the WebSocket connection open with a persistent loop
172
- while True:
173
- try:
174
- async for response in process_audio_stream(websocket):
175
- await websocket.send_text(response)
176
- except Exception as stream_error:
177
- print(f"Audio stream error: {stream_error}")
178
- # Attempt to restart the stream
179
- await asyncio.sleep(1)
180
- except Exception as e:
181
- print(f"WebSocket endpoint error: {e}")
182
- finally:
183
- try:
184
- await websocket.close(code=1000)
185
- except Exception as close_error:
186
- print(f"Error closing WebSocket: {close_error}")
187
-
188
  if __name__ == "__main__":
189
  import uvicorn
190
  uvicorn.run(app, host="0.0.0.0", port=8000)
 
68
  # You might want to use libraries like Porcupine or build your own wake word detector
69
  return True
70
 
71
+ @app.websocket("/ws")
72
+ async def websocket_endpoint(websocket: WebSocket):
73
+ await websocket.accept()
74
+ try:
75
+ # Use a queue to manage audio chunks
76
+ audio_queue = asyncio.Queue()
77
+
78
+ # Create a task to process the audio stream
79
+ stream_task = asyncio.create_task(process_audio_stream(audio_queue))
80
+
81
+ # Main receive loop
82
+ while True:
83
+ try:
84
+ # Try to receive audio data with a timeout
85
+ audio_data = await asyncio.wait_for(websocket.receive_bytes(), timeout=5.0)
86
+
87
+ # Put audio data into queue
88
+ await audio_queue.put(audio_data)
89
+
90
+ except asyncio.TimeoutError:
91
+ # Timeout is normal, just continue
92
+ continue
93
+
94
+ except WebSocketDisconnect:
95
+ # Handle clean disconnection
96
+ print("WebSocket disconnected")
97
+ break
98
+
99
+ except Exception as e:
100
+ print(f"WebSocket receive error: {e}")
101
+ break
102
+
103
+ except Exception as e:
104
+ print(f"WebSocket endpoint error: {e}")
105
+
106
+ finally:
107
+ # Cancel the stream processing task
108
+ stream_task.cancel()
109
+ try:
110
+ await websocket.close(code=1000)
111
+ except Exception as close_error:
112
+ print(f"Error closing WebSocket: {close_error}")
113
+
114
+ async def process_audio_stream(audio_queue: asyncio.Queue) -> AsyncGenerator[str, None]:
115
  buffer = []
116
  is_speaking = False
117
  silence_frames = 0
118
 
119
  while True:
120
  try:
121
+ # Get audio data from queue with timeout
122
  try:
123
+ audio_data = await asyncio.wait_for(audio_queue.get(), timeout=5.0)
124
  except asyncio.TimeoutError:
125
+ # No audio for a while, reset state
126
+ buffer = []
127
+ is_speaking = False
128
+ silence_frames = 0
129
  continue
 
 
 
 
130
 
131
  # Validate audio data
132
+ if not audio_data or len(audio_data) < CHUNK_SIZE:
 
 
 
 
 
 
133
  continue
134
 
135
  try:
 
136
  is_speech = vad.is_speech(audio_data, SAMPLE_RATE)
137
  except Exception as vad_error:
138
  print(f"VAD processing error: {vad_error}")
 
168
  user_speech_text = stt(wav_buffer, desired_language)
169
  if "computer" in user_speech_text.lower():
170
  translated_text = to_en_translation(user_speech_text, desired_language)
171
+ response = await agent.arun(translated_text)
172
  bot_response_de = from_en_translation(response, desired_language)
173
 
174
  # Stream the response
 
188
  except Exception as processing_error:
189
  print(f"Error processing speech utterance: {processing_error}")
190
 
191
+ except asyncio.CancelledError:
192
+ # Handle task cancellation
193
+ break
194
  except Exception as e:
195
  print(f"Unexpected error in audio stream processing: {e}")
196
+ # Prevent tight error loop
197
  await asyncio.sleep(1)
 
198
 
199
  @app.get("/", response_class=HTMLResponse)
200
  async def get_index():
201
  with open("static/index.html") as f:
202
  return f.read()
203
 
204
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  if __name__ == "__main__":
206
  import uvicorn
207
  uvicorn.run(app, host="0.0.0.0", port=8000)