sg123321 commited on
Commit
1dd5ac4
·
verified ·
1 Parent(s): c0b8023

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -59
app.py CHANGED
@@ -1,87 +1,164 @@
 
1
  import uuid
2
  import gradio as gr
3
  import torch
4
  import spaces
5
  from TTS.api import TTS
6
  from supabase import create_client, Client
 
7
 
8
- # 👇 यहाँ हमने आपकी नई अलग फाइल को इंपोर्ट किया
9
- import config
10
-
11
- # 1. Setup Supabase (Using config file)
12
  supabase = None
13
  if config.IS_CONNECTED:
14
  try:
15
  supabase: Client = create_client(config.SUPABASE_URL, config.SUPABASE_KEY)
16
- print("✅ Supabase Client Connected!")
17
  except Exception as e:
18
- print(f"❌ Connection Error: {e}")
19
 
20
- # 2. Terms & Model Setup
21
- import os
22
  os.environ["COQUI_TOS_AGREED"] = "1"
23
  device = "cuda" if torch.cuda.is_available() else "cpu"
24
- print(f"⚙️ Device: {device}")
25
-
26
- print("⏳ Loading XTTS Model...")
27
  tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2").to(device)
28
 
29
- # 3. Main Logic
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  @spaces.GPU(duration=120)
31
- def clone_voice(text, language, speaker_audio):
32
- if not text or not speaker_audio:
33
- return None, "Error: Text or Audio missing"
34
 
35
- filename = f"generated_{uuid.uuid4()}.wav"
36
- output_path = "output.wav"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
- # A. Generate Audio
39
- print("🎙️ Generating...")
40
  tts.tts_to_file(
41
  text=text,
42
  file_path=output_path,
43
- speaker_wav=speaker_audio,
44
  language=language
45
  )
46
 
47
- # B. Upload using Config vars
48
- storage_url = "Not Saved"
49
- if supabase:
50
- try:
51
- with open(output_path, 'rb') as f:
52
- supabase.storage.from_("voice-bucket").upload(filename, f)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
- # URL बनाना
55
- storage_url = f"{config.SUPABASE_URL}/storage/v1/object/public/voice-bucket/{filename}"
56
- print(f" Uploaded: {storage_url}")
57
-
58
- # Database Entry
59
- data = {
60
- "name": f"Clone_{language}",
61
- "file_path": storage_url,
62
- "ref_text": text
63
- }
64
- supabase.table("clones").insert(data).execute()
65
 
66
- except Exception as e:
67
- print(f" Error: {e}")
68
- storage_url = f"Error: {e}"
69
-
70
- return output_path, storage_url
71
-
72
- # 4. Interface
73
- with gr.Interface(
74
- fn=clone_voice,
75
- inputs=[
76
- gr.Textbox(label="Text", value="Config file test successful!", lines=2),
77
- gr.Dropdown(label="Language", choices=["hi", "en"], value="hi"),
78
- gr.Audio(label="Audio", type="filepath")
79
- ],
80
- outputs=[
81
- gr.Audio(label="Result"),
82
- gr.Textbox(label="Cloud Link")
83
- ],
84
- title="🚀 Shubham's Clean Code XTTS",
85
- description="Running with separate config file."
86
- ) as iface:
87
- iface.launch(server_name="0.0.0.0", server_port=7860)
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
  import uuid
3
  import gradio as gr
4
  import torch
5
  import spaces
6
  from TTS.api import TTS
7
  from supabase import create_client, Client
8
+ import config # आपकी config file
9
 
10
+ # 1. Supabase Connection
 
 
 
11
  supabase = None
12
  if config.IS_CONNECTED:
13
  try:
14
  supabase: Client = create_client(config.SUPABASE_URL, config.SUPABASE_KEY)
15
+ print("✅ Supabase Connected!")
16
  except Exception as e:
17
+ print(f"❌ Supabase Error: {e}")
18
 
19
+ # 2. Model Setup
 
20
  os.environ["COQUI_TOS_AGREED"] = "1"
21
  device = "cuda" if torch.cuda.is_available() else "cpu"
22
+ print(f" Loading XTTS Model on {device}...")
 
 
23
  tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2").to(device)
24
 
25
+ # --- Helper Functions ---
26
+
27
+ def get_voice_list():
28
+ """Supabase Bucket से फाइलों की लिस्ट लाता है"""
29
+ if not supabase: return []
30
+ try:
31
+ # 'voice-bucket' से सारी फाइलें लाना
32
+ res = supabase.storage.from_("voice-bucket").list()
33
+ # सिर्फ ऑडियो फाइलें छांटना
34
+ files = [f['name'] for f in res if f['name'].endswith(('.wav', '.mp3'))]
35
+ return files
36
+ except Exception as e:
37
+ print(f"List Error: {e}")
38
+ return []
39
+
40
+ def download_cloud_voice(filename):
41
+ """क्लाउड से फाइल डाउनलोड करके temp फोल्डर में रखता है"""
42
+ local_path = f"temp_{filename}"
43
+ with open(local_path, 'wb+') as f:
44
+ res = supabase.storage.from_("voice-bucket").download(filename)
45
+ f.write(res)
46
+ return local_path
47
+
48
+ # --- Main Logic ---
49
+
50
  @spaces.GPU(duration=120)
