Spaces:
Running on Zero
Running on Zero
Raise errors HARP can show, and prepare the reference before reserving the GPU
Browse filesgr.Warning never reaches HARP, so a failed request looked like an empty result. Missing inputs and an unusable reference are now refused with gr.Error before the GPU is reserved, and the reference is trimmed outside the GPU call.
app.py
CHANGED
|
@@ -59,81 +59,40 @@ print("Initializing MegaTTS3 model...")
|
|
| 59 |
infer_pipe = MegaTTS3DiTInfer()
|
| 60 |
print("Model loaded successfully!")
|
| 61 |
|
| 62 |
-
def reset_model():
|
| 63 |
-
"""Reset the inference pipeline to recover from CUDA errors."""
|
| 64 |
-
global infer_pipe
|
| 65 |
-
try:
|
| 66 |
-
if torch.cuda.is_available():
|
| 67 |
-
torch.cuda.empty_cache()
|
| 68 |
-
torch.cuda.synchronize()
|
| 69 |
-
print("Reinitializing MegaTTS3 model...")
|
| 70 |
-
infer_pipe = MegaTTS3DiTInfer()
|
| 71 |
-
print("Model reinitialized successfully!")
|
| 72 |
-
return True
|
| 73 |
-
except Exception as e:
|
| 74 |
-
print(f"Failed to reinitialize model: {e}")
|
| 75 |
-
return False
|
| 76 |
-
|
| 77 |
@spaces.GPU
|
| 78 |
-
def generate_speech(
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
try:
|
| 84 |
print(f"Generating speech with: {inp_text}...")
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
try:
|
| 88 |
-
processed_audio_path = preprocess_audio_robust(inp_audio)
|
| 89 |
-
# Use existing cut_wav for final trimming
|
| 90 |
-
cut_wav(processed_audio_path, max_len=10)
|
| 91 |
-
wav_path = processed_audio_path
|
| 92 |
-
except Exception as audio_error:
|
| 93 |
-
gr.Warning(f"Audio preprocessing failed: {str(audio_error)}")
|
| 94 |
-
return None
|
| 95 |
-
|
| 96 |
-
# Read audio file
|
| 97 |
-
with open(wav_path, 'rb') as file:
|
| 98 |
-
file_content = file.read()
|
| 99 |
-
|
| 100 |
-
# Check CUDA availability and clear cache
|
| 101 |
-
# if torch.cuda.is_available():
|
| 102 |
-
# torch.cuda.empty_cache()
|
| 103 |
-
# print(f"CUDA device: {torch.cuda.get_device_name()}")
|
| 104 |
-
# else:
|
| 105 |
-
# gr.Warning("CUDA is not available. Please check your GPU setup.")
|
| 106 |
-
# return None
|
| 107 |
-
|
| 108 |
-
# Generate speech with proper error handling
|
| 109 |
-
try:
|
| 110 |
-
resource_context = infer_pipe.preprocess(file_content)
|
| 111 |
-
fs, wav = infer_pipe.forward(resource_context, inp_text, time_step=infer_timestep, p_w=p_w, t_w=t_w)
|
| 112 |
-
# Clean up memory after successful generation
|
| 113 |
-
cleanup_memory()
|
| 114 |
-
return fs, wav
|
| 115 |
-
except RuntimeError as cuda_error:
|
| 116 |
-
if "CUDA" in str(cuda_error):
|
| 117 |
-
print(f"CUDA error detected: {cuda_error}")
|
| 118 |
-
# Try to reset the model to recover from CUDA errors
|
| 119 |
-
if reset_model():
|
| 120 |
-
gr.Warning("CUDA error occurred. Model has been reset. Please try again.")
|
| 121 |
-
else:
|
| 122 |
-
gr.Warning("CUDA error occurred and model reset failed. Please restart the application.")
|
| 123 |
-
return None, None
|
| 124 |
-
else:
|
| 125 |
-
raise cuda_error
|
| 126 |
-
|
| 127 |
except Exception as e:
|
| 128 |
traceback.print_exc()
|
| 129 |
-
gr.
|
| 130 |
-
|
| 131 |
cleanup_memory()
|
| 132 |
-
|
| 133 |
-
|
|
|
|
| 134 |
|
| 135 |
def process_fn(inp_audio, inp_text, infer_timestep, p_w, t_w):
|
| 136 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
sig = AudioSignal(wav, sample_rate=fs)
|
| 138 |
return save_audio(sig)
|
| 139 |
|
|
|
|
| 59 |
infer_pipe = MegaTTS3DiTInfer()
|
| 60 |
print("Model loaded successfully!")
|
| 61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
@spaces.GPU
|
| 63 |
+
def generate_speech(wav_path, inp_text, infer_timestep, p_w, t_w):
|
| 64 |
+
with open(wav_path, 'rb') as file:
|
| 65 |
+
file_content = file.read()
|
| 66 |
+
|
|
|
|
| 67 |
try:
|
| 68 |
print(f"Generating speech with: {inp_text}...")
|
| 69 |
+
resource_context = infer_pipe.preprocess(file_content)
|
| 70 |
+
fs, wav = infer_pipe.forward(resource_context, inp_text, time_step=infer_timestep, p_w=p_w, t_w=t_w)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
except Exception as e:
|
| 72 |
traceback.print_exc()
|
| 73 |
+
raise gr.Error(f"Speech generation failed: {e}") from e
|
| 74 |
+
finally:
|
| 75 |
cleanup_memory()
|
| 76 |
+
|
| 77 |
+
return fs, wav
|
| 78 |
+
|
| 79 |
|
| 80 |
def process_fn(inp_audio, inp_text, infer_timestep, p_w, t_w):
|
| 81 |
+
# Checked and prepared before the GPU is reserved, so a request that cannot run spends none of
|
| 82 |
+
# the caller's ZeroGPU allowance. A failure is raised as gr.Error, since HARP never sees a
|
| 83 |
+
# gr.Warning.
|
| 84 |
+
if not inp_audio:
|
| 85 |
+
raise gr.Error("Provide a recording of the voice to clone.")
|
| 86 |
+
if not (inp_text or "").strip():
|
| 87 |
+
raise gr.Error("Enter the text for the cloned voice to speak.")
|
| 88 |
+
|
| 89 |
+
try:
|
| 90 |
+
wav_path = preprocess_audio_robust(inp_audio)
|
| 91 |
+
cut_wav(wav_path, max_len=10)
|
| 92 |
+
except Exception as e:
|
| 93 |
+
raise gr.Error(f"Could not use the reference recording: {e}") from e
|
| 94 |
+
|
| 95 |
+
fs, wav = generate_speech(wav_path, inp_text, int(infer_timestep), p_w, t_w)
|
| 96 |
sig = AudioSignal(wav, sample_rate=fs)
|
| 97 |
return save_audio(sig)
|
| 98 |
|