Arrcttacsrks commited on
Commit
6b200af
·
verified ·
1 Parent(s): 86fdb38

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +86 -40
app.py CHANGED
@@ -354,40 +354,63 @@ def decode_audio(codes_str, codec):
354
  return recon[0, 0, :]
355
 
356
  # --- MODEL LOADING ---
357
- print("📦 Đang tải model Q4 GGUF Codec ONNX...")
358
- model_loaded = False
359
- backbone = None
360
- codec = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
 
362
- try:
363
- backbone = Llama.from_pretrained(
364
- repo_id=BACKBONE_REPO,
365
- filename="*.gguf",
366
- verbose=False,
367
- n_gpu_layers=-1,
368
- n_ctx=2048,
369
- mlock=True,
370
- flash_attn=True,
371
- )
372
-
373
- codec = NeuCodecOnnxDecoder.from_pretrained(CODEC_REPO)
374
-
375
- print("✅ Model đã tải thành công!")
376
- model_loaded = True
377
- except Exception as e:
378
- import traceback
379
- traceback.print_exc()
380
- print(f"❌ Lỗi khi tải model: {e}")
381
- model_loaded = False
382
 
383
  # --- SYNTHESIS FUNCTION (Internal) ---
384
  def synthesize_speech_internal(text, voice_choice):
385
  """Internal synthesis function không phụ thuộc UI"""
386
- global backbone, codec, model_loaded
387
 
388
- if not model_loaded:
389
- print("❌ Model chưa được tải")
390
- return None
 
 
391
 
392
  if not text or text.strip() == "":
393
  print("❌ Text rỗng")
@@ -451,7 +474,7 @@ def synthesize_speech_internal(text, voice_choice):
451
  )
452
 
453
  # Generate
454
- output = backbone(
455
  prompt,
456
  max_tokens=2048,
457
  temperature=1.0,
@@ -461,7 +484,7 @@ def synthesize_speech_internal(text, voice_choice):
461
  output_str = output["choices"][0]["text"]
462
 
463
  # Decode
464
- chunk_wav = decode_audio(output_str, codec)
465
 
466
  if chunk_wav is not None and len(chunk_wav) > 0:
467
  all_audio_segments.append(chunk_wav)
@@ -495,11 +518,13 @@ def synthesize_speech_internal(text, voice_choice):
495
  # --- SYNTHESIS FUNCTION (UI) ---
496
  def synthesize_speech(text, voice_choice):
497
  """Main synthesis function với UI feedback"""
498
- global backbone, codec, model_loaded
499
 
500
- if not model_loaded:
501
- yield None, "⚠️ Model chưa tải. Vui lòng kiểm tra lỗi console!"
502
- return
 
 
 
503
 
504
  if not text or text.strip() == "":
505
  yield None, "⚠️ Vui lòng nhập văn bản!"
@@ -553,7 +578,8 @@ def synthesize_speech(text, voice_choice):
553
 
554
  try:
555
  for i, chunk in enumerate(text_chunks):
556
- yield None, f"⏳ Đang xử lý đoạn {i+1}/{total_chunks}... ({int((i/total_chunks)*100)}%)"
 
557
 
558
  # Phonemize
559
  ref_text_phoneme = phonemize_with_dict(ref_text_raw)
@@ -568,7 +594,7 @@ def synthesize_speech(text, voice_choice):
568
  )
569
 
570
  # Generate
