File size: 4,018 Bytes
1dd5ac4
c0b8023
5de0578
 
c0b8023
 
 
3767dfa
5de0578
1dd5ac4
c0b8023
 
 
 
1dd5ac4
c0b8023
1dd5ac4
9c8f593
1dd5ac4
c0b8023
5de0578
1dd5ac4
5de0578
 
1dd5ac4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c0b8023
1dd5ac4
 
 
 
 
 
 
 
3767dfa
1dd5ac4
3767dfa
1dd5ac4
 
3767dfa
 
1dd5ac4
 
 
3767dfa
1dd5ac4
 
 
 
 
 
 
 
 
 
3767dfa
1dd5ac4
 
3767dfa
1dd5ac4
 
 
3767dfa
 
 
1dd5ac4
 
 
3767dfa
 
1dd5ac4
3767dfa
 
 
1dd5ac4
3767dfa
 
 
 
1dd5ac4
3767dfa
 
 
 
1dd5ac4
3767dfa
1dd5ac4
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
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
    )