Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import numpy as np | |
| import time | |
| from typing import Generator, Tuple | |
| def process_audio(audio: Tuple[int, np.ndarray]) -> Generator[np.ndarray, None, None]: | |
| """Process audio in real-time with shadow effects""" | |
| if audio is None: | |
| return | |
| sample_rate, audio_data = audio | |
| # Simulate real-time processing with shadow effect | |
| for i in range(0, len(audio_data), 1024): | |
| chunk = audio_data[i:i+1024] | |
| # Apply shadow effect (attenuate and delay simulation) | |
| shadow_effect = chunk * 0.7 | |
| if i > 512: | |
| shadow_effect += audio_data[i-512:i-512+len(chunk)] * 0.3 | |
| yield shadow_effect | |
| def get_audio_info(audio: Tuple[int, np.ndarray]) -> str: | |
| """Get audio information""" | |
| if audio is None: | |
| return "No audio detected" | |
| sample_rate, audio_data = audio | |
| duration = len(audio_data) / sample_rate | |
| return f"Sample Rate: {sample_rate} Hz\nDuration: {duration:.2f} seconds\nChannels: Mono" | |
| # Custom dark theme with shadow effects | |
| custom_dark_theme = gr.themes.Soft( | |
| primary_hue="purple", | |
| secondary_hue="indigo", | |
| neutral_hue="gray", | |
| font=gr.themes.GoogleFont("Inter"), | |
| text_size="lg", | |
| spacing_size="lg", | |
| radius_size="md" | |
| ).set( | |
| body_background_fill="*neutral_950", | |
| block_background_fill="*neutral_900", | |
| block_border_width="1px", | |
| block_border_color="*neutral_800", | |
| block_shadow="0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.2)", | |
| block_title_text_weight="600", | |
| block_title_text_color="*neutral_50", | |
| block_label_text_color="*neutral_300", | |
| input_background_fill="*neutral_800", | |
| input_border_color="*neutral_700", | |
| input_text_color="*neutral_100", | |
| button_primary_background_fill="*primary_600", | |
| button_primary_background_fill_hover="*primary_700", | |
| button_primary_text_color="white", | |
| button_secondary_background_fill="*neutral_800", | |
| button_secondary_background_fill_hover="*neutral_700", | |
| button_secondary_text_color="*neutral_100", | |
| prose_text_color="*neutral_200", | |
| prose_header_text_color="*neutral_50" | |
| ) | |
| # Custom CSS for additional shadow effects | |
| custom_css = """ | |
| /* Enhanced shadow effects */ | |
| .gradio-container { | |
| background: linear-gradient(135deg, #0f0f0f 0%, #1a1a1a 100%); | |
| } | |
| /* Card shadow effects */ | |
| .shadow-card { | |
| box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5), 0 6px 10px rgba(0, 0, 0, 0.3); | |
| border: 1px solid #333; | |
| background: rgba(30, 30, 30, 0.8); | |
| backdrop-filter: blur(10px); | |
| } | |
| /* Button shadow effects */ | |
| .btn-shadow { | |
| box-shadow: 0 4px 15px rgba(139, 92, 246, 0.3), 0 2px 4px rgba(0, 0, 0, 0.2); | |
| transition: all 0.3s ease; | |
| } | |
| .btn-shadow:hover { | |
| box-shadow: 0 6px 20px rgba(139, 92, 246, 0.4), 0 3px 6px rgba(0, 0, 0, 0.3); | |
| transform: translateY(-2px); | |
| } | |
| /* Audio component shadow */ | |
| audio { | |
| box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4); | |
| border-radius: 8px; | |
| } | |
| /* Text shadow for headings */ | |
| h1, h2, h3 { | |
| text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5); | |
| } | |
| /* Glow effect for active elements */ | |
| .glow { | |
| box-shadow: 0 0 20px rgba(139, 92, 246, 0.5), 0 0 40px rgba(139, 92, 246, 0.3); | |
| } | |
| /* Animation for recording */ | |
| @keyframes pulse { | |
| 0% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.7); } | |
| 70% { box-shadow: 0 0 0 10px rgba(239, 68, 68, 0); } | |
| 100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); } | |
| } | |
| .recording { | |
| animation: pulse 2s infinite; | |
| } | |
| """ | |
| with gr.Blocks() as demo: | |
| # Header with shadow effect | |
| gr.HTML(""" | |
| <div style="text-align: center; margin-bottom: 30px; padding: 20px; background: rgba(30, 30, 30, 0.6); border-radius: 12px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);"> | |
| <h1 style="color: #e5e7eb; font-size: 2.5em; margin-bottom: 10px; text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.7);"> | |
| ποΈ Real-Time Voice Shadow Processor | |
| </h1> | |
| <p style="color: #9ca3af; font-size: 1.1em; text-shadow: 1px 1px 4px rgba(0, 0, 0, 0.5);"> | |
| Experience audio with dynamic shadow effects in real-time | |
| </p> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" style="color: #8b5cf6; text-decoration: none; font-weight: 600;"> | |
| Built with anycoder | |
| </a> | |
| </div> | |
| """) | |
| with gr.Row(equal_height=True): | |
| with gr.Column(scale=1, elem_classes=["shadow-card"]): | |
| gr.Markdown(""" | |
| ### ποΈ Input Controls | |
| Speak into your microphone to apply real-time shadow effects | |
| """, elem_id="input-header") | |
| # Input audio with shadow effect | |
| input_audio = gr.Audio( | |
| sources=["microphone"], | |
| type="numpy", | |
| label="π€ Input Audio", | |
| streaming=True, | |
| elem_classes=["shadow-card"] | |
| ) | |
| with gr.Row(): | |
| start_btn = gr.Button( | |
| "βΆοΈ Start Processing", | |
| variant="primary", | |
| elem_classes=["btn-shadow"], | |
| size="lg" | |
| ) | |
| stop_btn = gr.Button( | |
| "βΉοΈ Stop", | |
| variant="secondary", | |
| elem_classes=["btn-shadow"], | |
| size="lg" | |
| ) | |
| with gr.Column(scale=1, elem_classes=["shadow-card"]): | |
| gr.Markdown(""" | |
| ### π Audio Information | |
| Real-time audio analysis and processing status | |
| """, elem_id="info-header") | |
| # Audio info display | |
| audio_info = gr.Textbox( | |
| label="π Audio Details", | |
| value="Waiting for audio input...", | |
| interactive=False, | |
| elem_classes=["shadow-card"] | |
| ) | |
| # Status indicator | |
| status_display = gr.HTML(""" | |
| <div style="padding: 15px; background: rgba(55, 65, 81, 0.5); border-radius: 8px; margin: 10px 0;"> | |
| <p style="color: #9ca3af; margin: 0;">π΄ Status: Ready</p> | |
| </div> | |
| """) | |
| # Volume visualization | |
| volume_meter = gr.Slider( | |
| minimum=0, | |
| maximum=100, | |
| value=0, | |
| label="π Volume Level", | |
| interactive=False, | |
| elem_classes=["shadow-card"] | |
| ) | |
| with gr.Row(): | |
| with gr.Column(elem_classes=["shadow-card"]): | |
| gr.Markdown(""" | |
| ### π― Processed Output | |
| Audio with shadow effects applied in real-time | |
| """, elem_id="output-header") | |
| # Output audio with shadow effect | |
| output_audio = gr.Audio( | |
| label="π Processed Audio", | |
| streaming=True, | |
| autoplay=True, | |
| elem_classes=["shadow-card"] | |
| ) | |
| # Effect controls | |
| with gr.Accordion("βοΈ Shadow Effect Settings", open=True): | |
| shadow_intensity = gr.Slider( | |
| minimum=0, | |
| maximum=100, | |
| value=30, | |
| label="Shadow Intensity (%)", | |
| elem_classes=["shadow-card"] | |
| ) | |
| delay_amount = gr.Slider( | |
| minimum=0, | |
| maximum=100, | |
| value=50, | |
| label="Delay Amount (%)", | |
| elem_classes=["shadow-card"] | |
| ) | |
| # Real-time processing function | |
| def process_realtime(audio, intensity, delay): | |
| if audio is None: | |
| return None, "No audio input", 0, '<div style="padding: 15px; background: rgba(55, 65, 81, 0.5); border-radius: 8px; margin: 10px 0;"><p style="color: #9ca3af; margin: 0;">π΄ Status: Ready</p></div>' | |
| sample_rate, audio_data = audio | |
| # Calculate volume | |
| volume = np.sqrt(np.mean(audio_data**2)) * 100 | |
| volume = min(volume, 100) | |
| # Apply shadow effect | |
| shadow_factor = intensity / 100 | |
| delay_samples = int((delay / 100) * sample_rate * 0.1) # Max 100ms delay | |
| processed_audio = audio_data * (1 - shadow_factor) | |
| if delay_samples > 0 and len(audio_data) > delay_samples: | |
| processed_audio[delay_samples:] += audio_data[:-delay_samples] * shadow_factor | |
| info = get_audio_info(audio) | |
| status_color = "#10b981" if volume > 10 else "#f59e0b" | |
| status_html = f'<div style="padding: 15px; background: rgba(55, 65, 81, 0.5); border-radius: 8px; margin: 10px 0;"><p style="color: #9ca3af; margin: 0;">π’ Status: Processing | Volume: {volume:.1f}%</p></div>' | |
| return (sample_rate, processed_audio), info, volume, status_html | |
| # Event handlers | |
| input_audio.stream( | |
| process_realtime, | |
| inputs=[input_audio, shadow_intensity, delay_amount], | |
| outputs=[output_audio, audio_info, volume_meter, status_display], | |
| time_limit=30, | |
| stream_every=0.1, | |
| api_visibility="public" | |
| ) | |
| start_btn.click( | |
| lambda: gr.Audio(streaming=True), | |
| outputs=[input_audio], | |
| api_visibility="public" | |
| ) | |
| stop_btn.click( | |
| lambda: None, | |
| outputs=[input_audio], | |
| api_visibility="public" | |
| ) | |
| # Footer with shadow effect | |
| gr.HTML(""" | |
| <div style="text-align: center; margin-top: 30px; padding: 20px; background: rgba(30, 30, 30, 0.6); border-radius: 12px; box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.3);"> | |
| <p style="color: #6b7280; font-size: 0.9em;"> | |
| ποΈ Real-time voice processing with shadow effects | Dark mode interface | |
| </p> | |
| </div> | |
| """) | |
| # Launch with custom dark theme and settings | |
| demo.launch( | |
| theme=custom_dark_theme, | |
| css=custom_css, | |
| footer_links=[{"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"}] | |
| ) |