File size: 8,603 Bytes
1dd5ac4 5de0578 c0b8023 3767dfa b629f13 5de0578 b629f13 c0b8023 1dd5ac4 c0b8023 1dd5ac4 9c8f593 b629f13 c0b8023 5de0578 1dd5ac4 5de0578 b629f13 1dd5ac4 b629f13 1dd5ac4 b629f13 1dd5ac4 b629f13 1dd5ac4 b629f13 1dd5ac4 b629f13 1dd5ac4 b629f13 1dd5ac4 b629f13 c0b8023 b629f13 1dd5ac4 b629f13 1dd5ac4 b629f13 1dd5ac4 b629f13 1dd5ac4 b629f13 1dd5ac4 b629f13 1dd5ac4 3767dfa b629f13 3767dfa | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | import os
import gradio as gr
import torch
import spaces
from TTS.api import TTS
from supabase import create_client, Client
import config
import uuid
# --- 1. Supabase Connection & Setup ---
supabase = None
if config.IS_CONNECTED:
try:
supabase: Client = create_client(config.SUPABASE_URL, config.SUPABASE_KEY)
print("✅ Supabase Connected!")
except Exception as e:
print(f"❌ Supabase Error: {e}")
# Model Setup
os.environ["COQUI_TOS_AGREED"] = "1"
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"⏳ Loading XTTS Model on {device}...")
tts = TTS("tts_models/multilingual/multi-dataset/xtts_v2").to(device)
BUCKET_NAME = "voice-bucket"
# --- Helper Functions ---
def get_file_list():
"""Supabase se saari audio files ki list layega"""
if not supabase: return []
try:
res = supabase.storage.from_(BUCKET_NAME).list()
# Sirf wav/mp3 files filter karein
files = [f['name'] for f in res if f['name'].endswith(('.wav', '.mp3'))]
return sorted(files)
except Exception as e:
print(f"List Error: {e}")
return []
def get_public_url(filename):
"""File ka direct link banayega sunne ke liye"""
if not supabase: return None
return f"{config.SUPABASE_URL}/storage/v1/object/public/{BUCKET_NAME}/{filename}"
def download_voice(filename):
"""Generate karne ke liye file download karega"""
local_path = f"temp_{filename}"
with open(local_path, 'wb+') as f:
res = supabase.storage.from_(BUCKET_NAME).download(filename)
f.write(res)
return local_path
# --- CORE FUNCTIONS (Tabs Logic) ---
# TAB 1: Generate
@spaces.GPU(duration=120)
def generate_audio(text, language, selected_voice):
if not selected_voice:
return None, "⚠️ पहले कोई आवाज़ (Sample) चुनें!"
try:
speaker_wav = download_voice(selected_voice)
output_path = "output.wav"
tts.tts_to_file(
text=text,
file_path=output_path,
speaker_wav=speaker_wav,
language=language
)
return output_path, "✅ ऑडियो तैयार है!"
except Exception as e:
return None, f"❌ Error: {e}"
# TAB 2: Save New Sample
def save_new_sample(audio_file, custom_name):
if not supabase: return "❌ Database connect nahi hai."
if not audio_file: return "⚠️ ऑडियो फाइल नहीं मिली।"
if not custom_name: return "⚠️ कृपया आवाज़ का नाम लिखें।"
# Filename clean karein (spaces hata kar)
clean_name = custom_name.strip().replace(" ", "_")
filename = f"{clean_name}.wav"
try:
with open(audio_file, 'rb') as f:
supabase.storage.from_(BUCKET_NAME).upload(filename, f)
return f"🎉 '{filename}' सेव हो गया! अब आप इसे Home टैब में चुन सकते हैं।"
except Exception as e:
return f"❌ Error: शायद इस नाम की फाइल पहले से है. ({e})"
# TAB 3: Manage (Delete/Rename/Preview)
def update_library_view():
"""Library refresh karega"""
files = get_file_list()
return gr.Dropdown(choices=files, value=files[0] if files else None), "📂 लिस्ट अपडेटेड"
def load_file_preview(filename):
"""Select karte hi audio sunayega"""
if not filename: return None
return get_public_url(filename)
def delete_sample(filename):
if not supabase or not filename: return "⚠️ कुछ सेलेक्ट नहीं किया।"
try:
supabase.storage.from_(BUCKET_NAME).remove([filename])
return "🗑️ फाइल डिलीट हो गई!"
except Exception as e:
return f"❌ Delete Error: {e}"
def rename_sample(old_name, new_name):
if not supabase or not old_name or not new_name: return "⚠️ नाम सही नहीं है।"
clean_new = new_name.strip().replace(" ", "_")
if not clean_new.endswith(".wav"): clean_new += ".wav"
try:
supabase.storage.from_(BUCKET_NAME).move(old_name, clean_new)
return f"✏️ नाम बदलकर '{clean_new}' हो गया!"
except Exception as e:
return f"❌ Rename Error: {e}"
# --- UI LAYOUT (Tabs Style) ---
with gr.Blocks(title="My Voice AI", theme=gr.themes.Soft()) as app:
gr.Markdown("## 🎙️ My Hindi Voice Studio")
with gr.Tabs():
# --- TAB 1: HOME (GENERATE) ---
with gr.TabItem("🏠 Home (Generate)"):
with gr.Row():
voice_selector = gr.Dropdown(
label="1. आवाज़ चुनें (Sample Voice)",
choices=get_file_list(),
interactive=True
)
refresh_home_btn = gr.Button("🔄 रिफ्रेश लिस्ट", size="sm")
with gr.Row():
txt_input = gr.Textbox(label="2. क्या बुलवाना है? (Text)", lines=3, placeholder="नमस्ते, आप कैसे हैं?")
lang_drop = gr.Dropdown(label="भाषा (Language)", choices=["hi", "en"], value="hi")
gen_btn = gr.Button("🚀 आवाज़ बनाओ (Generate)", variant="primary")
with gr.Row():
audio_out = gr.Audio(label="Result")
status_home = gr.Textbox(label="Status")
# Events
refresh_home_btn.click(lambda: gr.Dropdown(choices=get_file_list()), outputs=voice_selector)
gen_btn.click(generate_audio, [txt_input, lang_drop, voice_selector], [audio_out, status_home])
# --- TAB 2: ADD NEW VOICE ---
with gr.TabItem("➕ Add Sample (Save)"):
gr.Markdown("अपनी या किसी की भी आवाज़ सेव करें ताकि बाद में यूज़ कर सकें।")
new_audio = gr.Audio(label="आवाज़ रिकॉर्ड करें या अपलोड करें", type="filepath")
new_name = gr.Textbox(label="इस आवाज़ का नाम (Example: Meri_Awaz)", placeholder="Naam likhein...")
save_btn = gr.Button("💾 सेव करें (Save to Cloud)", variant="primary")
status_save = gr.Textbox(label="Status")
save_btn.click(save_new_sample, [new_audio, new_name], status_save)
# --- TAB 3: MY LIBRARY (LIST/EDIT) ---
with gr.TabItem("📂 My Library"):
gr.Markdown("यहाँ आपकी सारी सेव की हुई आवाज़ें हैं।")
with gr.Row():
lib_dropdown = gr.Dropdown(label="फाइल चुनें", choices=get_file_list(), interactive=True)
refresh_lib_btn = gr.Button("🔄 रिफ्रेश", size="sm")
preview_player = gr.Audio(label="Preview (सुनें)")
with gr.Accordion("🛠️ Edit / Delete Options", open=False):
with gr.Row():
rename_txt = gr.Textbox(label="नया नाम (New Name)", placeholder="New_Name.wav")
rename_btn = gr.Button("✏️ नाम बदलें (Rename)")
delete_btn = gr.Button("🗑️ हमेशा के लिए डिलीट करें (Delete)", variant="stop")
status_lib = gr.Textbox(label="Status")
# Events
# Select karte hi play karega
lib_dropdown.change(load_file_preview, lib_dropdown, preview_player)
# Buttons Logic
refresh_lib_btn.click(update_library_view, None, [lib_dropdown, status_lib])
delete_btn.click(delete_sample, lib_dropdown, status_lib).then(
update_library_view, None, [lib_dropdown, status_lib]
)
rename_btn.click(rename_sample, [lib_dropdown, rename_txt], status_lib).then(
update_library_view, None, [lib_dropdown, status_lib]
)
# Login System
if __name__ == "__main__":
app.launch(
auth=(config.APP_USER, config.APP_PASS),
server_name="0.0.0.0",
server_port=7860
) |