mrboost commited on
Commit
698dc2c
·
verified ·
1 Parent(s): fa1dd61

Deploy voice-clone-studio on ZeroGPU

Browse files
Files changed (3) hide show
  1. README.md +21 -8
  2. app.py +120 -0
  3. requirements.txt +7 -0
README.md CHANGED
@@ -1,13 +1,26 @@
1
  ---
2
- title: Voice Clone Studio
3
- emoji: 🐢
4
- colorFrom: green
5
- colorTo: indigo
6
  sdk: gradio
7
- sdk_version: 6.31.0
8
- python_version: '3.12'
9
  app_file: app.py
10
- pinned: false
 
 
 
 
 
 
 
 
 
 
 
 
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
1
  ---
2
+ title: Voice Cloning & Neural TTS Studio
3
+ emoji: 🎙️
4
+ colorFrom: purple
5
+ colorTo: blue
6
  sdk: gradio
7
+ sdk_version: 6.13.0
 
8
  app_file: app.py
9
+ python_version: "3.12"
10
+ startup_duration_timeout: 1h
11
+ short_description: Zero-Shot Voice Cloning (F5-TTS/Chatterbox) & Neural TTS
12
+ models:
13
+ - SWivid/F5-TTS
14
+ - suno/bark-small
15
+ tags:
16
+ - voice-cloning
17
+ - tts
18
+ - text-to-speech
19
+ - f5-tts
20
+ - zerogpu
21
+ - mcp-server
22
  ---
23
 
