xtts67 / app.py
sg123321's picture
Update app.py
b629f13 verified
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
)