# ================================================================================================== # DEEPFAKE AUDIO - app_ui_demo.py (The UI Sandbox) # ================================================================================================== # # 📝 DESCRIPTION # This script serves as a lightweight, "UI-Only" verification environment for the Deepfake # Audio Studio. It is designed to run without the heavy neural dependencies (TensorFlow, PyTorch) # used in the production pipeline, allowing designers and developers to iterate on the # Human-Machine Interface (HMI) aesthetics without loading massive model weights. # # 👤 AUTHORS # - Amey Thakur (https://github.com/Amey-Thakur) # - Mega Satish (https://github.com/msatmod) # # 🤝🏻 CREDITS # Original Real-Time Voice Cloning methodology by CorentinJ # Repository: https://github.com/CorentinJ/Real-Time-Voice-Cloning # # 🔗 PROJECT LINKS # Repository: https://github.com/Amey-Thakur/DEEPFAKE-AUDIO # Video Demo: https://youtu.be/i3wnBcbHDbs # Research: https://github.com/Amey-Thakur/DEEPFAKE-AUDIO/blob/main/DEEPFAKE-AUDIO.ipynb # # 📜 LICENSE # Released under the MIT License # Release Date: 2021-02-06 # ================================================================================================== import os import sys from pathlib import Path # --- ENVIRONMENT CONFIGURATION --- # We suppress lower-level system warnings to ensure the focus remains on the HMI presentation. os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' os.environ['PYTHONWARNINGS'] = 'ignore' import warnings warnings.filterwarnings('ignore') import numpy as np import gradio as gr import base64 # --- DIRECTORY ARCHITECTURE --- PROJ_DIR = Path(__file__).parent.absolute() ROOT_DIR = PROJ_DIR.parent DATASET_DIR = ROOT_DIR / "Dataset" SAMPLES_DIR = DATASET_DIR / "samples" # --- Sample Loading (Dynamic Discovery) --- ROOT_DIR = PROJ_DIR.parent SAMPLES_DIR = ROOT_DIR / "Dataset/samples" if SAMPLES_DIR.exists(): for f in SAMPLES_DIR.glob("*.wav"): stem = f.stem if "_preset" in stem: name = stem.replace("_preset", "").replace("_", " ").title() else: name = stem SAMPLES[name] = str(f) def load_preset(name): if name in SAMPLES: return SAMPLES[name] return None # --- Mock Synthesis (UI Demo Only) --- def synthesize(audio_file, text, progress=gr.Progress()): if not audio_file or not text: return None, "Reference audio and text script are required." progress(0.2, desc="Extracting Voice Identity") progress(0.5, desc="Synthesizing Speech") progress(0.8, desc="Generating High-Fidelity Audio") progress(0.9, desc="Refining Audio Quality") progress(1.0, desc="Finalizing") return None, "⚠️ UI Demo Mode - TensorFlow blocked by system policy. Use Docker to run full synthesis." def play_intro(): intro_path = PROJ_DIR / "intro_message.wav" if intro_path.exists(): return str(intro_path) return None # --- NEON MIC ICON --- try: with open(PROJ_DIR / "favicon.png", "rb") as f: encoded_icon = base64.b64encode(f.read()).decode('utf-8') NEON_MIC_ICON = f"data:image/png;base64,{encoded_icon}" except: NEON_MIC_ICON = "/file=favicon.png" # --- Minimalist Navy & Orange UI --- custom_css = """ /* General Styles */ @import url('https://fonts.googleapis.com/css2?family=Play:wght@400;700&display=swap'); * { font-family: 'Play', sans-serif !important; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } /* Allow selection in inputs */ input, textarea, .gr-box, .gr-input, .gr-text-input { -webkit-user-select: text !important; -moz-user-select: text !important; -ms-user-select: text !important; user-select: text !important; cursor: text !important; } body { background-color: #0a192f !important; color: #ccd6f6 !important; overflow-x: hidden; } .gradio-container { background-color: transparent !important; position: relative !important; z-index: 1 !important; } /* Pseudo-element for the pattern to control opacity properly without affecting text */ body::before { content: ""; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-image: url('FAVICON_PLACEHOLDER') !important; background-repeat: repeat !important; background-size: 60px !important; opacity: 0.05 !important; /* Dimmed to 5% - Perfect watermark */ pointer-events: none; z-index: 0; } """.replace("FAVICON_PLACEHOLDER", NEON_MIC_ICON) + """ .main-container { max-width: 950px !important; margin: 0 auto !important; padding: 20px !important; } #header h1 { font-size: 2.2rem; color: #ff8c00; margin-bottom: 0px; letter-spacing: -1px; } #header p { font-size: 0.9rem; color: #8892b0; margin-top: 5px; } #intro-btn { background: transparent !important; border: none !important; font-size: 2.2rem !important; color: #ff8c00 !important; font-weight: 800 !important; cursor: pointer !important; box-shadow: none !important; padding: 0 !important; margin: 0 !important; transition: all 0.3s ease !important; } #intro-btn:hover { color: #ccd6f6 !important; transform: scale(1.02); } #intro-audio { display: none !important; } .studio-card { background: #112240 !important; border: 1px solid #233554 !important; border-radius: 12px !important; padding: 10px !important; box-shadow: 0 10px 30px -15px rgba(2, 12, 27, 0.7) !important; margin-bottom: 6px !important; transition: transform 0.2s ease, border-color 0.2s ease !important; min-height: 180px !important; display: flex !important; flex-direction: column !important; overflow: visible !important; } .studio-card .prose { margin-bottom: 5px !important; } /* Force Play Font on everything */ * { font-family: 'Play', sans-serif !important; } span, button, input, label, textarea, select { font-family: 'Play', sans-serif !important; } .studio-card:hover { transform: translateY(-2px); border-color: #ff8c00 !important; } /* --- PRO CODE DEFINITIVE "ZERO-BLEED" FIX --- */ /* 1. FLATTEN THE WRAPPERS: Make specific outer containers invisible */ #script-box, #status-box, #script-box > .form, #status-box > .form, .gray-border, .form { background-color: transparent !important; background: transparent !important; border: none !important; box-shadow: none !important; padding: 0 !important; } /* 2. STYLE THE INNER INPUTS: Apply the theme ONLY to the interactive element */ #script-box textarea, #status-box input, #preset-dropdown-container .gr-dropdown { background-color: #112240 !important; /* Perfect Match to Studio Card */ border: 2px solid #ff8c00 !important; border-radius: 12px !important; color: #ccd6f6 !important; box-shadow: none !important; } /* Remove placeholder color interference */ #script-box textarea::placeholder { color: #555 !important; } /* Focus States */ #script-box textarea:focus, #status-box input:focus { border-color: #ffb347 !important; box-shadow: 0 0 15px rgba(255, 140, 0, 0.4) !important; } /* --- PRO CODE "VOICE DECK" (SCROLLABLE LIST) --- */ /* The Voice Deck Container */ #voice-deck { max-height: 70px !important; overflow-y: auto !important; background-color: #0d1b2a !important; /* Slightly darker than card for depth */ border: 2px solid #ff8c00 !important; border-radius: 12px !important; padding: 8px !important; margin-bottom: 10px !important; scrollbar-width: thin !important; scrollbar-color: #ff8c00 #0a192f !important; } /* Radio Item Styling (Premium Chips) */ #voice-deck label { display: flex !important; align-items: center !important; width: 100% !important; background: transparent !important; border: 1px solid #233554 !important; border-radius: 8px !important; margin-bottom: 4px !important; padding: 8px 12px !important; transition: all 0.2s ease !important; cursor: pointer !important; color: #8892b0 !important; } #voice-deck label:hover { background: #112240 !important; border-color: #ff8c00 !important; color: #ff8c00 !important; } #voice-deck label.selected, #voice-deck input:checked + span { background: #233554 !important; border-color: #ff8c00 !important; color: #ff8c00 !important; font-weight: bold !important; box-shadow: 0 0 10px rgba(255, 140, 0, 0.2) !important; } /* Hide the default radio circle */ #voice-deck input[type="radio"] { display: none !important; } /* Ensure text is nicely aligned */ #voice-deck span { margin-left: 0 !important; font-size: 0.95rem !important; } /* Audio Input Transparency Fix */ #audio-input, #audio-input .gr-input, #audio-input .gr-box, #audio-input .gr-block { background: transparent !important; background-color: transparent !important; border: none !important; box-shadow: none !important; } div[role="option"] { padding: 10px !important; color: #ccd6f6 !important; border-bottom: 1px solid #233554 !important; } div[role="option"]:hover, div[role="option"][aria-selected="true"] { background-color: #233554 !important; color: #ff8c00 !important; } div[role="listbox"]::-webkit-scrollbar { width: 6px !important; } div[role="listbox"]::-webkit-scrollbar-track { background: #0a192f !important; border-radius: 10px !important; } div[role="listbox"]::-webkit-scrollbar-thumb { background: #ff8c00 !important; border-radius: 10px !important; border: 1px solid #0a192f !important; } div[role="listbox"]::-webkit-scrollbar-thumb:hover { background: #ffa500 !important; } /* --- PREMIUM SCROLLBARS --- */ /* Global Scrollbar Styling */ ::-webkit-scrollbar { width: 6px !important; height: 6px !important; } ::-webkit-scrollbar-track { background: #0a192f !important; } ::-webkit-scrollbar-thumb { background: #ff8c00 !important; border-radius: 20px !important; border: 1px solid #0a192f !important; } ::-webkit-scrollbar-thumb:hover { background: #ffa500 !important; box-shadow: 0 0 10px rgba(255, 140, 0, 0.5) !important; } /* Ensure Audio Player Scrollbars match */ audio::-webkit-scrollbar { height: 6px !important; } div[role="option"] { background-color: transparent !important; color: #ccd6f6 !important; } div[role="option"]:hover, div[role="option"][aria-selected="true"] { background-color: #233554 !important; color: #ff8c00 !important; } .btn-primary { background: #ff8c00 !important; border: 2px solid #ff8c00 !important; color: #0a192f !important; font-weight: 800 !important; border-radius: 8px !important; padding: 0 20px !important; height: 50px !important; cursor: pointer !important; transition: all 0.3s ease !important; width: 100% !important; } .btn-primary:hover { background: transparent !important; color: #ff8c00 !important; border-color: #ff8c00 !important; } .btn-secondary { background: transparent !important; border: 1px solid #233554 !important; color: #8892b0 !important; border-radius: 8px !important; height: 50px !important; padding: 0 20px !important; transition: all 0.3s ease !important; width: 100% !important; } .btn-secondary:hover { background: #ff8c00 !important; color: #0a192f !important; border-color: #ff8c00 !important; } .info-section { font-size: 0.85rem; color: #8892b0; margin-top: 20px; padding: 0 15px; animation: fadeIn 0.8s ease-out; } .info-header { color: #ff8c00 !important; font-weight: 800 !important; margin-bottom: 5px !important; display: block !important; } .footer { text-align: center; margin-top: 40px; padding-top: 20px; border-top: 1px solid #233554; font-size: 0.8rem; color: #8892b0; animation: fadeIn 1s ease-out; } .footer a { color: #ff8c00; text-decoration: none; font-weight: 600; transition: opacity 0.2s; } .footer a:hover { opacity: 0.8; } .authorship { margin-bottom: 10px; font-weight: 600; } /* Dropdown Polish */ .gr-dropdown { background: #0a192f !important; border-color: #233554 !important; margin-bottom: 12px !important; } .gr-dropdown:focus-within { border-color: #ff8c00 !important; } /* Premium Progress Bar Styling */ .gr-progress { background-color: #0a192f !important; border: 1px solid #233554 !important; border-radius: 12px !important; height: 38px !important; overflow: hidden !important; box-shadow: inset 0 2px 4px rgba(0,0,0,0.3) !important; } .gr-progress .progress-level { background: linear-gradient(90deg, #ff8c00, #ffb347) !important; border-radius: 10px !important; box-shadow: 0 0 20px rgba(255, 140, 0, 0.4) !important; height: 100% !important; transition: width 0.4s cubic-bezier(0.4, 0, 0.2, 1) !important; position: relative !important; overflow: hidden !important; } .gr-progress .progress-level::after { content: "" !important; position: absolute !important; top: 0 !important; left: -150% !important; width: 100% !important; height: 100% !important; background: linear-gradient( 90deg, transparent, rgba(255, 255, 255, 0.4), transparent ) !important; animation: apple-shimmer 2s infinite linear !important; } @keyframes apple-shimmer { 0% { left: -150%; } 100% { left: 150%; } } .gr-progress .progress-text { color: #ffffff !important; font-family: 'Play', sans-serif !important; font-weight: 700 !important; font-size: 0.85rem !important; line-height: 38px !important; text-shadow: 0 1px 2px rgba(0,0,0,0.5) !important; letter-spacing: 0.5px !important; position: relative !important; z-index: 5 !important; } .progress-container { padding: 0 !important; margin: 0 !important; } /* Subtle Animations */ @keyframes fadeIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } } .main-container { animation: fadeIn 0.6s ease-out; } .studio-card { transition: transform 0.2s ease, border-color 0.2s ease !important; } .studio-card:hover { transform: translateY(-2px); border-color: #ff8c00 !important; } """ theme = gr.themes.Default( primary_hue="orange", secondary_hue="slate", ).set( body_background_fill="#0a192f", block_background_fill="#112240", input_background_fill="#0a192f", input_border_color="#233554", ) # --- Low-Level Security & Easter Egg --- custom_js = """ function() { document.addEventListener('contextmenu', event => { event.preventDefault(); alert('Security Protocol Engaged: System protected by Amey Thakur & Mega Satish'); console.warn('Security Alert: Unauthorized access attempt detected.'); }); console.log("%c STOP! %c You are entering a protected zone.", "color: red; font-size: 50px; font-weight: bold;", "color: white; font-size: 20px;"); } """ # Inject Favicon via Head (Reliable) and Security JS with gr.Blocks(title="Deepfake Audio Studio", theme=theme, css=custom_css, js=custom_js, head=''.format(NEON_MIC_ICON)) as demo: with gr.Column(elem_classes=["main-container"]): # Minimal Header with gr.Column(elem_id="header"): with gr.Row(): intro_btn = gr.Button("🎙️ Deepfake Audio", elem_id="intro-btn") gr.Markdown("
A neural voice cloning studio powered by SV2TTS technology
") intro_audio = gr.Audio(visible=True, autoplay=True, elem_id="intro-audio") # Compact 2x2 Grid with gr.Row(): # Voice Deck (Scrollable Radio List) with gr.Column(elem_classes=["studio-card"]): gr.Markdown("
01. Voice Reference
") # The Voice Deck preset_dropdown = gr.Radio( choices=["Custom Upload"] + sorted([k for k in SAMPLES.keys()]), value="Custom Upload", label="Voice Selection", show_label=False, elem_id="voice-deck", interactive=True ) audio_input = gr.Audio(type="filepath", label="Reference Sample", container=False, show_label=False, elem_id="audio-input") with gr.Column(): with gr.Column(elem_classes=["studio-card"], elem_id="synthesis-output-card"): gr.Markdown("
02. Synthesis Output
") audio_output = gr.Audio(label="Generated Result", interactive=False, container=False, show_label=False, elem_id="audio-output") # Input & Status Row (2x2 Grid Symmetry) with gr.Row(): with gr.Column(elem_classes=["studio-card"]): gr.Markdown("
03. Target Script
") text_input = gr.Textbox( label="Target text to synthesize", placeholder="Enter audio text...", lines=3, show_label=False, elem_id="script-box" ) with gr.Column(elem_classes=["studio-card"]): gr.Markdown("
04. System Status
") status_info = gr.Textbox( label="System Status", value="⚠️ UI Demo Mode - TensorFlow blocked by system policy.", interactive=False, show_label=False, elem_id="status-box" ) # Controls with gr.Row(): with gr.Column(scale=1): reset_btn = gr.Button("Reset", variant="secondary", elem_id="reset-btn", elem_classes=["btn-secondary"]) with gr.Column(scale=1): run_btn = gr.Button("Generate Voice Clone", variant="primary", elem_classes=["btn-primary"]) # Information Sections (Neat & Compact) with gr.Row(elem_classes=["info-section"]): with gr.Column(): gr.Markdown("How it Works") gr.Markdown("Extracts speaker identity into a latent embedding to drive neural text-to-speech synthesis.") with gr.Column(): gr.Markdown("Privacy Notice") gr.Markdown("Audio is processed in memory and never stored. For educational and research use only.") # Minimal Footer with gr.Column(elem_classes=["footer"]): gr.HTML("""
Created by Amey Thakur & Mega Satish
GitHub Repository | YouTube Demo

© 2021 Deepfake Audio Studio

""") # Events run_btn.click( fn=synthesize, inputs=[audio_input, text_input], outputs=[audio_output, status_info] ) reset_btn.click(lambda: (None, "Custom Upload", "", None, "⚠️ UI Demo Mode"), outputs=[audio_input, preset_dropdown, text_input, audio_output, status_info]) # Preset selection logic def on_preset_change(name): if name == "Custom Upload": return None return load_preset(name) preset_dropdown.change(fn=on_preset_change, inputs=[preset_dropdown], outputs=[audio_input]) # Custom JS to force play because browser autoplay policies are strict play_js = "() => { setTimeout(() => { const audio = document.querySelector('#intro-audio audio'); if (audio) audio.play(); }, 300); }" intro_btn.click(fn=play_intro, outputs=intro_audio, js=play_js) if __name__ == "__main__": print("🎙️ Launching Deepfake Audio Studio (UI Demo Mode)...") print("📍 Open: http://localhost:7860") demo.queue().launch(server_name="0.0.0.0", server_port=7860, show_error=True, pwa=True)