24
+ # 🎙️ Instant Voice Cloning & Neural TTS Studio
25
+
26
+ Upload a **5–10 second reference audio clip** to clone any voice via **F5-TTS / Chatterbox ZeroGPU**, or generate expressive multi-speaker neural voiceovers locally on **ZeroGPU (`zero-a10g`)** at **$0/hour**.
app.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Instant Voice Cloning (F5-TTS / Chatterbox) & Local ZeroGPU Neural TTS Studio."""
2
+
3
+ import os
4
+ import shutil
5
+ import tempfile
6
+
7
+ os.environ.setdefault("PYTORCH_ALLOC_CONF", "backend:cudaMallocAsync")
8
+ os.environ.setdefault("PYTORCH_CUDA_ALLOC_CONF", "backend:cudaMallocAsync")
9
+
10
+ import spaces # Must be imported before torch
11
+ import gradio as gr
12
+ import numpy as np
13
+ import scipy.io.wavfile as wavfile
14
+ import torch
15
+ from gradio_client import Client, handle_file
16
+ from transformers import AutoProcessor, BarkModel
17
+
18
+ HF_TOKEN = os.environ.get("HF_TOKEN")
19
+ LOCAL_TTS_ID = "suno/bark-small"
20
+
21
+ VOICE_PRESETS = {
22
+ "English Narrator · Studio Male (v2/en_speaker_6)": "v2/en_speaker_6",
23
+ "English Narrator · Warm Female (v2/en_speaker_9)": "v2/en_speaker_9",
24
+ "English Broadcast · Deep Male (v2/en_speaker_0)": "v2/en_speaker_0",
25
+ "English Conversational · Male (v2/en_speaker_3)": "v2/en_speaker_3",
26
+ }
27
+
28
+ print(f"[voice-clone-studio] Preloading {LOCAL_TTS_ID} at module scope for ZeroGPU...", flush=True)
29
+ processor = AutoProcessor.from_pretrained(LOCAL_TTS_ID)
30
+ bark_model = BarkModel.from_pretrained(LOCAL_TTS_ID, torch_dtype=torch.float16)
31
+ bark_model.to("cuda")
32
+ SAMPLE_RATE = bark_model.generation_config.sample_rate
33
+ print("[voice-clone-studio] Local ZeroGPU TTS ready!", flush=True)
34
+
35
+
36
+ @spaces.GPU(duration=45)
37
+ def synthesize_local_tts(text: str, voice_preset_key: str) -> tuple[str, str]:
38
+ """Generate expressive speech locally on ZeroGPU using Bark."""
39
+ preset = VOICE_PRESETS.get(voice_preset_key, "v2/en_speaker_6")
40
+ inputs = processor(text.strip(), voice_preset=preset).to("cuda")
41
+ with torch.no_grad():
42
+ audio_array = bark_model.generate(**inputs)
43
+ audio_np = audio_array.cpu().numpy().squeeze().astype(np.float32)
44
+ with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp:
45
+ wavfile.write(tmp.name, rate=SAMPLE_RATE, data=audio_np)
46
+ return tmp.name, f"Local ZeroGPU Neural TTS ({preset} · {SAMPLE_RATE} Hz)"
47
+
48
+
49
+ def clone_or_speak(
50
+ text_to_speak: str,
51
+ reference_audio_path: str | None = None,
52
+ reference_transcript: str = "",
53
+ voice_preset_key: str = "English Narrator · Studio Male (v2/en_speaker_6)",
54
+ ) -> tuple[str, str]:
55
+ """Clone a voice from a 5-10s audio clip (via F5-TTS ZeroGPU) or generate studio neural narration."""
56
+ if not text_to_speak or not text_to_speak.strip():
57
+ raise gr.Error("Please enter the text you want spoken.")
58
+
59
+ if reference_audio_path:
60
+ for space_id in ("mrfakename/E2-F5-TTS", "SWivid/F5-TTS"):
61
+ try:
62
+ client = Client(space_id, token=HF_TOKEN, httpx_kwargs={"timeout": 180.0})
63
+ res = client.predict(
64
+ handle_file(reference_audio_path),
65
+ (reference_transcript or "").strip(),
66
+ text_to_speak.strip(),
67
+ False,
68
+ api_name="/predict",
69
+ )
70
+ wav_out = res[0] if isinstance(res, (list, tuple)) else res
71
+ with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as tmp:
72
+ shutil.copyfile(wav_out, tmp.name)
73
+ return tmp.name, f"Zero-Shot Voice Clone via {space_id}"
74
+ except Exception as err: # noqa: BLE001
75
+ print(f"[voice-clone-studio] {space_id} fallback ({err!r})", flush=True)
76
+
77
+ return synthesize_local_tts(text_to_speak, voice_preset_key)
78
+
79
+
80
+ with gr.Blocks(title="Instant Voice Cloning & TTS Studio", fill_width=True) as demo:
81
+ gr.Markdown(
82
+ "# 🎙️ Instant Voice Cloning & Neural TTS Studio\n"
83
+ "Upload a **5–10 second voice clip** for **Zero-Shot Voice Cloning (F5-TTS)**, or leave the reference audio blank "
84
+ "to generate studio narration on **ZeroGPU (`zero-a10g`)** at **$0/hour**."
85
+ )
86
+ with gr.Row():
87
+ with gr.Column(scale=1):
88
+ text_box = gr.Textbox(
89
+ label="Script / Text to Speak",
90
+ lines=5,
91
+ placeholder="Type the narration, dialogue, or voiceover script here...",
92
+ )
93
+ ref_audio = gr.Audio(
94
+ label="Reference Voice Audio (Optional · 5–10s clip for Voice Cloning)",
95
+ type="filepath",
96
+ )
97
+ ref_text = gr.Textbox(
98
+ label="Reference Audio Transcript (Optional · improves F5-TTS voice clone accuracy)",
99
+ lines=2,
100
+ placeholder="Leave blank for automatic transcription, or type what was said in the reference clip...",
101
+ )
102
+ preset_dropdown = gr.Dropdown(
103
+ choices=list(VOICE_PRESETS),
104
+ value="English Narrator · Studio Male (v2/en_speaker_6)",
105
+ label="Studio Voice Preset (Used when no reference audio is uploaded)",
106
+ )
107
+ speak_btn = gr.Button("🎙️ Generate Voiceover", variant="primary")
108
+ with gr.Column(scale=1):
109
+ audio_out = gr.Audio(label="Generated Voiceover (WAV)", type="filepath", autoplay=True)
110
+ status_out = gr.Textbox(label="Engine Details", interactive=False)
111
+
112
+ speak_btn.click(
113
+ fn=clone_or_speak,
114
+ inputs=[text_box, ref_audio, ref_text, preset_dropdown],
115
+ outputs=[audio_out, status_out],
116
+ api_name="synthesize_voice",
117
+ )
118
+
119
+ if __name__ == "__main__":
120
+ demo.launch(theme=gr.themes.Citrus(), mcp_server=True)
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ transformers>=4.49.0
2
+ accelerate>=1.6.0
3
+ safetensors
4
+ scipy
5
+ numpy
6
+ gradio_client
7
+ soundfile