571
- output = backbone(
572
  prompt,
573
  max_tokens=2048,
574
  temperature=1.0,
@@ -578,7 +604,7 @@ def synthesize_speech(text, voice_choice):
578
  output_str = output["choices"][0]["text"]
579
 
580
  # Decode
581
- chunk_wav = decode_audio(output_str, codec)
582
 
583
  if chunk_wav is not None and len(chunk_wav) > 0:
584
  all_audio_segments.append(chunk_wav)
@@ -598,11 +624,13 @@ def synthesize_speech(text, voice_choice):
598
  output_path = tmp.name
599
 
600
  process_time = time.time() - start_time
 
 
601
 
602
  # Lưu vào lịch sử
603
  permanent_path = add_to_history(raw_text, voice_choice, output_path, process_time, "Thành công")
604
 
605
- yield permanent_path, f"✅ Hoàn tất! (Tổng thời gian: {process_time:.2f}s | RTF: {process_time/(len(final_wav)/SAMPLE_RATE):.3f})"
606
 
607
  except Exception as e:
608
  import traceback
@@ -731,7 +759,7 @@ EXAMPLES_LIST = [
731
  ["Thành phố Hồ Chí Minh luôn chuyển mình không ngừng với nhịp sống hối hả, năng động.", "Dung (nữ miền Nam)"],
732
  ]
733
 
734
- initial_status = f"✅ Model đã tải thành công! (Chạy trên **{DEVICE_INFO}**). Hỗ trợ xử lý background và lưu lịch sử." if model_loaded else " Lỗi khi tải model."
735
 
736
  with gr.Blocks(title="VieNeu-TTS", theme=theme, css=css) as demo:
737
  with gr.Column(elem_classes="container"):
@@ -757,6 +785,22 @@ with gr.Blocks(title="VieNeu-TTS", theme=theme, css=css) as demo:
757
  """)
758
 
759
  status_banner = gr.Markdown(initial_status)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
760
 
761
  # --- TABS ---
762
  with gr.Tabs():
@@ -778,7 +822,7 @@ with gr.Blocks(title="VieNeu-TTS", theme=theme, css=css) as demo:
778
  )
779
 
780
  with gr.Row():
781
- btn_generate = gr.Button("🎵 Bắt đầu tổng hợp", variant="primary", size="lg", interactive=model_loaded)
782
  btn_clear = gr.Button("🗑️ Xóa", variant="secondary", size="lg")
783
 
784
  with gr.Column(scale=2):
@@ -905,6 +949,7 @@ with gr.Blocks(title="VieNeu-TTS", theme=theme, css=css) as demo:
905
  - ✅ Chia chunk thông minh
906
  - ✅ Thread-safe operations
907
  - ✅ Tự động xóa file cũ khi vượt quá 100 bản ghi
 
908
 
909
  ### 📊 Thống kê
910
  {get_processing_stats()}
@@ -969,6 +1014,7 @@ if __name__ == "__main__":
969
  print(f"📂 Lịch sử lưu tại: {HISTORY_DIR}")
970
  print(f"🎭 Số giọng mẫu: {len(VOICE_SAMPLES)}")
971
  print(f"⚙️ Chế độ: {DEVICE_INFO}")
 
972
  print(f"{'='*60}\n")
973
 
974
  demo.queue().launch(
 
354
  return recon[0, 0, :]
355
 
356
  # --- MODEL LOADING ---
357
+ # Sử dụng class để giữ state của model
358
+ class ModelManager:
359
+ def __init__(self):
360
+ self.backbone = None
361
+ self.codec = None
362
+ self.model_loaded = False
363
+ self.loading_lock = threading.Lock()
364
+ self.load_models()
365
+
366
+ def load_models(self):
367
+ """Tải models với thread safety"""
368
+ with self.loading_lock:
369
+ if self.model_loaded:
370
+ print("✅ Models đã được tải trước đó")
371
+ return True
372
+
373
+ print("📦 Đang tải model Q4 GGUF và Codec ONNX...")
374
+ try:
375
+ self.backbone = Llama.from_pretrained(
376
+ repo_id=BACKBONE_REPO,
377
+ filename="*.gguf",
378
+ verbose=False,
379
+ n_gpu_layers=-1,
380
+ n_ctx=2048,
381
+ mlock=True,
382
+ flash_attn=True,
383
+ )
384
+
385
+ self.codec = NeuCodecOnnxDecoder.from_pretrained(CODEC_REPO)
386
+
387
+ self.model_loaded = True
388
+ print("✅ Model đã tải thành công!")
389
+ return True
390
+
391
+ except Exception as e:
392
+ import traceback
393
+ traceback.print_exc()
394
+ print(f"❌ Lỗi khi tải model: {e}")
395
+ self.model_loaded = False
396
+ return False
397
+
398
+ def is_ready(self):
399
+ """Kiểm tra xem model đã sẵn sàng chưa"""
400
+ return self.model_loaded and self.backbone is not None and self.codec is not None
401
 
402
+ # Khởi tạo ModelManager singleton
403
+ model_manager = ModelManager()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
404
 
405
  # --- SYNTHESIS FUNCTION (Internal) ---
406
  def synthesize_speech_internal(text, voice_choice):
407
  """Internal synthesis function không phụ thuộc UI"""
 
408
 
409
+ if not model_manager.is_ready():
410
+ print("❌ Model chưa được tải, đang thử tải lại...")
411
+ if not model_manager.load_models():
412
+ print("❌ Không thể tải model")
413
+ return None
414
 
415
  if not text or text.strip() == "":
416
  print("❌ Text rỗng")
 
474
  )
475
 
476
  # Generate
477
+ output = model_manager.backbone(
478
  prompt,
479
  max_tokens=2048,
480
  temperature=1.0,
 
484
  output_str = output["choices"][0]["text"]
485
 
486
  # Decode
487
+ chunk_wav = decode_audio(output_str, model_manager.codec)
488
 
489
  if chunk_wav is not None and len(chunk_wav) > 0:
490
  all_audio_segments.append(chunk_wav)
 
518
  # --- SYNTHESIS FUNCTION (UI) ---
519
  def synthesize_speech(text, voice_choice):
520
  """Main synthesis function với UI feedback"""
 
521
 
522
+ if not model_manager.is_ready():
523
+ yield None, "⚠️ Model chưa tải. Đang thử tải lại..."
524
+ if not model_manager.load_models():
525
+ yield None, "❌ Không thể tải model. Vui lòng kiểm tra console!"
526
+ return
527
+ yield None, "✅ Model đã tải thành công!"
528
 
529
  if not text or text.strip() == "":
530
  yield None, "⚠️ Vui lòng nhập văn bản!"
 
578
 
579
  try:
580
  for i, chunk in enumerate(text_chunks):
581
+ progress = int((i/total_chunks)*100)
582
+ yield None, f"⏳ Đang xử lý đoạn {i+1}/{total_chunks}... ({progress}%)"
583
 
584
  # Phonemize
585
  ref_text_phoneme = phonemize_with_dict(ref_text_raw)
 
594
  )
595
 
596
  # Generate
597
+ output = model_manager.backbone(
598
  prompt,
599
  max_tokens=2048,
600
  temperature=1.0,
 
604
  output_str = output["choices"][0]["text"]
605
 
606
  # Decode
607
+ chunk_wav = decode_audio(output_str, model_manager.codec)
608
 
609
  if chunk_wav is not None and len(chunk_wav) > 0:
610
  all_audio_segments.append(chunk_wav)
 
624
  output_path = tmp.name
625
 
626
  process_time = time.time() - start_time
627
+ audio_duration = len(final_wav) / SAMPLE_RATE
628
+ rtf = process_time / audio_duration
629
 
630
  # Lưu vào lịch sử
631
  permanent_path = add_to_history(raw_text, voice_choice, output_path, process_time, "Thành công")
632
 
633
+ yield permanent_path, f"✅ Hoàn tất! (Thời gian: {process_time:.2f}s | Audio: {audio_duration:.2f}s | RTF: {rtf:.3f})"
634
 
635
  except Exception as e:
636
  import traceback
 
759
  ["Thành phố Hồ Chí Minh luôn chuyển mình không ngừng với nhịp sống hối hả, năng động.", "Dung (nữ miền Nam)"],
760
  ]
761
 
762
+ initial_status = f"✅ Model đã tải thành công! (Chạy trên **{DEVICE_INFO}**). Hỗ trợ xử lý background và lưu lịch sử." if model_manager.is_ready() else "⚠️ Model đang được tải hoặc chưa sẵn sàng..."
763
 
764
  with gr.Blocks(title="VieNeu-TTS", theme=theme, css=css) as demo:
765
  with gr.Column(elem_classes="container"):
 
785
  """)
