xtts / app.py
sg123321's picture
Update app.py
3767dfa verified
import os
import uuid
import gradio as gr
import torch
import spaces
from TTS.api import TTS
from supabase import create_client, Client
import config
# 1. Supabase Connection
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}")
# 2. 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)
# --- Helper Functions ---
def get_voice_list():
if not supabase: return []
try:
res = supabase.storage.from_("voice-bucket").list()
files = [f['name'] for f in res if f['name'].endswith(('.wav', '.mp3'))]
return files
except Exception as e:
return []
def download_cloud_voice(filename):
local_path = f"temp_{filename}"
with open(local_path, 'wb+') as f:
res = supabase.storage.from_("voice-bucket").download(filename)
f.write(res)
return local_path
# --- Main Logic ---
@spaces.GPU(duration=120)
def generate_preview(text, language, upload_voice, cloud_voice_name):
speaker_wav = None
if upload_voice is not None:
speaker_wav = upload_voice
elif cloud_voice_name:
try:
speaker_wav = download_cloud_voice(cloud_voice_name)
except Exception as e:
return None, f"Error downloading: {e}"
else:
return None, "⚠️ Please select a voice!"
output_path = "preview.wav"
tts.tts_to_file(text=text, file_path=output_path, speaker_wav=speaker_wav, language=language)
return output_path, "βœ… Preview Ready!"
def save_to_cloud(preview_path, text, language):
if not preview_path or not os.path.exists(preview_path):
return "⚠️ No preview found!"
if not supabase:
return "❌ Supabase not connected!"
filename = f"final_{language}_{uuid.uuid4()}.wav"
try:
with open(preview_path, 'rb') as f:
supabase.storage.from_("voice-bucket").upload(filename, f)
storage_url = f"{config.SUPABASE_URL}/storage/v1/object/public/voice-bucket/{filename}"
data = {"name": f"Clone_{language}", "file_path": storage_url, "ref_text": text}
supabase.table("clones").insert(data).execute()
return f"πŸŽ‰ Saved! Link: {storage_url}"
except Exception as e:
return f"❌ Save Error: {e}"
# --- UI Layout ---
with gr.Blocks(title="Shubham's Secure Voice AI") as app:
gr.Markdown("## πŸ” Secure XTTS Voice Cloning")
with gr.Row():
with gr.Column():
txt_input = gr.Textbox(label="Text", lines=3, value="Namaste!")
lang_dropdown = gr.Dropdown(label="Language", choices=["hi", "en"], value="hi")
with gr.Column():
voice_upload = gr.Audio(label="Upload Voice", type="filepath")
voice_dropdown = gr.Dropdown(label="Select from Cloud", choices=get_voice_list())
refresh_btn = gr.Button("πŸ”„ Refresh List")
btn_preview = gr.Button("πŸ”Š Generate Preview", variant="primary")
audio_output = gr.Audio(label="Preview")
status_msg = gr.Textbox(label="Status")
btn_save = gr.Button("☁️ Save to Cloud", variant="secondary")
# Events
refresh_btn.click(lambda: gr.Dropdown(choices=get_voice_list()), outputs=voice_dropdown)
btn_preview.click(generate_preview, inputs=[txt_input, lang_dropdown, voice_upload, voice_dropdown], outputs=[audio_output, status_msg])
btn_save.click(save_to_cloud, inputs=[audio_output, txt_input, lang_dropdown], outputs=status_msg)
# πŸš€ LOGIN SYSTEM (Powered by Config/Secrets)
if __name__ == "__main__":
app.launch(
auth=(config.APP_USER, config.APP_PASS), # πŸ”’ Ab ye config file se password lega
server_name="0.0.0.0",
server_port=7860
)