PlotweaverModel commited on
Commit
5b62e76
Β·
verified Β·
1 Parent(s): 0a3811e

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -19
app.py CHANGED
@@ -110,17 +110,46 @@ def generate_silence(dur, path):
110
  capture_output=True, check=True)
111
 
112
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  # ==========================================
114
  # SINGLE-SPEAKER MODES
115
  # ==========================================
116
  @spaces.GPU
117
- def generate_custom_voice(text, language, speaker_label, instruction):
118
- if not text.strip():
119
- raise gr.Error("Please enter some text.")
120
  model = get_model("custom")
121
  speaker = speaker_label.split("--")[0].strip()
122
  lang = language if language != "Auto" else "Auto"
123
- kwargs = {"text": text, "language": lang, "speaker": speaker}
124
  if instruction and instruction.strip():
125
  kwargs["instruct"] = instruction.strip()
126
  print(f"[TTS] Custom: speaker={speaker}, lang={lang}")
@@ -131,15 +160,14 @@ def generate_custom_voice(text, language, speaker_label, instruction):
131
 
132
 
133
  @spaces.GPU
134
- def generate_voice_design(text, language, voice_description):
135
- if not text.strip():
136
- raise gr.Error("Please enter some text.")
137
  if not voice_description.strip():
138
  raise gr.Error("Please describe the voice you want.")
139
  model = get_model("design")
140
  lang = language if language != "Auto" else "Auto"
141
  print(f"[TTS] Design: lang={lang}, desc={voice_description[:60]}")
142
- wavs, sr = model.generate_voice_design(text=text, language=lang, instruct=voice_description)
143
  path = os.path.join(OUTPUT_DIR, f"design_{int(time.time())}.wav")
144
  sf.write(path, wavs[0], sr)
145
  return path
@@ -244,14 +272,13 @@ def extract_pdf_sections(filepath):
244
 
245
 
246
  @spaces.GPU
247
- def generate_voice_clone(text, language, ref_audio, ref_text, add_emotions):
248
- if not text.strip():
249
- raise gr.Error("Please enter some text.")
250
  if ref_audio is None:
251
  raise gr.Error("Please upload a reference audio sample.")
252
 
253
  # Enhance text with emotions if requested
254
- final_text = text
255
  if add_emotions:
256
  client = get_llm_client()
257
  if client:
@@ -574,7 +601,9 @@ with gr.Blocks(title="Qwen3-TTS Demo") as demo:
574
  gr.Markdown("Pick a preset speaker with optional emotion/style.")
575
  with gr.Row():
576
  with gr.Column():
577
- cv_text = gr.Textbox(label="Text", lines=4, placeholder="Enter text...")
 
 
578
  cv_lang = gr.Dropdown(choices=LANGUAGES, value="Auto", label="Language")
579
  cv_speaker = gr.Dropdown(choices=SPEAKER_CHOICES,
580
  value="Ryan -- Dynamic male, strong rhythmic drive (English)",
@@ -585,14 +614,16 @@ with gr.Blocks(title="Qwen3-TTS Demo") as demo:
585
  with gr.Column():
586
  cv_audio = gr.Audio(label="Generated Speech", type="filepath")
587
  cv_btn.click(fn=generate_custom_voice,
588
- inputs=[cv_text, cv_lang, cv_speaker, cv_instruct], outputs=cv_audio)
589
 
590
  # ── Tab 2: Voice Design ──
591
  with gr.Tab("Voice Design"):
592
  gr.Markdown("Describe the voice you want β€” the AI creates it.")
593
  with gr.Row():
594
  with gr.Column():
595
- vd_text = gr.Textbox(label="Text", lines=4, placeholder="Enter text...")
 
 
596
  vd_lang = gr.Dropdown(choices=LANGUAGES, value="English", label="Language")
597
  vd_desc = gr.Textbox(label="Voice Description", lines=3,
598
  placeholder="e.g. Warm male storyteller with British accent...")
@@ -610,7 +641,7 @@ with gr.Blocks(title="Qwen3-TTS Demo") as demo:
610
  with gr.Column():
611
  vd_audio = gr.Audio(label="Generated Speech", type="filepath")
612
  vd_btn.click(fn=generate_voice_design,
613
- inputs=[vd_text, vd_lang, vd_desc], outputs=vd_audio)
614
 
615
  # ── Tab 3: Voice Clone ──
616
  with gr.Tab("Voice Clone"):
@@ -620,18 +651,20 @@ with gr.Blocks(title="Qwen3-TTS Demo") as demo:
620
  )