786
 
787
  status_banner = gr.Markdown(initial_status)
788
+
789
+ # Thêm nút kiểm tra model status
790
+ with gr.Row():
791
+ btn_check_model = gr.Button("🔍 Kiểm tra trạng thái Model", size="sm", variant="secondary")
792
+ model_status_output = gr.Textbox(label="", show_label=False, interactive=False, container=False)
793
+
794
+ def check_model_status():
795
+ if model_manager.is_ready():
796
+ return f"✅ Model sẵn sàng | Backbone: {'Loaded' if model_manager.backbone else 'Not loaded'} | Codec: {'Loaded' if model_manager.codec else 'Not loaded'}"
797
+ else:
798
+ return "⚠️ Model chưa sẵn sàng. Nhấn nút tổng hợp để tự động tải model."
799
+
800
+ btn_check_model.click(
801
+ fn=check_model_status,
802
+ outputs=model_status_output
803
+ )
804
 
805
  # --- TABS ---
806
  with gr.Tabs():
 
822
  )
823
 
824
  with gr.Row():
825
+ btn_generate = gr.Button("🎵 Bắt đầu tổng hợp", variant="primary", size="lg")
826
  btn_clear = gr.Button("🗑️ Xóa", variant="secondary", size="lg")
827
 
828
  with gr.Column(scale=2):
 
949
  - ✅ Chia chunk thông minh
950
  - ✅ Thread-safe operations
951
  - ✅ Tự động xóa file cũ khi vượt quá 100 bản ghi
952
+ - ✅ Auto-reload model sau khi reload trang
953
 
954
  ### 📊 Thống kê
955
  {get_processing_stats()}
 
1014
  print(f"📂 Lịch sử lưu tại: {HISTORY_DIR}")
1015
  print(f"🎭 Số giọng mẫu: {len(VOICE_SAMPLES)}")
1016
  print(f"⚙️ Chế độ: {DEVICE_INFO}")
1017
+ print(f"✅ Model status: {'Ready' if model_manager.is_ready() else 'Not ready'}")
1018
  print(f"{'='*60}\n")
1019
 
1020
  demo.queue().launch(