PlotweaverModel commited on
Commit
ba5a437
·
verified ·
1 Parent(s): 0ff5f89

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +11 -16
app.py CHANGED
@@ -8,6 +8,7 @@ import os
8
  import json
9
  import re
10
  import tempfile
 
11
  import subprocess
12
  import shutil
13
  import struct
@@ -32,6 +33,10 @@ except ImportError:
32
  OMNI_MODEL = "qwen3.5-omni-plus"
33
  DASHSCOPE_BASE_URL = "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
34
 
 
 
 
 
35
  LANGUAGES = ["Auto", "English", "Chinese", "Japanese", "Korean", "German",
36
  "French", "Russian", "Portuguese", "Spanish", "Italian"]
37
 
@@ -120,7 +125,7 @@ def generate_custom_voice(text, language, speaker_label, instruction):
120
  kwargs["instruct"] = instruction.strip()
121
  print(f"[TTS] Custom: speaker={speaker}, lang={lang}")
122
  wavs, sr = model.generate_custom_voice(**kwargs)
123
- path = os.path.join(tempfile.mkdtemp(), "custom.wav")
124
  sf.write(path, wavs[0], sr)
125
  return path
126
 
@@ -135,7 +140,7 @@ def generate_voice_design(text, language, voice_description):
135
  lang = language if language != "Auto" else "Auto"
136
  print(f"[TTS] Design: lang={lang}, desc={voice_description[:60]}")
137
  wavs, sr = model.generate_voice_design(text=text, language=lang, instruct=voice_description)
138
- path = os.path.join(tempfile.mkdtemp(), "design.wav")
139
  sf.write(path, wavs[0], sr)
140
  return path
141
 
@@ -155,7 +160,7 @@ def generate_voice_clone(text, language, ref_audio, ref_text):
155
  kwargs["x_vector_only_mode"] = True
156
  print(f"[TTS] Clone: lang={lang}")
157
  wavs, sr = model.generate_voice_clone(**kwargs)
158
- path = os.path.join(tempfile.mkdtemp(), "clone.wav")
159
  sf.write(path, wavs[0], sr)
160
  return path
161
 
@@ -299,7 +304,8 @@ def generate_multi_speaker_story(text_input, file_input, language, progress=gr.P
299
  "Add it in Settings > Secrets."
300
  )
301
 
302
- tmp_dir = tempfile.mkdtemp(prefix="multispeaker_")
 
303
 
304
  # Step 1: Detect characters and emotions
305
  progress(0.05, desc="Analyzing story characters and emotions...")
@@ -439,16 +445,7 @@ The old man was silent for a long time. "I already did," he finally whispered. "
439
 
440
  DESCRIPTION = """
441
  # Qwen3-TTS Demo
442
- ### Open-Source Text-to-Speech (1.7B) — Self-Hosted, No API Keys for TTS
443
-
444
- | Mode | What it does |
445
- |------|-------------|
446
- | **Custom Voice** | Pick a preset voice + optional emotion instruction |
447
- | **Voice Design** | Describe any voice in natural language |
448
- | **Voice Clone** | Clone a voice from 3 seconds of audio |
449
- | **Multi-Speaker Story** | Auto-detect characters, assign voices, add emotions — full audiobook |
450
 
451
- 10 languages supported. Running on ZeroGPU (free).
452
  """
453
 
454
  with gr.Blocks(title="Qwen3-TTS Demo") as demo:
@@ -545,11 +542,9 @@ with gr.Blocks(title="Qwen3-TTS Demo") as demo:
545
 
546
  gr.Markdown(
547
  "---\n"
548
- "**Models:** Qwen3-TTS-12Hz-1.7B (Apache 2.0) | "
549
  "**Languages:** EN, ZH, JA, KO, DE, FR, RU, PT, ES, IT | "
550
- "**TTS:** Self-hosted on ZeroGPU | "
551
  "**Character Analysis:** Cloud AI (optional, for Multi-Speaker mode)"
552
  )
553
 
554
  if __name__ == "__main__":
555
- demo.launch()
 
8
  import json
9
  import re
10
  import tempfile
11
+ import time
12
  import subprocess
13
  import shutil
14
  import struct
 
33
  OMNI_MODEL = "qwen3.5-omni-plus"
34
  DASHSCOPE_BASE_URL = "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
35
 
36
+ # Persistent output directory (survives between requests)
37
+ OUTPUT_DIR = os.path.join(tempfile.gettempdir(), "qwen3_tts_outputs")
38
+ os.makedirs(OUTPUT_DIR, exist_ok=True)
39
+
40
  LANGUAGES = ["Auto", "English", "Chinese", "Japanese", "Korean", "German",
41
  "French", "Russian", "Portuguese", "Spanish", "Italian"]
42
 
 
125
  kwargs["instruct"] = instruction.strip()
126
  print(f"[TTS] Custom: speaker={speaker}, lang={lang}")
127
  wavs, sr = model.generate_custom_voice(**kwargs)
128
+ path = os.path.join(OUTPUT_DIR, f"custom_{int(time.time())}.wav")
129
  sf.write(path, wavs[0], sr)
130
  return path
131
 
 
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
146
 
 
160
  kwargs["x_vector_only_mode"] = True
161
  print(f"[TTS] Clone: lang={lang}")
162
  wavs, sr = model.generate_voice_clone(**kwargs)
163
+ path = os.path.join(OUTPUT_DIR, f"clone_{int(time.time())}.wav")
164
  sf.write(path, wavs[0], sr)
165
  return path
166
 
 
304
  "Add it in Settings > Secrets."
305
  )
306
 
307
+ tmp_dir = os.path.join(OUTPUT_DIR, f"ms_{int(time.time())}")
308
+ os.makedirs(tmp_dir, exist_ok=True)
309
 
310
  # Step 1: Detect characters and emotions
311
  progress(0.05, desc="Analyzing story characters and emotions...")
 
445
 
446
  DESCRIPTION = """
447
  # Qwen3-TTS Demo
 
 
 
 
 
 
 
 
448
 
 
449
  """
450
 
451
  with gr.Blocks(title="Qwen3-TTS Demo") as demo:
 
542
 
543
  gr.Markdown(
544
  "---\n"
 
545
  "**Languages:** EN, ZH, JA, KO, DE, FR, RU, PT, ES, IT | "
 
546
  "**Character Analysis:** Cloud AI (optional, for Multi-Speaker mode)"
547
  )
548
 
549
  if __name__ == "__main__":
550
+ demo.launch(allowed_paths=[OUTPUT_DIR])