Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import os | |
| import uuid | |
| from pydub import AudioSegment | |
| from pydub.silence import split_on_silence | |
| import re | |
| import click | |
| # --- LOGIC SECTION (SAME) --- | |
| def clean_file_name(file_path): | |
| file_name = os.path.basename(file_path) | |
| file_name, file_extension = os.path.splitext(file_name) | |
| cleaned = re.sub(r'[^a-zA-Z\d]+', '_', file_name) | |
| clean_file_name = re.sub(r'_+', '_', cleaned).strip('_') | |
| random_uuid = uuid.uuid4().hex[:6] | |
| clean_file_path = os.path.join(os.path.dirname(file_path), clean_file_name + f"_{random_uuid}" + file_extension) | |
| return clean_file_path | |
| def remove_silence(file_path, minimum_silence=50): | |
| sound = AudioSegment.from_file(file_path) | |
| audio_chunks = split_on_silence(sound, min_silence_len=100, silence_thresh=-45, keep_silence=minimum_silence) | |
| combined = AudioSegment.empty() | |
| for chunk in audio_chunks: | |
| combined += chunk | |
| output_path = clean_file_name(file_path) | |
| combined.export(output_path) | |
| return output_path | |
| def calculate_duration(file_path): | |
| audio = AudioSegment.from_file(file_path) | |
| return len(audio) / 1000.0 | |
| def process_audio(audio_file, seconds=0.05): | |
| if not audio_file: | |
| return None, None, "⚠️ Please upload a file first." | |
| keep_silence = int(seconds * 1000) | |
| output_audio_file = remove_silence(audio_file, minimum_silence=keep_silence) | |
| before = calculate_duration(audio_file) | |
| after = calculate_duration(output_audio_file) | |
| text = f"⏱️ Old: {before:.2f}s | ✅ New: {after:.2f}s | 🚀 Saved: {before-after:.2f}s" | |
| return output_audio_file, output_audio_file, text | |
| def reset_interface(): | |
| return None, 0.05, None, None, "" | |
| # --- NEW MOBILE-OPTIMIZED UI --- | |
| def ui(): | |
| # Clean Modern Font Theme | |
| theme = gr.themes.Soft( | |
| primary_hue="cyan", | |
| secondary_hue="slate", | |
| font=[gr.themes.GoogleFont("Poppins"), "sans-serif"], # Changed to Poppins (Cleaner) | |
| ).set( | |
| body_background_fill="#050505", | |
| block_background_fill="#121212", | |
| block_border_width="0px", | |
| input_background_fill="#1a1a1a" | |
| ) | |
| css = """ | |
| /* MOBILE FIX: Container width 100% karega */ | |
| .gradio-container { | |
| width: 100% !important; | |
| max-width: 100% !important; | |
| padding: 10px !important; | |
| margin: 0 !important; | |
| overflow-x: hidden; | |
| } | |
| /* Font Change */ | |
| * { font-family: 'Poppins', sans-serif !important; } | |
| /* RGB Animation */ | |
| @keyframes rgb-flow { | |
| 0% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| 100% { background-position: 0% 50%; } | |
| } | |
| /* Title Styling - Mobile Friendly */ | |
| .rgb-text { | |
| background: linear-gradient(45deg, #ff0000, #00ffd5, #002bff, #ff00c8); | |
| background-size: 300%; | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| font-weight: 800; | |
| font-size: 2rem; /* Thoda chota kiya mobile ke liye */ | |
| text-align: center; | |
| animation: rgb-flow 8s linear infinite; | |
| margin-bottom: 5px; | |
| line-height: 1.2; | |
| } | |
| .subtitle { | |
| text-align: center; | |
| color: #888; | |
| font-size: 0.9rem; | |
| margin-bottom: 15px; | |
| } | |
| /* Card Styling */ | |
| .rgb-card { | |
| background: #111; | |
| border-radius: 15px; | |
| padding: 2px; /* Border patla kiya */ | |
| margin-bottom: 10px; | |
| position: relative; | |
| } | |
| .rgb-card::before { | |
| content: ""; | |
| position: absolute; | |
| inset: 0; | |
| z-index: -1; | |
| background: linear-gradient(45deg, #ff0000, #00ffd5, #002bff, #ff00c8); | |
| background-size: 400%; | |
| border-radius: 15px; | |
| animation: rgb-flow 15s linear infinite; | |
| opacity: 0.6; | |
| } | |
| .inner-card { | |
| background: #0a0a0a; | |
| border-radius: 13px; | |
| padding: 15px; | |
| } | |
| /* Button Styling */ | |
| .process-btn { | |
| background: linear-gradient(90deg, #00c6ff 0%, #0072ff 100%) !important; | |
| color: white !important; | |
| font-weight: 600 !important; | |
| border: none !important; | |
| box-shadow: 0 4px 15px rgba(0, 114, 255, 0.3); | |
| } | |
| .reset-btn { | |
| background: #ff0055 !important; | |
| color: white !important; | |
| border: none !important; | |
| } | |
| /* Stats Box Text Fix */ | |
| .stat-box textarea { | |
| background-color: #000 !important; | |
| color: #00ff88 !important; | |
| font-family: monospace; | |
| font-size: 14px !important; | |
| } | |
| /* Mobile Specific Tweaks */ | |
| @media (max-width: 768px) { | |
| .rgb-text { font-size: 1.5rem !important; } /* Mobile pe title chota */ | |
| .inner-card { padding: 10px !important; } | |
| .process-btn, .reset-btn { width: 100%; margin-top: 5px; } /* Buttons full width */ | |
| } | |
| """ | |
| with gr.Blocks(theme=theme, css=css, title="Silence Remover Pro") as demo: | |
| gr.HTML(""" | |
| <div class="rgb-text">SILENCE REMOVER</div> | |
| <div class="subtitle">Clean Audio • Fast • AI Powered</div> | |
| """) | |
| with gr.Group(elem_classes="rgb-card"): | |
| with gr.Column(elem_classes="inner-card"): | |
| # Mobile par ye stack ho jayega (upar-niche) | |
| with gr.Row(): | |
| # --- INPUT SECTION --- | |
| with gr.Column(scale=1): | |
| gr.Markdown("### 📤 UPLOAD") | |
| audio_input = gr.Audio( | |
| label="Source", type="filepath", | |
| sources=["upload", "microphone"], show_label=False | |
| ) | |
| gr.Markdown("### 🎚️ SETTING") | |
| silence_threshold = gr.Slider( | |
| minimum=0, maximum=1, step=0.01, value=0.05, | |
| label="Keep Silence (Sec)" | |
| ) | |
| submit_btn = gr.Button("🚀 PROCESS AUDIO", elem_classes="process-btn") | |
| # --- OUTPUT SECTION --- | |
| with gr.Column(scale=1): | |
| gr.Markdown("### 🎧 RESULT") | |
| audio_output = gr.Audio( | |
| label="Clean Audio", show_label=False, interactive=False | |
| ) | |
| with gr.Row(): | |
| file_output = gr.File(label="Download", file_count="single", scale=2) | |
| clear_btn = gr.Button("❌ RESET", elem_classes="reset-btn", scale=1) | |
| duration_output = gr.Textbox( | |
| label="STATS", lines=2, | |
| elem_classes="stat-box", show_label=True | |
| ) | |
| gr.Markdown("""<div style="text-align: center; color: #555; font-size: 0.8rem; margin-top: 5px;">Made with ❤️</div>""") | |
| submit_btn.click( | |
| fn=process_audio, | |
| inputs=[audio_input, silence_threshold], | |
| outputs=[audio_output, file_output, duration_output] | |
| ) | |
| clear_btn.click( | |
| fn=reset_interface, | |
| inputs=None, | |
| outputs=[audio_input, silence_threshold, audio_output, file_output, duration_output] | |
| ) | |
| return demo | |
| def main(debug, share): | |
| demo = ui() | |
| demo.queue().launch(debug=debug, share=share) | |
| if __name__ == "__main__": | |
| main() | |