Spaces:
Paused
Paused
Commit ·
44fbd0d
1
Parent(s): 60d60e5
fix: Play produces no sound on HF Space
Browse filesRoot 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>
- app.py +6 -1
- tts.py +7 -1
- 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 |
-
|
|
|
|
|
|
|
| 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 |
-
|
| 378 |
-
|
| 379 |
-
|
| 380 |
-
|
| 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 |
-
|
| 396 |
-
|
|
|
|
|
|
|
| 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:
|