datbkpro commited on
Commit
3bcab2c
·
verified ·
1 Parent(s): 19ac002

Update services/streaming_voice_service.py

Browse files
Files changed (1) hide show
  1. services/streaming_voice_service.py +80 -72
services/streaming_voice_service.py CHANGED
@@ -190,7 +190,7 @@ class StreamingVoiceService:
190
  print("🔄 Đang khởi tạo VOSK ASR...")
191
  self.vosk_asr = VoskStreamingASR()
192
 
193
- # Khởi tạo VAD - SỬ DỤNG SILERO VAD CỦA MÀY
194
  self.vad_processor = SileroVAD()
195
  self.is_listening = False
196
  self.speech_callback = None
@@ -204,11 +204,27 @@ class StreamingVoiceService:
204
  self.response_queue = queue.Queue()
205
  self.processing_active = False
206
 
 
 
 
207
  # Latency tracking
208
  self.latency_metrics = {
209
  'asr': [], 'llm': [], 'tts': [], 'total': []
210
  }
211
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  def start_listening(self, speech_callback: Callable) -> bool:
213
  """Bắt đầu lắng nghe với Silero VAD"""
214
  if self.is_listening:
@@ -241,6 +257,7 @@ class StreamingVoiceService:
241
  name="AI-Response-Worker"
242
  )
243
  worker_thread.start()
 
244
 
245
  print("🎙️ Đã bắt đầu lắng nghe với Silero VAD")
246
 
@@ -257,8 +274,69 @@ class StreamingVoiceService:
257
 
258
  return False
259
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  def _on_speech_detected(self, speech_audio: np.ndarray, sample_rate: int):
261
- """Callback khi Silero VAD phát hiện speech - FIXED VERSION"""
262
  if not self.is_listening:
263
  return
264
 
@@ -312,56 +390,6 @@ class StreamingVoiceService:
312
  except Exception as e:
313
  print(f"❌ Lỗi trong VAD speech detection: {e}")
314
 
315
- def _process_response_worker(self):
316
- """Worker xử lý phản hồi AI từ queue"""
317
- while self.processing_active:
318
- try:
319
- # Lấy item từ queue với timeout
320
- item = self.response_queue.get(timeout=1.0)
321
- if item is None: # Tín hiệu dừng
322
- break
323
-
324
- transcription = item['transcription']
325
- start_time = item['timestamp']
326
-
327
- print(f"🤖 Processing AI response for: '{transcription}'")
328
-
329
- # Tạo phản hồi AI với latency tracking
330
- llm_start_time = time.time()
331
- response = self._generate_ai_response(transcription)
332
- llm_time = time.time() - llm_start_time
333
- self.latency_metrics['llm'].append(llm_time)
334
-
335
- tts_start_time = time.time()
336
- tts_audio_path = self._text_to_speech(response)
337
- tts_time = time.time() - tts_start_time
338
- if tts_time > 0:
339
- self.latency_metrics['tts'].append(tts_time)
340
-
341
- # Gửi kết quả về callback
342
- if self.speech_callback:
343
- self.speech_callback({
344
- 'transcription': transcription,
345
- 'response': response,
346
- 'tts_audio': tts_audio_path,
347
- 'status': 'completed'
348
- })
349
-
350
- # Đánh dấu task hoàn thành
351
- self.response_queue.task_done()
352
-
353
- except queue.Empty:
354
- continue
355
- except Exception as e:
356
- print(f"❌ Lỗi trong response worker: {e}")
357
- if self.speech_callback:
358
- self.speech_callback({
359
- 'transcription': "Lỗi xử lý",
360
- 'response': f"Xin lỗi, có lỗi xảy ra: {str(e)}",
361
- 'tts_audio': None,
362
- 'status': 'error'
363
- })
364
-
365
  def process_streaming_audio(self, audio_data: tuple) -> Dict[str, Any]:
366
  """Xử lý audio streaming manual mode"""
367
  if not audio_data:
@@ -500,15 +528,6 @@ class StreamingVoiceService:
500
  'status': 'error'
501
  }
502
 
503
- def stop_listening(self):
504
- """Dừng lắng nghe"""
505
- self.is_listening = False
506
- self.processing_active = False
507
- self.vad_processor.stop_stream()
508
- if self.vosk_asr:
509
- self.vosk_asr.stop_stream()
510
- print("🛑 Đã dừng lắng nghe")
511
-
512
  def clear_conversation(self):
513
  """Xóa lịch sử hội thoại"""
514
  self.conversation_history = []
@@ -516,17 +535,6 @@ class StreamingVoiceService:
516
  self.partial_transcription = ""
517
  print("🗑️ Đã xóa lịch sử hội thoại")
518
 
519
- def get_conversation_state(self) -> dict:
520
- return {
521
- 'is_listening': self.is_listening,
522
- 'history_length': len(self.conversation_history),
523
- 'current_transcription': self.current_transcription,
524
- 'partial_transcription': self.partial_transcription,
525
- 'queue_size': self.response_queue.qsize(),
526
- 'vosk_active': self.vosk_asr.is_streaming if self.vosk_asr else False,
527
- 'last_update': time.strftime("%H:%M:%S")
528
- }
529
-
530
  def get_latency_stats(self) -> dict:
531
  """Lấy thống kê latency"""
