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 )