621
  with gr.Row():
622
  with gr.Column():
623
- vc_text = gr.Textbox(label="Text (in cloned voice)", lines=4, placeholder="What should the cloned voice say...")
 
 
624
  vc_lang = gr.Dropdown(choices=LANGUAGES, value="English", label="Language")
625
  vc_ref = gr.Audio(label="Reference Audio (3+ seconds)", type="filepath")
626
  vc_ref_text = gr.Textbox(label="Transcript (optional, improves quality)",
627
  placeholder="What the person says in the reference...")
628
  vc_emotions = gr.Checkbox(value=False, label="Enhance with emotions",
629
- info="AI adds natural emotional cues (pauses, emphasis, interjections) to make the delivery more expressive. Requires DASHSCOPE_API_KEY.")
630
  vc_btn = gr.Button("Clone & Generate", variant="primary")
631
  with gr.Column():
632
  vc_audio = gr.Audio(label="Cloned Voice Speech", type="filepath")
633
  vc_btn.click(fn=generate_voice_clone,
634
- inputs=[vc_text, vc_lang, vc_ref, vc_ref_text, vc_emotions], outputs=vc_audio)
635
 
636
  # ── Tab 4: Multi-Speaker Story ──
637
  with gr.Tab("Multi-Speaker Story"):
 
110
  capture_output=True, check=True)
111
 
112
 
113
+ # ==========================================
114
+ # TEXT RESOLVER (shared across all modes)
115
+ # ==========================================
116
+ def resolve_text(text_input, file_input):
117
+ """Get text from either the textbox or an uploaded file."""
118
+ if file_input is not None:
119
+ ext = os.path.splitext(file_input)[1].lower()
120
+ if ext == ".pdf":
121
+ try:
122
+ import pypdf
123
+ reader = pypdf.PdfReader(file_input)
124
+ return "\n\n".join(p.extract_text().strip() for p in reader.pages if p.extract_text())
125
+ except Exception as e:
126
+ raise gr.Error(f"PDF read failed: {e}")
127
+ elif ext == ".docx":
128
+ try:
129
+ import docx
130
+ doc = docx.Document(file_input)
131
+ return "\n\n".join(p.text.strip() for p in doc.paragraphs if p.text.strip())
132
+ except Exception as e:
133
+ raise gr.Error(f"DOCX read failed: {e}")
134
+ else:
135
+ with open(file_input, "r", encoding="utf-8", errors="replace") as f:
136
+ return f.read()
137
+ elif text_input and text_input.strip():
138
+ return text_input.strip()
139
+ else:
140
+ raise gr.Error("Please enter text or upload a file.")
141
+
142
+
143
  # ==========================================
144
  # SINGLE-SPEAKER MODES
145
  # ==========================================
146
  @spaces.GPU
147
+ def generate_custom_voice(text, file_input, language, speaker_label, instruction):
148
+ resolved_text = resolve_text(text, file_input)
 
149
  model = get_model("custom")
150
  speaker = speaker_label.split("--")[0].strip()
151
  lang = language if language != "Auto" else "Auto"
152
+ kwargs = {"text": resolved_text, "language": lang, "speaker": speaker}
153
  if instruction and instruction.strip():
154
  kwargs["instruct"] = instruction.strip()
155
  print(f"[TTS] Custom: speaker={speaker}, lang={lang}")
 
160
 
161
 
162
  @spaces.GPU
163
+ def generate_voice_design(text, file_input, language, voice_description):
164
+ resolved_text = resolve_text(text, file_input)
 
165
  if not voice_description.strip():
166
  raise gr.Error("Please describe the voice you want.")
167
  model = get_model("design")
168
  lang = language if language != "Auto" else "Auto"
169
  print(f"[TTS] Design: lang={lang}, desc={voice_description[:60]}")
170
+ wavs, sr = model.generate_voice_design(text=resolved_text, language=lang, instruct=voice_description)
171
  path = os.path.join(OUTPUT_DIR, f"design_{int(time.time())}.wav")