532
  stats = {}
 
190
  print("🔄 Đang khởi tạo VOSK ASR...")
191
  self.vosk_asr = VoskStreamingASR()
192
 
193
+ # Khởi tạo VAD
194
  self.vad_processor = SileroVAD()
195
  self.is_listening = False
196
  self.speech_callback = None
 
204
  self.response_queue = queue.Queue()
205
  self.processing_active = False
206
 
207
+ # Worker threads tracking
208
+ self.worker_threads = 0
209
+
210
  # Latency tracking
211
  self.latency_metrics = {
212
  'asr': [], 'llm': [], 'tts': [], 'total': []
213
  }
214
 
215
+ def get_conversation_state(self) -> dict:
216
+ """Lấy trạng thái hội thoại - FIXED VERSION"""
217
+ return {
218
+ 'is_listening': self.is_listening,
219
+ 'history_length': len(self.conversation_history),
220
+ 'current_transcription': self.current_transcription,
221
+ 'partial_transcription': self.partial_transcription,
222
+ 'queue_size': self.response_queue.qsize(),
223
+ 'worker_threads': self.worker_threads, # THÊM KEY NÀY
224
+ 'vosk_active': self.vosk_asr.is_streaming if self.vosk_asr else False,
225
+ 'last_update': time.strftime("%H:%M:%S")
226
+ }
227
+
228
  def start_listening(self, speech_callback: Callable) -> bool:
229
  """Bắt đầu lắng nghe với Silero VAD"""
230
  if self.is_listening:
 
257
  name="AI-Response-Worker"
258
  )
259
  worker_thread.start()
260
+ self.worker_threads = 1 # CẬP NHẬT SỐ LƯỢNG THREAD
261
 
262
  print("🎙️ Đã bắt đầu lắng nghe với Silero VAD")
263
 
 
274
 
275
  return False
276
 
277
+ def stop_listening(self):
278
+ """Dừng lắng nghe"""
279
+ self.is_listening = False
280
+ self.processing_active = False
281
+ self.worker_threads = 0 # RESET SỐ THREAD
282
+ self.vad_processor.stop_stream()
283
+ if self.vosk_asr:
284
+ self.vosk_asr.stop_stream()
285
+ print("🛑 Đã dừng lắng nghe")
286
+
287
+ def _process_response_worker(self):
288
+ """Worker xử lý phản hồi AI từ queue"""
289
+ while self.processing_active:
290
+ try:
291
+ # Lấy item từ queue với timeout
292
+ item = self.response_queue.get(timeout=1.0)
293
+ if item is None: # Tín hiệu dừng
294
+ break
295
+
296
+ transcription = item['transcription']
297
+ start_time = item['timestamp']
298
+
299
+ print(f"🤖 Processing AI response for: '{transcription}'")
300
+
301
+ # Tạo phản hồi AI với latency tracking
302
+ llm_start_time = time.time()
303
+ response = self._generate_ai_response(transcription)
304
+ llm_time = time.time() - llm_start_time
305
+ self.latency_metrics['llm'].append(llm_time)
306
+
307
+ tts_start_time = time.time()
308
+ tts_audio_path = self._text_to_speech(response)
309
+ tts_time = time.time() - tts_start_time
310
+ if tts_time > 0:
311
+ self.latency_metrics['tts'].append(tts_time)
312
+
313
+ # Gửi kết quả về callback
314
+ if self.speech_callback:
315
+ self.speech_callback({
316
+ 'transcription': transcription,
317
+ 'response': response,
318
+ 'tts_audio': tts_audio_path,
319
+ 'status': 'completed'
320
+ })
321
+
322
+ # Đánh dấu task hoàn thành
323
+ self.response_queue.task_done()
324
+
325
+ except queue.Empty:
326
+ continue
327
+ except Exception as e:
328
+ print(f"❌ Lỗi trong response worker: {e}")
329
+ if self.speech_callback:
330
+ self.speech_callback({
331
+ 'transcription': "Lỗi xử lý",
332
+ 'response': f"Xin lỗi, có lỗi xảy ra: {str(e)}",
333
+ 'tts_audio': None,
334
+ 'status': 'error'
335
+ })
336
+
337
+ # CÁC METHOD KHÁC GIỮ NGUYÊN...
338
  def _on_speech_detected(self, speech_audio: np.ndarray, sample_rate: int):
339
+ """Callback khi Silero VAD phát hiện speech"""
340
  if not self.is_listening:
341
  return
342
 
 
390
  except Exception as e:
391
  print(f"❌ Lỗi trong VAD speech detection: {e}")
392
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
393
  def process_streaming_audio(self, audio_data: tuple) -> Dict[str, Any]:
394
  """Xử lý audio streaming manual mode"""
395
  if not audio_data:
 
528
  'status': 'error'
529
  }
530
 
 
 
 
 
 
 
 
 
 
531
  def clear_conversation(self):
532
  """Xóa lịch sử hội thoại"""
533
  self.conversation_history = []
 
535
  self.partial_transcription = ""
536
  print("🗑️ Đã xóa lịch sử hội thoại")
537
 
 
 
 
 
 
 
 
 
 
 
 
538
  def get_latency_stats(self) -> dict:
539
  """Lấy thống kê latency"""
540
  stats = {}