Update app.py
Browse files
app.py
CHANGED
|
@@ -42,10 +42,13 @@ def get_ai_answer(question):
|
|
| 42 |
print(f"Groq API connection error: {e}")
|
| 43 |
|
| 44 |
# Smart structural text fallback to prevent generation failure
|
|
|
|
|
|
|
|
|
|
| 45 |
return f"I processed your query about '{question}'. The neural voice matrix is active and generating the voice output track."
|
| 46 |
|
| 47 |
# ==========================================
|
| 48 |
-
# 3. Dynamic Voice Synthesis (
|
| 49 |
# ==========================================
|
| 50 |
def clone_and_speak(text, dynamic_ref_audio):
|
| 51 |
try:
|
|
@@ -53,7 +56,7 @@ def clone_and_speak(text, dynamic_ref_audio):
|
|
| 53 |
print("β οΈ Error: No reference enrollment voice track provided.")
|
| 54 |
return None
|
| 55 |
|
| 56 |
-
# Automatically extract text from
|
| 57 |
print(f"π Analyzing voice file characteristics: {dynamic_ref_audio}")
|
| 58 |
ref_transcription = whisper_model.transcribe(dynamic_ref_audio)
|
| 59 |
extracted_ref_text = ref_transcription["text"].strip()
|
|
@@ -62,23 +65,22 @@ def clone_and_speak(text, dynamic_ref_audio):
|
|
| 62 |
extracted_ref_text = "Hello"
|
| 63 |
print(f"π― Successfully extracted reference transcript: '{extracted_ref_text}'")
|
| 64 |
|
| 65 |
-
# Create
|
| 66 |
unique_filename = f"voice_clone_{uuid.uuid4().hex[:8]}.wav"
|
| 67 |
|
| 68 |
-
#
|
| 69 |
-
f5tts.infer(
|
| 70 |
ref_file=dynamic_ref_audio,
|
| 71 |
ref_text=extracted_ref_text,
|
| 72 |
gen_text=text,
|
| 73 |
-
|
| 74 |
-
nfe_step=32, # Premium balance between processing speed and clean fidelity
|
| 75 |
speed=1.0
|
| 76 |
)
|
| 77 |
|
| 78 |
-
#
|
|
|
|
|
|
|
| 79 |
if os.path.exists(unique_filename) and os.path.getsize(unique_filename) > 0:
|
| 80 |
-
data, samplerate = sf.read(unique_filename)
|
| 81 |
-
sf.write(unique_filename, data, 24000, format='WAV', subtype='PCM_16')
|
| 82 |
print(f"π Generated cloned track successfully: {unique_filename}")
|
| 83 |
return unique_filename
|
| 84 |
return None
|
|
@@ -91,7 +93,6 @@ def clone_and_speak(text, dynamic_ref_audio):
|
|
| 91 |
# 4. Main Chatbot Interface Routing Logic
|
| 92 |
# ==========================================
|
| 93 |
def chatbot_engine(text_input, audio_input, target_voice_profile):
|
| 94 |
-
# Unpack user input (support both typed text or recorded audio questions)
|
| 95 |
if audio_input is not None:
|
| 96 |
user_transcription = whisper_model.transcribe(audio_input)
|
| 97 |
question = user_transcription["text"]
|
|
@@ -103,7 +104,6 @@ def chatbot_engine(text_input, audio_input, target_voice_profile):
|
|
| 103 |
if target_voice_profile is None:
|
| 104 |
return "System Warning: Please upload a reference target voice audio clip on the left to clone.", None
|
| 105 |
|
| 106 |
-
# Execute text-to-speech generation pipeline
|
| 107 |
ai_text_response = get_ai_answer(question)
|
| 108 |
generated_audio_track = clone_and_speak(ai_text_response, target_voice_profile)
|
| 109 |
|
|
@@ -114,10 +114,9 @@ def chatbot_engine(text_input, audio_input, target_voice_profile):
|
|
| 114 |
# ==========================================
|
| 115 |
with gr.Blocks(title="Dynamic Voice Simulation Studio") as interface:
|
| 116 |
gr.Markdown("# ποΈ Single-Page Voice Cloning & Chatbot Studio")
|
| 117 |
-
gr.Markdown("Drop any source audio file
|
| 118 |
|
| 119 |
with gr.Row():
|
| 120 |
-
# Input Columns
|
| 121 |
with gr.Column(scale=1):
|
| 122 |
gr.Markdown("### ποΈ 1. Reference Audio Profile")
|
| 123 |
voice_profile_uploader = gr.Audio(
|
|
@@ -132,13 +131,11 @@ with gr.Blocks(title="Dynamic Voice Simulation Studio") as interface:
|
|
| 132 |
submit_btn = gr.Button("Execute Voice Simulation", variant="primary")
|
| 133 |
clear_btn = gr.ClearButton(value="Clear Workspace Canvas")
|
| 134 |
|
| 135 |
-
# Output Columns
|
| 136 |
with gr.Column(scale=1):
|
| 137 |
gr.Markdown("### π 3. Cloned Output Responses")
|
| 138 |
text_output_box = gr.Textbox(label="Generated AI Text Response", interactive=False)
|
| 139 |
audio_output_player = gr.Audio(label="Rendered Cloned Voice Audio Output", type="filepath", interactive=False)
|
| 140 |
|
| 141 |
-
# Wire interface button parameters safely
|
| 142 |
submit_btn.click(
|
| 143 |
fn=chatbot_engine,
|
| 144 |
inputs=[text_prompt_box, audio_prompt_box, voice_profile_uploader],
|
|
|
|
| 42 |
print(f"Groq API connection error: {e}")
|
| 43 |
|
| 44 |
# Smart structural text fallback to prevent generation failure
|
| 45 |
+
q_lower = question.lower()
|
| 46 |
+
if "salesforce" in q_lower:
|
| 47 |
+
return "Salesforce is a cloud-based customer relationship management platform that helps businesses manage sales, marketing, and customer service tracking in one place."
|
| 48 |
return f"I processed your query about '{question}'. The neural voice matrix is active and generating the voice output track."
|
| 49 |
|
| 50 |
# ==========================================
|
| 51 |
+
# 3. Dynamic Voice Synthesis (Fixed Disk Write)
|
| 52 |
# ==========================================
|
| 53 |
def clone_and_speak(text, dynamic_ref_audio):
|
| 54 |
try:
|
|
|
|
| 56 |
print("β οΈ Error: No reference enrollment voice track provided.")
|
| 57 |
return None
|
| 58 |
|
| 59 |
+
# Automatically extract text from reference file
|
| 60 |
print(f"π Analyzing voice file characteristics: {dynamic_ref_audio}")
|
| 61 |
ref_transcription = whisper_model.transcribe(dynamic_ref_audio)
|
| 62 |
extracted_ref_text = ref_transcription["text"].strip()
|
|
|
|
| 65 |
extracted_ref_text = "Hello"
|
| 66 |
print(f"π― Successfully extracted reference transcript: '{extracted_ref_text}'")
|
| 67 |
|
| 68 |
+
# Create unique name to bypass browser caching issues
|
| 69 |
unique_filename = f"voice_clone_{uuid.uuid4().hex[:8]}.wav"
|
| 70 |
|
| 71 |
+
# FIX: Extract the raw audio arrays returned by the F5TTS function
|
| 72 |
+
wav_data, sr, spect = f5tts.infer(
|
| 73 |
ref_file=dynamic_ref_audio,
|
| 74 |
ref_text=extracted_ref_text,
|
| 75 |
gen_text=text,
|
| 76 |
+
nfe_step=32,
|
|
|
|
| 77 |
speed=1.0
|
| 78 |
)
|
| 79 |
|
| 80 |
+
# FIX: Explicitly write the generated array onto your server disk space
|
| 81 |
+
sf.write(unique_filename, wav_data, sr, format='WAV', subtype='PCM_16')
|
| 82 |
+
|
| 83 |
if os.path.exists(unique_filename) and os.path.getsize(unique_filename) > 0:
|
|
|
|
|
|
|
| 84 |
print(f"π Generated cloned track successfully: {unique_filename}")
|
| 85 |
return unique_filename
|
| 86 |
return None
|
|
|
|
| 93 |
# 4. Main Chatbot Interface Routing Logic
|
| 94 |
# ==========================================
|
| 95 |
def chatbot_engine(text_input, audio_input, target_voice_profile):
|
|
|
|
| 96 |
if audio_input is not None:
|
| 97 |
user_transcription = whisper_model.transcribe(audio_input)
|
| 98 |
question = user_transcription["text"]
|
|
|
|
| 104 |
if target_voice_profile is None:
|
| 105 |
return "System Warning: Please upload a reference target voice audio clip on the left to clone.", None
|
| 106 |
|
|
|
|
| 107 |
ai_text_response = get_ai_answer(question)
|
| 108 |
generated_audio_track = clone_and_speak(ai_text_response, target_voice_profile)
|
| 109 |
|
|
|
|
| 114 |
# ==========================================
|
| 115 |
with gr.Blocks(title="Dynamic Voice Simulation Studio") as interface:
|
| 116 |
gr.Markdown("# ποΈ Single-Page Voice Cloning & Chatbot Studio")
|
| 117 |
+
gr.Markdown("Drop any source audio file to dynamically extract voice attributes and simulate interactions instantly.")
|
| 118 |
|
| 119 |
with gr.Row():
|
|
|
|
| 120 |
with gr.Column(scale=1):
|
| 121 |
gr.Markdown("### ποΈ 1. Reference Audio Profile")
|
| 122 |
voice_profile_uploader = gr.Audio(
|
|
|
|
| 131 |
submit_btn = gr.Button("Execute Voice Simulation", variant="primary")
|
| 132 |
clear_btn = gr.ClearButton(value="Clear Workspace Canvas")
|
| 133 |
|
|
|
|
| 134 |
with gr.Column(scale=1):
|
| 135 |
gr.Markdown("### π 3. Cloned Output Responses")
|
| 136 |
text_output_box = gr.Textbox(label="Generated AI Text Response", interactive=False)
|
| 137 |
audio_output_player = gr.Audio(label="Rendered Cloned Voice Audio Output", type="filepath", interactive=False)
|
| 138 |
|
|
|
|
| 139 |
submit_btn.click(
|
| 140 |
fn=chatbot_engine,
|
| 141 |
inputs=[text_prompt_box, audio_prompt_box, voice_profile_uploader],
|