minhahwang Copilot commited on
Commit
44fbd0d
·
1 Parent(s): 60d60e5

fix: Play produces no sound on HF Space

Browse files

Root causes:
- Stock voice profile was only created lazily on first Play, failing silently
- synthesize_custom_voice_streaming returned empty when profile missing
- Worker put empty arrays into queue, Gradio received zero-length audio

Fixes:
- Pre-create stock voice profile at startup (after model load)
- Raise RuntimeError instead of silent return when profile unavailable
- _ensure_stock_voice_profile raises FileNotFoundError if ref wav missing
- Skip empty wav segments in audio stream generator
- Guard against None wav in error path

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Files changed (3) hide show
  1. app.py +6 -1
  2. tts.py +7 -1
  3. voice_clone.py +9 -8
app.py CHANGED
@@ -410,10 +410,15 @@ else:
410
 
411
  # Preload models at startup for fast response
412
  print("[MomsVoice] Preloading Qwen3-TTS 1.7B Base model (cloning + stock voice)...")
413
- from voice_clone import get_qwen_tts
414
  get_qwen_tts()
415
  print("[MomsVoice] TTS model ready.")
416
 
 
 
 
 
 
417
  print("[MomsVoice] Preloading LFM2.5-Audio-1.5B Q&A model...")
418
  from inference_lfm import get_lfm_model
419
  get_lfm_model()
 
410
 
411
  # Preload models at startup for fast response
412
  print("[MomsVoice] Preloading Qwen3-TTS 1.7B Base model (cloning + stock voice)...")
413
+ from voice_clone import get_qwen_tts, _ensure_stock_voice_profile
414
  get_qwen_tts()
415
  print("[MomsVoice] TTS model ready.")
416
 
417
+ # Pre-create stock voice profile so Play works immediately
418
+ print("[MomsVoice] Creating stock voice profile (vivian)...")
419
+ _ensure_stock_voice_profile()
420
+ print("[MomsVoice] Stock voice profile ready.")
421
+
422
  print("[MomsVoice] Preloading LFM2.5-Audio-1.5B Q&A model...")
423
  from inference_lfm import get_lfm_model
424
  get_lfm_model()
tts.py CHANGED
@@ -405,9 +405,15 @@ def generate_audio_stream(
405
  if audio_buffer:
406
  combined = np.concatenate(audio_buffer)
407
  yield sample_rate, combined, last_idx, n, None
408
- yield sample_rate, wav, i, n, err
 
 
409
  break
410
  last_idx = i
 
 
 
 
411
 
412
  # Add transition chime between chunks (not before first)
413
  if add_transitions and chunk_count > 0:
 
405
  if audio_buffer:
406
  combined = np.concatenate(audio_buffer)
407
  yield sample_rate, combined, last_idx, n, None
408
+ audio_buffer = []
409
+ buffer_samples = 0
410
+ yield sample_rate, np.zeros(0, dtype=np.float32), i, n, err
411
  break
412
  last_idx = i
413
+
414
+ # Skip empty audio segments
415
+ if wav is None or len(wav) == 0:
416
+ continue
417
 
418
  # Add transition chime between chunks (not before first)
419
  if add_transitions and chunk_count > 0:
voice_clone.py CHANGED
@@ -373,12 +373,11 @@ def _ensure_stock_voice_profile():
373
  if STOCK_VOICE_PROFILE_ID in _PROFILE_CACHE:
374
  return
375
  # Create profile from vivian reference audio
376
- if VIVIAN_REF_PATH.exists():
377
- try:
378
- create_voice_profile(str(VIVIAN_REF_PATH), voice_name="Vivian (Stock)", profile_id_override=STOCK_VOICE_PROFILE_ID)
379
- logger.info("Stock vivian voice profile created from reference audio.")
380
- except Exception as e:
381
- logger.warning("Failed to create stock voice profile: %s", e)
382
 
383
 
384
  def synthesize_custom_voice_streaming(
@@ -392,8 +391,10 @@ def synthesize_custom_voice_streaming(
392
  with _cache_lock:
393
  prompt_items = _PROFILE_CACHE.get(STOCK_VOICE_PROFILE_ID)
394
  if prompt_items is None:
395
- logger.warning("Stock voice profile not available, synthesizing without clone.")
396
- return
 
 
397
 
398
  model = get_qwen_tts()
399
  with GPU_INFERENCE_LOCK:
 
373
  if STOCK_VOICE_PROFILE_ID in _PROFILE_CACHE:
374
  return
375
  # Create profile from vivian reference audio
376
+ if not VIVIAN_REF_PATH.exists():
377
+ logger.error("Stock voice reference not found at %s", VIVIAN_REF_PATH)
378
+ raise FileNotFoundError(f"Stock voice reference not found: {VIVIAN_REF_PATH}")
379
+ create_voice_profile(str(VIVIAN_REF_PATH), voice_name="Vivian (Stock)", profile_id_override=STOCK_VOICE_PROFILE_ID)
380
+ logger.info("Stock vivian voice profile created from reference audio.")
 
381
 
382
 
383
  def synthesize_custom_voice_streaming(
 
391
  with _cache_lock:
392
  prompt_items = _PROFILE_CACHE.get(STOCK_VOICE_PROFILE_ID)
393
  if prompt_items is None:
394
+ raise RuntimeError(
395
+ "Stock voice profile could not be created. "
396
+ "Check that assets/vivian_reference.wav exists and the TTS model loaded correctly."
397
+ )
398
 
399
  model = get_qwen_tts()
400
  with GPU_INFERENCE_LOCK: