Spaces:
Runtime error
Runtime error
| import time | |
| import gradio as gr | |
| # --- Custom CSS to mimic your original look --- | |
| custom_css = """ | |
| :root { | |
| --primary: #6366f1; | |
| --primary-dark: #4f46e5; | |
| --secondary: #10b981; | |
| --dark: #1e293b; | |
| --light: #f8fafc; | |
| --gray: #94a3b8; | |
| --danger: #ef4444; | |
| } | |
| body { | |
| background: linear-gradient(135deg, #0f172a, #1e293b) !important; | |
| color: var(--light) !important; | |
| } | |
| .gradio-container { | |
| max-width: 1200px !important; | |
| margin: 0 auto !important; | |
| padding: 20px !important; | |
| font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; | |
| } | |
| h1, h2, h3 { | |
| font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; | |
| } | |
| .rvc-card { | |
| background: rgba(30, 41, 59, 0.7); | |
| backdrop-filter: blur(10px); | |
| border-radius: 16px; | |
| padding: 30px; | |
| margin-bottom: 30px; | |
| box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3); | |
| border: 1px solid rgba(255, 255, 255, 0.1); | |
| } | |
| .rvc-title { | |
| font-size: 2.5rem; | |
| margin-bottom: 10px; | |
| background: linear-gradient(to right, #8b5cf6, #06b6d4); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); | |
| text-align: center; | |
| } | |
| .rvc-subtitle { | |
| font-size: 1.2rem; | |
| color: var(--gray); | |
| max-width: 600px; | |
| margin: 0 auto; | |
| text-align: center; | |
| } | |
| .rvc-card-title { | |
| font-size: 1.5rem; | |
| margin-bottom: 20px; | |
| color: #8b5cf6; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .rvc-status { | |
| padding: 15px; | |
| border-radius: 8px; | |
| margin-top: 20px; | |
| text-align: center; | |
| font-weight: 500; | |
| } | |
| .rvc-status-processing { | |
| background: rgba(59, 130, 246, 0.2); | |
| color: #3b82f6; | |
| } | |
| .rvc-status-success { | |
| background: rgba(16, 185, 129, 0.2); | |
| color: var(--secondary); | |
| } | |
| .rvc-status-error { | |
| background: rgba(239, 68, 68, 0.2); | |
| color: var(--danger); | |
| } | |
| /* Fake progress bar */ | |
| .rvc-progress-container { | |
| height: 8px; | |
| background: rgba(15, 23, 42, 0.5); | |
| border-radius: 4px; | |
| overflow: hidden; | |
| margin: 20px 0; | |
| } | |
| .rvc-progress-bar { | |
| height: 100%; | |
| background: linear-gradient(to right, var(--primary), var(--secondary)); | |
| width: 0%; | |
| transition: width 0.2s ease; | |
| } | |
| /* Make Gradio buttons vaguely match your buttons */ | |
| button, .gr-button { | |
| font-weight: 600 !important; | |
| border-radius: 8px !important; | |
| } | |
| /* Smaller screens tweaks */ | |
| @media (max-width: 768px) { | |
| .rvc-card { | |
| padding: 20px; | |
| } | |
| .rvc-title { | |
| font-size: 2rem; | |
| } | |
| } | |
| """ | |
| # --- Backend logic (simulated) --- | |
| def train_model(files, model_name, voice_type, quality, epochs, trained, progress=gr.Progress(track_tqdm=True)): | |
| """Simulate model training.""" | |
| if not files: | |
| # No files โ error | |
| status_html = ( | |
| '<div class="rvc-status rvc-status-error">' | |
| "Please upload at least one audio file." | |
| "</div>" | |
| ) | |
| # progress_html with 0% | |
| progress_html = ( | |
| '<div class="rvc-progress-container">' | |
| '<div class="rvc-progress-bar" style="width:0%"></div>' | |
| "</div>" | |
| ) | |
| return status_html, False, progress_html | |
| model_name = model_name or "MySingingVoice" | |
| steps = 20 | |
| # Simulate training loop | |
| for i in progress.tqdm(range(steps), desc=f'Training "{model_name}"'): | |
| time.sleep(0.15) | |
| status_html = ( | |
| '<div class="rvc-status rvc-status-success">' | |
| f'Model "{model_name}" trained successfully!' | |
| "</div>" | |
| ) | |
| progress_html = ( | |
| '<div class="rvc-progress-container">' | |
| '<div class="rvc-progress-bar" style="width:100%"></div>' | |
| "</div>" | |
| ) | |
| return status_html, True, progress_html | |
| def preview_model(trained, model_name): | |
| """Simulate generating a preview.""" | |
| model_name = model_name or "MySingingVoice" | |
| if not trained: | |
| return ( | |
| '<div class="rvc-status rvc-status-error">' | |
| "Please train a model first." | |
| "</div>" | |
| ) | |
| # Fake delay for โpreview generationโ | |
| time.sleep(1.0) | |
| return ( | |
| '<div class="rvc-status rvc-status-success">' | |
| f'Preview generated successfully for "{model_name}"! ' | |
| "Imagine your custom voice playing here ๐ต" | |
| "</div>" | |
| ) | |
| def export_model(trained, what): | |
| """Simulate export of model / sample / info.""" | |
| if not trained: | |
| return ( | |
| '<div class="rvc-status rvc-status-error">' | |
| "Please train a model before exporting." | |
| "</div>" | |
| ) | |
| time.sleep(0.8) | |
| return ( | |
| '<div class="rvc-status rvc-status-success">' | |
| f'{what} exported successfully! (Demo only โ no real file generated)' | |
| "</div>" | |
| ) | |
| def reset_app(): | |
| """Reset everything to defaults.""" | |
| status_html = "" | |
| trained = False | |
| model_name = "MySingingVoice" | |
| voice_type = "soprano" | |
| quality = "high" | |
| epochs = 300 | |
| files = None | |
| progress_html = ( | |
| '<div class="rvc-progress-container">' | |
| '<div class="rvc-progress-bar" style="width:0%"></div>' | |
| "</div>" | |
| ) | |
| return status_html, trained, model_name, voice_type, quality, epochs, files, progress_html | |
| # --- Gradio UI --- | |
| with gr.Blocks(css=custom_css, title="RVC Voice Model Creator") as demo: | |
| # Header | |
| gr.HTML( | |
| """ | |
| <h1 class="rvc-title">RVC Voice Model Creator</h1> | |
| <p class="rvc-subtitle"> | |
| Upload your audio files to create custom singing voice models for AI voice conversion. | |
| </p> | |
| """ | |
| ) | |
| trained_state = gr.State(False) | |
| # --- Upload Card --- | |
| with gr.Group(elem_classes="rvc-card"): | |
| gr.HTML('<h2 class="rvc-card-title">๐ Upload Audio Files</h2>') | |
| files = gr.File( | |
| label="Drag & drop your audio files here or click to browse", | |
| file_types=["audio"], | |
| file_count="multiple", | |
| ) | |
| # --- Settings + Training Card --- | |
| with gr.Group(elem_classes="rvc-card"): | |
| gr.HTML('<h2 class="rvc-card-title">โ๏ธ Model Settings</h2>') | |
| with gr.Row(): | |
| with gr.Column(): | |
| model_name = gr.Textbox( | |
| label="Model Name", | |
| value="MySingingVoice", | |
| placeholder="Enter your model name", | |
| ) | |
| voice_type = gr.Dropdown( | |
| label="Voice Type", | |
| choices=[ | |
| "soprano", | |
| "alto", | |
| "tenor", | |
| "bass", | |
| "custom", | |
| ], | |
| value="soprano", | |
| ) | |
| with gr.Column(): | |
| quality = gr.Dropdown( | |
| label="Quality Level", | |
| choices=["high", "medium", "low"], | |
| value="high", | |
| ) | |
| epochs = gr.Slider( | |
| label="Training Epochs", | |
| minimum=50, | |
| maximum=1000, | |
| step=10, | |
| value=300, | |
| ) | |
| progress_html = gr.HTML( | |
| value=( | |
| '<div class="rvc-progress-container">' | |
| '<div class="rvc-progress-bar" style="width:0%"></div>' | |
| "</div>" | |
| ) | |
| ) | |
| status_html = gr.HTML(value="") | |
| with gr.Row(): | |
| train_btn = gr.Button("๐ Train Model", variant="primary") | |
| preview_btn = gr.Button("๐๏ธ Preview Model", variant="secondary") | |
| reset_btn = gr.Button("๐๏ธ Reset All", variant="stop") | |
| # --- Export Card --- | |
| with gr.Group(elem_classes="rvc-card"): | |
| gr.HTML('<h2 class="rvc-card-title">๐ฅ Export Model</h2>') | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("**RVC Model** \n.pth weight file for voice conversion") | |
| export_rvc_btn = gr.Button("Download RVC") | |
| with gr.Column(): | |
| gr.Markdown("**Sample Audio** \nConverted sample with your voice") | |
| export_sample_btn = gr.Button("Download Sample") | |
| with gr.Column(): | |
| gr.Markdown("**Model Info** \nConfiguration and training details") | |
| export_info_btn = gr.Button("Download Info") | |
| # Footer note | |
| gr.Markdown( | |
| "> RVC Voice Model Creator | Create custom singing voices for AI applications \n" | |
| "> **Note:** This Space is a frontend/demo. Real RVC training needs a proper backend pipeline." | |
| ) | |
| # --- Wiring logic --- | |
| # Train button | |
| train_btn.click( | |
| fn=train_model, | |
| inputs=[files, model_name, voice_type, quality, epochs, trained_state], | |
| outputs=[status_html, trained_state, progress_html], | |
| ) | |
| # Preview button | |
| preview_btn.click( | |
| fn=preview_model, | |
| inputs=[trained_state, model_name], | |
| outputs=status_html, | |
| ) | |
| # Export buttons | |
| export_rvc_btn.click( | |
| fn=export_model, | |
| inputs=[trained_state, gr.State("RVC model (.pth)")], | |
| outputs=status_html, | |
| ) | |
| export_sample_btn.click( | |
| fn=export_model, | |
| inputs=[trained_state, gr.State("Sample audio")], | |
| outputs=status_html, | |
| ) | |
| export_info_btn.click( | |
| fn=export_model, | |
| inputs=[trained_state, gr.State("Model info")], | |
| outputs=status_html, | |
| ) | |
| # Reset button | |
| reset_btn.click( | |
| fn=reset_app, | |
| inputs=None, | |
| outputs=[ | |
| status_html, | |
| trained_state, | |
| model_name, | |
| voice_type, | |
| quality, | |
| epochs, | |
| files, | |
| progress_html, | |
| ], | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |