datbkpro commited on
Commit
1ef025d
·
verified ·
1 Parent(s): f8c624c

Update ui/tabs.py

Browse files
Files changed (1) hide show
  1. ui/tabs.py +193 -76
ui/tabs.py CHANGED
@@ -1018,7 +1018,7 @@ def create_streaming_voice_tab(streaming_service: StreamingVoiceService):
1018
  with gr.Blocks() as streaming_tab:
1019
  gr.Markdown("## 🎤 Trò chuyện giọng nói thời gian thực - Tối ưu hóa")
1020
 
1021
- # FIXED: Thêm state để lưu kết quả VAD
1022
  vad_result_state = gr.State(value=None)
1023
 
1024
  with gr.Row():
@@ -1027,6 +1027,7 @@ def create_streaming_voice_tab(streaming_service: StreamingVoiceService):
1027
  with gr.Row():
1028
  start_btn = gr.Button("🎙️ Bắt đầu VAD", variant="primary")
1029
  stop_btn = gr.Button("🛑 Dừng VAD", variant="secondary")
 
1030
 
1031
  gr.Markdown("### Chế độ tự động (VAD)")
1032
  gr.Markdown("Hệ thống tự động nhận diện khi bạn bắt đầu nói")
@@ -1038,6 +1039,14 @@ def create_streaming_voice_tab(streaming_service: StreamingVoiceService):
1038
  interactive=False
1039
  )
1040
 
 
 
 
 
 
 
 
 
1041
  gr.Markdown("### Chế độ thủ công")
1042
  microphone = gr.Microphone(
1043
  label="🎤 Nhấn để nói thủ công",
@@ -1052,27 +1061,21 @@ def create_streaming_voice_tab(streaming_service: StreamingVoiceService):
1052
  )
1053
  refresh_latency_btn = gr.Button("🔄 Refresh Metrics", size="sm")
1054
 
1055
- clear_btn = gr.Button("🗑️ Xóa hội thoại")
1056
-
1057
- # State info
1058
- state_info = gr.Textbox(
1059
- label="Thông tin hệ thống",
1060
- value="Khởi tạo...",
1061
- lines=3,
1062
- interactive=False
1063
- )
1064
-
1065
  with gr.Column(scale=2):
 
1066
  transcription_box = gr.Textbox(
1067
- label="📝 Bạn vừa nói",
1068
- lines=2,
1069
- interactive=False
 
1070
  )
1071
 
 
1072
  response_box = gr.Textbox(
1073
  label="🤖 Phản hồi AI",
1074
- lines=3,
1075
- interactive=False
 
1076
  )
1077
 
1078
  audio_output = gr.Audio(
@@ -1083,98 +1086,207 @@ def create_streaming_voice_tab(streaming_service: StreamingVoiceService):
1083
 
1084
  # State variables
1085
  is_vad_active = gr.State(value=False)
 
 
 
 
1086
 
1087
  def vad_callback(result):
1088
- """Callback khi VAD phát hiện speech - FIXED VERSION"""
1089
- print(f"🎯 Nhận kết quả từ VAD: {result['transcription']}")
1090
- vad_result_state.value = result
1091
 
1092
  def start_vad():
1093
- """Bắt đầu VAD - FIXED VERSION"""
1094
- success = streaming_service.start_listening(vad_callback)
1095
- if success:
1096
- is_vad_active.value = True
1097
- status = "✅ VAD đang chạy - Hãy nói gì đó!"
1098
- state = streaming_service.get_conversation_state()
1099
- state_text = f"VAD: Đang hoạt động\nQueue: {state['queue_size']}\nThreads: {state['worker_threads']}"
1100
- else:
1101
- status = "❌ Không thể khởi động VAD"
1102
- state_text = "Lỗi khởi động"
1103
-
1104
- return status, state_text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1105
 
1106
  def stop_vad():
1107
  """Dừng VAD"""
1108
- streaming_service.stop_listening()
1109
- is_vad_active.value = False
1110
- state = streaming_service.get_conversation_state()
1111
- state_text = f"VAD: Đã dừng\nHistory: {state['history_length']} messages"
1112
- return "🛑 VAD đã dừng", state_text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1113
 
1114
  def process_microphone(audio_data):
1115
- """Xử lý microphone input"""
1116
  if audio_data is None:
1117
- return "Chưa có âm thanh", "Hãy nói gì đó...", None, "VAD: Đang chạy" if is_vad_active.value else "VAD: Dừng"
1118
 
1119
  try:
 
 
 
1120
  result = streaming_service.process_streaming_audio(audio_data)
 
1121
  state = streaming_service.get_conversation_state()
1122
  state_text = f"Manual mode\nHistory: {state['history_length']} messages"
1123
- return result['transcription'], result['response'], result['tts_audio'], state_text
 
 
 
 
 
 
 
 
 
 
1124
  except Exception as e:
1125
- return f"Lỗi: {e}", "Xin lỗi, có lỗi xảy ra", None, "Lỗi xử lý"
 
1126
 
1127
  def check_vad_results():
1128
- """Kiểm tra kết quả VAD - FIXED: Cập nhật UI khi có kết quả mới"""
1129
- if vad_result_state.value is not None:
1130
- result = vad_result_state.value
1131
- vad_result_state.value = None # Reset sau khi dùng
1132
-
1133
- state = streaming_service.get_conversation_state()
1134
- state_text = f"VAD mode\nHistory: {state['history_length']} messages\nQueue: {state['queue_size']}"
1135
 
1136
- return result['transcription'], result['response'], result['tts_audio'], state_text
1137
- return gr.skip(), gr.skip(), gr.skip(), gr.skip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1138
 
1139
  def clear_chat():
1140
  """Xóa hội thoại"""
1141
  streaming_service.clear_conversation()
1142
  state = streaming_service.get_conversation_state()
1143
- state_text = f"Đã xóa hội thoại\nHistory: {state['history_length']} messages"
1144
- return "", "", None, state_text
 
1145
 
1146
  def refresh_latency():
1147
  """Làm mới latency metrics"""
1148
- stats = streaming_service.get_latency_stats()
1149
- return stats
 
 
 
 
1150
 
1151
- def update_state_info():
1152
  """Cập nhật thông tin trạng thái"""
1153
- state = streaming_service.get_conversation_state()
1154
-
1155
- formatted_state = f"VAD: {'Đang chạy' if state['is_listening'] else 'Dừng'}\n"
1156
- formatted_state += f"Queue: {state['queue_size']}\n"
1157
- formatted_state += f"History: {state['history_length']} messages\n"
1158
- formatted_state += f"Threads: {state['worker_threads']}\n"
1159
- formatted_state += f"Last: {state['last_update']}"
1160
-
1161
- latency_info = streaming_service.get_latency_stats()
1162
-
1163
- return formatted_state, latency_info
 
 
 
 
 
 
 
 
 
 
 
 
1164
 
1165
  # Event handlers
1166
- start_btn.click(start_vad, outputs=[vad_status, state_info])
1167
- stop_btn.click(stop_vad, outputs=[vad_status, state_info])
 
 
1168
 
 
 
 
 
 
 
1169
  microphone.stream(
1170
  process_microphone,
1171
  inputs=[microphone],
1172
- outputs=[transcription_box, response_box, audio_output, state_info]
1173
  )
1174
 
1175
  clear_btn.click(
1176
  clear_chat,
1177
- outputs=[transcription_box, response_box, audio_output, state_info]
1178
  )
1179
 
1180
  refresh_latency_btn.click(
@@ -1182,16 +1294,21 @@ def create_streaming_voice_tab(streaming_service: StreamingVoiceService):
1182
  outputs=[latency_display]
1183
  )
1184
 
1185
- # FIXED: Timer để kiểm tra kết quả VAD
1186
- gr.Timer(1.0).tick(
 
 
 
1187
  fn=check_vad_results,
1188
- outputs=[transcription_box, response_box, audio_output, state_info]
1189
  )
1190
 
1191
- # Timer để cập nhật system info
1192
- gr.Timer(3.0).tick(
1193
- fn=update_state_info,
1194
- outputs=[state_info, latency_display]
 
 
1195
  )
1196
 
1197
  return streaming_tab
 
1018
  with gr.Blocks() as streaming_tab:
1019
  gr.Markdown("## 🎤 Trò chuyện giọng nói thời gian thực - Tối ưu hóa")
1020
 
1021
+ # Store VAD results
1022
  vad_result_state = gr.State(value=None)
1023
 
1024
  with gr.Row():
 
1027
  with gr.Row():
1028
  start_btn = gr.Button("🎙️ Bắt đầu VAD", variant="primary")
1029
  stop_btn = gr.Button("🛑 Dừng VAD", variant="secondary")
1030
+ clear_btn = gr.Button("🗑️ Xóa hội thoại")
1031
 
1032
  gr.Markdown("### Chế độ tự động (VAD)")
1033
  gr.Markdown("Hệ thống tự động nhận diện khi bạn bắt đầu nói")
 
1039
  interactive=False
1040
  )