172
  sf.write(path, wavs[0], sr)
173
  return path
 
272
 
273
 
274
  @spaces.GPU
275
+ def generate_voice_clone(text, file_input, language, ref_audio, ref_text, add_emotions):
276
+ resolved_text = resolve_text(text, file_input)
 
277
  if ref_audio is None:
278
  raise gr.Error("Please upload a reference audio sample.")
279
 
280
  # Enhance text with emotions if requested
281
+ final_text = resolved_text
282
  if add_emotions:
283
  client = get_llm_client()
284
  if client:
 
601
  gr.Markdown("Pick a preset speaker with optional emotion/style.")
602
  with gr.Row():
603
  with gr.Column():
604
+ cv_text = gr.Textbox(label="Text", lines=4, placeholder="Enter text or upload a file below...")
605
+ cv_file = gr.File(label="Or Upload (.txt, .pdf, .docx)",
606
+ file_types=[".txt", ".md", ".pdf", ".docx"], type="filepath")
607
  cv_lang = gr.Dropdown(choices=LANGUAGES, value="Auto", label="Language")
608
  cv_speaker = gr.Dropdown(choices=SPEAKER_CHOICES,
609
  value="Ryan -- Dynamic male, strong rhythmic drive (English)",
 
614
  with gr.Column():
615
  cv_audio = gr.Audio(label="Generated Speech", type="filepath")
616
  cv_btn.click(fn=generate_custom_voice,
617
+ inputs=[cv_text, cv_file, cv_lang, cv_speaker, cv_instruct], outputs=cv_audio)
618
 
619
  # ── Tab 2: Voice Design ──
620
  with gr.Tab("Voice Design"):
621
  gr.Markdown("Describe the voice you want β€” the AI creates it.")
622
  with gr.Row():
623
  with gr.Column():
624
+ vd_text = gr.Textbox(label="Text", lines=4, placeholder="Enter text or upload a file below...")
625
+ vd_file = gr.File(label="Or Upload (.txt, .pdf, .docx)",
626
+ file_types=[".txt", ".md", ".pdf", ".docx"], type="filepath")
627
  vd_lang = gr.Dropdown(choices=LANGUAGES, value="English", label="Language")
628
  vd_desc = gr.Textbox(label="Voice Description", lines=3,
629
  placeholder="e.g. Warm male storyteller with British accent...")
 
641
  with gr.Column():
642
  vd_audio = gr.Audio(label="Generated Speech", type="filepath")
643
  vd_btn.click(fn=generate_voice_design,
644
+ inputs=[vd_text, vd_file, vd_lang, vd_desc], outputs=vd_audio)
645
 
646
  # ── Tab 3: Voice Clone ──
647
  with gr.Tab("Voice Clone"):
 
651
  )
652
  with gr.Row():
653
  with gr.Column():
654
+ vc_text = gr.Textbox(label="Text (in cloned voice)", lines=4, placeholder="Enter text or upload a file below...")
655
+ vc_file = gr.File(label="Or Upload (.txt, .pdf, .docx)",
656
+ file_types=[".txt", ".md", ".pdf", ".docx"], type="filepath")
657
  vc_lang = gr.Dropdown(choices=LANGUAGES, value="English", label="Language")
658
  vc_ref = gr.Audio(label="Reference Audio (3+ seconds)", type="filepath")
659
  vc_ref_text = gr.Textbox(label="Transcript (optional, improves quality)",
660
  placeholder="What the person says in the reference...")
661
  vc_emotions = gr.Checkbox(value=False, label="Enhance with emotions",
662
+ info="AI adds natural emotional cues. Requires DASHSCOPE_API_KEY.")
663
  vc_btn = gr.Button("Clone & Generate", variant="primary")
664
  with gr.Column():
665
  vc_audio = gr.Audio(label="Cloned Voice Speech", type="filepath")
666
  vc_btn.click(fn=generate_voice_clone,
667
+ inputs=[vc_text, vc_file, vc_lang, vc_ref, vc_ref_text, vc_emotions], outputs=vc_audio)
668
 
669
  # ── Tab 4: Multi-Speaker Story ──
670
  with gr.Tab("Multi-Speaker Story"):