51
+ def generate_preview(text, language, upload_voice, cloud_voice_name):
52
+ # 1. Voice Selection Logic (Upload को पहली प्राथमिकता)
53
+ speaker_wav = None
54
 
55
+ if upload_voice is not None:
56
+ print("🎙️ Using Uploaded Voice")
57
+ speaker_wav = upload_voice
58
+ elif cloud_voice_name:
59
+ print(f"☁️ Using Cloud Voice: {cloud_voice_name}")
60
+ try:
61
+ speaker_wav = download_cloud_voice(cloud_voice_name)
62
+ except Exception as e:
63
+ return None, f"Error downloading voice: {e}"
64
+ else:
65
+ return None, "⚠️ Please upload a voice OR select one from Cloud!"
66
+
67
+ # 2. Preview Logic (Delete Previous / Overwrite)
68
+ # हम हमेशा एक ही नाम 'preview.wav' यूज़ करेंगे।
69
+ # इससे जब भी नया ऑडियो बनेगा, पुराना वाला अपने आप मिट जाएगा।
70
+ output_path = "preview.wav"
71
 
72
+ print("🔄 Generating Preview...")
 
73
  tts.tts_to_file(
74
  text=text,
75
  file_path=output_path,
76
+ speaker_wav=speaker_wav,
77
  language=language
78
  )
79
 
80
+ return output_path, "✅ Preview Ready! Save karne ke liye neeche button dabayein."
81
+
82
+ def save_to_cloud(preview_path, text, language):
83
+ """सिर्फ तब सेव करेगा जब यूजर चाहेगा"""
84
+ if not preview_path or not os.path.exists(preview_path):
85
+ return "⚠️ No preview found! Pehle 'Generate Preview' karein."
86
+
87
+ if not supabase:
88
+ return "❌ Supabase not connected!"
89
+
90
+ # फाइल का नया यूनिक नाम
91
+ filename = f"final_{language}_{uuid.uuid4()}.wav"
92
+
93
+ try:
94
+ print("☁️ Uploading to Supabase...")
95
+ with open(preview_path, 'rb') as f:
96
+ supabase.storage.from_("voice-bucket").upload(filename, f)
97
+
98
+ # पब्लिक लिंक
99
+ storage_url = f"{config.SUPABASE_URL}/storage/v1/object/public/voice-bucket/{filename}"
100
+
101
+ # डेटाबेस एंट्री
102
+ data = {
103
+ "name": f"Clone_{language}",
104
+ "file_path": storage_url,
105
+ "ref_text": text
106
+ }
107
+ supabase.table("clones").insert(data).execute()
108
+
109
+ return f"🎉 Saved Successfully! Link: {storage_url}"
110
+ except Exception as e:
111
+ return f"❌ Save Error: {e}"
112
+
113
+ # --- UI Layout (Blocks) ---
114
+ with gr.Blocks(title="Shubham's Ultimate Voice Cloner") as app:
115
+ gr.Markdown("## 🚀 XTTS Voice Cloning (With Preview & Cloud Select)")
116
+
117
+ with gr.Row():
118
+ # Text Input Area
119
+ with gr.Column():
120
+ txt_input = gr.Textbox(label="Text to Speak", lines=3, value="Namaste, main ab preview lekar cloud par save ho sakta hoon.")
121
+ lang_dropdown = gr.Dropdown(label="Language", choices=["hi", "en", "es", "fr"], value="hi")
122
 
123
+ # Voice Selection Area
124
+ with gr.Column():
125
+ gr.Markdown("### 🎤 Select Voice Source")
126
+ # Tab 1: Upload
127
+ voice_upload = gr.Audio(label="Option A: Upload New Voice", type="filepath")
128
+ # Tab 2: Cloud Select
129
+ voice_dropdown = gr.Dropdown(label="Option B: Choose from Supabase", choices=get_voice_list(), interactive=True)
130
+ refresh_btn = gr.Button("🔄 Refresh Cloud List") # लिस्ट रिफ्रेश करने के लिए
 
 
 
131
 
132
+ # Action Buttons
133
+ btn_preview = gr.Button("🔊 Generate Preview (Wait for it...)", variant="primary")
134
+
135
+ # Output Area
136
+ audio_output = gr.Audio(label="Preview Audio (Temporary)")
137
+ status_msg = gr.Textbox(label="Status", interactive=False)
138
+
139
+ # Save Button (Preview ke baad dabana hai)
140
+ btn_save = gr.Button("☁️ Save this to Supabase", variant="secondary")
141
+
142
+ # --- Click Events ---
143
+
144
+ # 1. Refresh Button Logic
145
+ def refresh_list():
146
+ return gr.Dropdown(choices=get_voice_list())
147
+ refresh_btn.click(refresh_list, outputs=voice_dropdown)
148
+
149
+ # 2. Preview Generation
150
+ btn_preview.click(
151
+ fn=generate_preview,
152
+ inputs=[txt_input, lang_dropdown, voice_upload, voice_dropdown],
153
+ outputs=[audio_output, status_msg]
154
+ )
155
+
156
+ # 3. Save to Cloud
157
+ btn_save.click(
158
+ fn=save_to_cloud,
159
+ inputs=[audio_output, txt_input, lang_dropdown],
160
+ outputs=status_msg
161
+ )
162
+
163
+ if __name__ == "__main__":
164
+ app.launch(server_name="0.0.0.0", server_port=7860)