1041
 
1042
+ # Hiển thị trạng thái real-time
1043
+ status_display = gr.Textbox(
1044
+ label="🎯 Trạng thái hiện tại",
1045
+ value="Đang chờ...",
1046
+ interactive=False,
1047
+ lines=2
1048
+ )
1049
+
1050
  gr.Markdown("### Chế độ thủ công")
1051
  microphone = gr.Microphone(
1052
  label="🎤 Nhấn để nói thủ công",
 
1061
  )
1062
  refresh_latency_btn = gr.Button("🔄 Refresh Metrics", size="sm")
1063
 
 
 
 
 
 
 
 
 
 
 
1064
  with gr.Column(scale=2):
1065
+ # Real-time transcription
1066
  transcription_box = gr.Textbox(
1067
+ label="📝 Bạn đang nói (real-time)",
1068
+ lines=3,
1069
+ interactive=False,
1070
+ value="Nói gì đó để bắt đầu..."
1071
  )
1072
 
1073
+ # AI Response
1074
  response_box = gr.Textbox(
1075
  label="🤖 Phản hồi AI",
1076
+ lines=5,
1077
+ interactive=False,
1078
+ value="Tôi sẽ trả lời bạn ở đây..."
1079
  )
1080
 
1081
  audio_output = gr.Audio(
 
1086
 
1087
  # State variables
1088
  is_vad_active = gr.State(value=False)
1089
+ last_vad_update = gr.State(value=0)
1090
+
1091
+ # Global variable for VAD callback
1092
+ vad_results_queue = queue.Queue()
1093
 
1094
  def vad_callback(result):
1095
+ """Callback khi VAD phát hiện speech"""
1096
+ print(f"🎯 VAD Callback: {result.get('transcription', 'No text')}")
1097
+ vad_results_queue.put(result)
1098
 
1099
  def start_vad():
1100
+ """Bắt đầu VAD"""
1101
+ try:
1102
+ # Set callback
1103
+ success = streaming_service.start_listening(vad_callback)
1104
+
1105
+ if success:
1106
+ is_vad_active.value = True
1107
+ status = "✅ VAD đang chạy - Hãy nói gì đó!"
1108
+
1109
+ # Hiển thị thông báo
1110
+ if streaming_service.speech_callback:
1111
+ streaming_service.speech_callback({
1112
+ 'transcription': "VAD đã sẵn sàng! Hãy nói...",
1113
+ 'response': "",
1114
+ 'tts_audio': None,
1115
+ 'status': 'listening'
1116
+ })
1117
+
1118
+ state = streaming_service.get_conversation_state()
1119
+ state_text = f"✅ VAD: Đang hoạt động\nQueue: {state['queue_size']}\nThreads: {state['worker_threads']}"
1120
+ status_msg = "🎤 Đang lắng nghe... nói đi!"
1121
+
1122
+ else:
1123
+ status = "❌ Không thể khởi động VAD"
1124
+ state_text = "Lỗi khởi động"
1125
+ status_msg = "Lỗi!"
1126
+
1127
+ return status, state_text, status_msg
1128
+
1129
+ except Exception as e:
1130
+ print(f"❌ Lỗi start_vad: {e}")
1131
+ return "❌ Lỗi khởi động", f"Lỗi: {e}", "Lỗi!"
1132
 
1133
  def stop_vad():
1134
  """Dừng VAD"""
1135
+ try:
1136
+ streaming_service.stop_listening()
1137
+ is_vad_active.value = False
1138
+
1139
+ # Clear queue
1140
+ while not vad_results_queue.empty():
1141
+ try:
1142
+ vad_results_queue.get_nowait()
1143
+ except:
1144
+ pass
1145
+
1146
+ state = streaming_service.get_conversation_state()
1147
+ state_text = f"🛑 VAD: Đã dừng\nHistory: {state['history_length']} messages"
1148
+ status_msg = "Đã dừng lắng nghe"
1149
+
1150
+ return "🛑 VAD đã dừng", state_text, status_msg
1151
+
1152
+ except Exception as e:
1153
+ print(f"❌ Lỗi stop_vad: {e}")
1154
+ return "Lỗi!", f"Lỗi: {e}", "Lỗi!"
1155
 
1156
  def process_microphone(audio_data):
1157
+ """Xử lý microphone input manual mode"""
1158
  if audio_data is None:
1159
+ return "Chưa có âm thanh", "Hãy nói gì đó...", None, "VAD: Tắt", "Manual mode"
1160
 
1161
  try:
1162
+ print(f"🎤 Manual audio: {len(audio_data[1])} samples")
1163
+
1164
+ # Process with streaming service
1165
  result = streaming_service.process_streaming_audio(audio_data)
1166
+
1167
  state = streaming_service.get_conversation_state()
1168
  state_text = f"Manual mode\nHistory: {state['history_length']} messages"
1169
+
1170
+ # Determine status
1171
+ if result['status'] == 'processing':
1172
+ status_msg = "⏳ Đang xử lý..."
1173
+ elif result['status'] == 'listening':
1174
+ status_msg = "🎤 Đang nghe..."
1175
+ else:
1176
+ status_msg = result['status']
1177
+
1178
+ return result['transcription'], result['response'], result['tts_audio'], state_text, status_msg
1179
+
1180
  except Exception as e:
1181
+ print(f"Lỗi process_microphone: {e}")
1182
+ return f"Lỗi: {e}", "Xin lỗi, có lỗi xảy ra", None, "Lỗi xử lý", "Lỗi!"
1183
 
1184
  def check_vad_results():
1185
+ """Kiểm tra hiển thị kết quả VAD"""
1186
+ try:
1187
+ # Check if VAD is active
1188
+ if not is_vad_active.value:
1189
+ return gr.skip(), gr.skip(), gr.skip(), gr.skip(), gr.skip()
 
 
1190
 
1191
+ # Try to get result from queue
1192
+ try:
1193
+ result = vad_results_queue.get_nowait()
1194
+
1195
+ print(f"📥 Got VAD result: {result.get('transcription', 'No text')}")
1196
+
1197
+ state = streaming_service.get_conversation_state()
1198
+ state_text = f"VAD mode\nQueue: {state['queue_size']}\nThreads: {state['worker_threads']}"
1199
+
1200
+ # Determine status message
1201
+ if result.get('status') == 'processing':
1202
+ status_msg = "⏳ Đang xử lý VAD..."
1203
+ elif result.get('status') == 'partial':
1204
+ status_msg = "🎤 Đang nhận diện..."
1205
+ elif result.get('status') == 'completed':
1206
+ status_msg = "✅ Đã xử lý xong"
1207
+ else:
1208
+ status_msg = result.get('status', 'Đang lắng nghe')
1209
+
1210
+ return (
1211
+ result.get('transcription', ''),
1212
+ result.get('response', ''),
1213
+ result.get('tts_audio', None),
1214
+ state_text,
1215
+ status_msg
1216
+ )
1217
+
1218
+ except queue.Empty:
1219
+ # No new results
1220
+ return gr.skip(), gr.skip(), gr.skip(), gr.skip(), gr.skip()
1221
+
1222
+ except Exception as e:
1223
+ print(f"❌ Lỗi check_vad_results: {e}")
1224
+ return gr.skip(), gr.skip(), gr.skip(), gr.skip(), gr.skip()
1225
 
1226
  def clear_chat():
1227
  """Xóa hội thoại"""
1228
  streaming_service.clear_conversation()
1229
  state = streaming_service.get_conversation_state()
1230
+ state_text = f"Đã xóa hội thoại\nHistory: {state['history_length']} messages"
1231
+ status_msg = "Sẵn sàng"
1232
+ return "", "", None, state_text, status_msg
1233
 
1234
  def refresh_latency():
1235
  """Làm mới latency metrics"""
1236
+ try:
1237
+ stats = streaming_service.get_latency_stats()
1238
+ return stats
1239
+ except Exception as e:
1240
+ print(f"❌ Lỗi refresh_latency: {e}")
1241
+ return {}
1242
 
1243
+ def update_status_info():
1244
  """Cập nhật thông tin trạng thái"""
1245
+ try:
1246
+ state = streaming_service.get_conversation_state()
1247
+
1248
+ formatted_state = f"🎯 VAD: {'✅ Đang chạy' if state['is_listening'] else '❌ Dừng'}\n"
1249
+ formatted_state += f"📊 Queue: {state['queue_size']}\n"
1250
+ formatted_state += f"📝 History: {state['history_length']} messages\n"
1251
+ formatted_state += f"🧵 Threads: {state['worker_threads']}\n"
1252
+ formatted_state += f"⏰ Last: {state['last_update']}"
1253
+
1254
+ # Get latency stats
1255
+ latency_info = streaming_service.get_latency_stats()
1256
+
1257
+ # Current status
1258
+ if state['is_listening']:
1259
+ current_status = "🎤 Đang lắng nghe... nói đi!"
1260
+ else:
1261
+ current_status = "🛑 Đã dừng"
1262
+
1263
+ return formatted_state, latency_info, current_status
1264
+
1265
+ except Exception as e:
1266
+ print(f"❌ Lỗi update_status_info: {e}")
1267
+ return f"Lỗi: {e}", {}, "Lỗi!"
1268
 
1269
  # Event handlers
1270
+ start_btn.click(
1271
+ start_vad,
1272
+ outputs=[vad_status, status_display, transcription_box]
1273
+ )
1274
 
1275
+ stop_btn.click(
1276
+ stop_vad,
1277
+ outputs=[vad_status, status_display, transcription_box]
1278
+ )
1279
+
1280
+ # Microphone streaming
1281
  microphone.stream(
1282
  process_microphone,
1283
  inputs=[microphone],
1284
+ outputs=[transcription_box, response_box, audio_output, status_display, vad_status]
1285
  )
1286
 
1287
  clear_btn.click(
1288
  clear_chat,
1289
+ outputs=[transcription_box, response_box, audio_output, status_display, vad_status]
1290
  )
1291
 
1292
  refresh_latency_btn.click(
 
1294
  outputs=[latency_display]
1295
  )
1296
 
1297
+ # IMPORTANT: Timer để kiểm tra kết quả VAD - sử dụng interval ngắn hơn
1298
+ timer_component = gr.Timer(0.5) # 500ms interval
1299
+
1300
+ # Connect timer to check function
1301
+ timer_component.tick(
1302
  fn=check_vad_results,
1303
+ outputs=[transcription_box, response_box, audio_output, status_display, vad_status]
1304
  )
1305
 
1306
+ # Timer để cập nhật system info (mỗi 2 giây)
1307
+ info_timer = gr.Timer(2.0)
1308
+
1309
+ info_timer.tick(
1310
+ fn=update_status_info,
1311
+ outputs=[status_display, latency_display, vad_status]
1312
  )
1313
 
1314
  return streaming_tab