Spaces:
Running
Running
| import gradio as gr | |
| from model.analyzer import analyze_content | |
| import asyncio | |
| import time | |
| import httpx | |
| import subprocess | |
| import atexit | |
| # Start the API server | |
| def start_api_server(): | |
| # Start uvicorn in a subprocess | |
| process = subprocess.Popen(["uvicorn", "script_search_api:app", "--reload"]) | |
| return process | |
| # Stop the API server | |
| def stop_api_server(process): | |
| process.terminate() | |
| # Register the exit handler | |
| api_process = start_api_server() | |
| atexit.register(stop_api_server, api_process) | |
| custom_css = """ | |
| * { | |
| font-family: 'Inter', system-ui, sans-serif; | |
| transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| .gradio-container { | |
| background: #0a0a0a !important; | |
| color: #fff !important; | |
| min-height: 100vh; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| /* Subtle Animated Background */ | |
| .gradio-container::before { | |
| content: ''; | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| background: | |
| linear-gradient(125deg, | |
| #0a0a0a 0%, | |
| rgba(218, 165, 32, 0.03) 30%, | |
| rgba(218, 165, 32, 0.05) 50%, | |
| rgba(218, 165, 32, 0.03) 70%, | |
| #0a0a0a 100%); | |
| animation: subtleGradient 20s ease infinite; | |
| background-size: 400% 400%; | |
| z-index: 0; | |
| } | |
| /* Premium Particles Effect */ | |
| .gradio-container::after { | |
| content: ''; | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: radial-gradient(circle at center, transparent 0%, #0a0a0a 70%), | |
| url("data:image/svg+xml,%3Csvg width='100' height='100' viewBox='0 0 100 100' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='50' cy='50' r='1' fill='rgba(218, 165, 32, 0.08)'/%3E%3C/svg%3E"); | |
| opacity: 0.3; | |
| animation: floatingParticles 30s linear infinite; | |
| z-index: 1; | |
| } | |
| /* Luxurious Header */ | |
| .treat-title { | |
| text-align: center; | |
| padding: 3rem 1rem; | |
| position: relative; | |
| overflow: hidden; | |
| z-index: 2; | |
| background: linear-gradient(180deg, | |
| rgba(218, 165, 32, 0.05), | |
| transparent 70%); | |
| } | |
| .treat-title::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 50%; | |
| width: 60%; | |
| height: 1px; | |
| background: linear-gradient(90deg, | |
| transparent, | |
| rgba(218, 165, 32, 0.3), | |
| transparent); | |
| transform: translateX(-50%); | |
| animation: luxuryScan 5s ease-in-out infinite; | |
| } | |
| .treat-title h1 { | |
| font-size: 4.5rem; | |
| font-weight: 800; | |
| background: linear-gradient(135deg, | |
| #996515 0%, | |
| #DAA520 25%, | |
| #FFD700 50%, | |
| #DAA520 75%, | |
| #996515 100%); | |
| background-size: 200% auto; | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| margin-bottom: 0.5rem; | |
| letter-spacing: -0.05em; | |
| animation: goldenFlow 8s ease infinite; | |
| position: relative; | |
| } | |
| .treat-title h1::after { | |
| content: attr(data-text); | |
| position: absolute; | |
| left: 0; | |
| top: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: linear-gradient(135deg, | |
| transparent 0%, | |
| rgba(218, 165, 32, 0.4) 50%, | |
| transparent 100%); | |
| background-size: 200% auto; | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| opacity: 0.5; | |
| animation: premiumGlow 4s ease-in-out infinite; | |
| } | |
| /* Premium Content Areas */ | |
| .tabs { | |
| background: rgba(10, 10, 10, 0.95); | |
| border: 1px solid rgba(218, 165, 32, 0.15); | |
| border-radius: 16px; | |
| padding: 1rem; | |
| margin: 0 1rem 2rem 1rem; | |
| position: relative; | |
| z-index: 2; | |
| backdrop-filter: blur(10px); | |
| box-shadow: 0 0 30px rgba(218, 165, 32, 0.05); | |
| } | |
| .tabs::before { | |
| content: ''; | |
| position: absolute; | |
| top: -1px; | |
| left: -1px; | |
| right: -1px; | |
| bottom: -1px; | |
| background: linear-gradient(45deg, | |
| rgba(218, 165, 32, 0.1), | |
| transparent, | |
| rgba(218, 165, 32, 0.1)); | |
| border-radius: 16px; | |
| z-index: -1; | |
| animation: luxuryBorder 6s ease-in-out infinite; | |
| } | |
| .content-area { | |
| background: rgba(10, 10, 10, 0.95) !important; | |
| border: 1px solid rgba(218, 165, 32, 0.15) !important; | |
| border-radius: 12px !important; | |
| padding: 1.5rem !important; | |
| backdrop-filter: blur(10px); | |
| position: relative; | |
| } | |
| /* Premium Input Fields */ | |
| .gradio-textbox textarea { | |
| background: rgba(10, 10, 10, 0.9) !important; | |
| border: 1px solid rgba(218, 165, 32, 0.2) !important; | |
| border-radius: 8px !important; | |
| color: rgba(255, 255, 255, 0.9) !important; | |
| font-size: 0.95rem !important; | |
| line-height: 1.6 !important; | |
| padding: 1rem !important; | |
| } | |
| .gradio-textbox textarea:focus { | |
| border-color: #DAA520 !important; | |
| box-shadow: 0 0 20px rgba(218, 165, 32, 0.1) !important; | |
| background: rgba(10, 10, 10, 0.95) !important; | |
| transform: translateY(-2px); | |
| } | |
| /* Luxury Buttons */ | |
| .gradio-button { | |
| background: linear-gradient(45deg, | |
| #996515, | |
| #DAA520, | |
| #FFD700, | |
| #DAA520) !important; | |
| background-size: 200% auto !important; | |
| border: none !important; | |
| border-radius: 8px !important; | |
| color: #0a0a0a !important; | |
| font-weight: 600 !important; | |
| font-size: 0.95rem !important; | |
| padding: 0.75rem 1.5rem !important; | |
| letter-spacing: 0.025em !important; | |
| position: relative; | |
| overflow: hidden; | |
| transition: all 0.3s ease !important; | |
| animation: goldenFlow 4s ease infinite; | |
| } | |
| .gradio-button:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 5px 20px rgba(218, 165, 32, 0.2) !important; | |
| } | |
| /* Premium Footer */ | |
| .footer { | |
| text-align: center; | |
| padding: 2rem 0; | |
| margin-top: 3rem; | |
| font-size: 1.0rem; | |
| position: relative; | |
| z-index: 2; | |
| } | |
| .footer p { | |
| color: rgba(218, 165, 32, 0.8); | |
| } | |
| .footer .heart { | |
| color: #DAA520; | |
| animation: luxuryPulse 2s ease infinite; | |
| } | |
| .footer .name { | |
| color: #DAA520; | |
| text-decoration: none; | |
| transition: all 0.3s ease; | |
| padding: 0 4px; | |
| } | |
| .footer .name:hover { | |
| color: #FFD700; | |
| } | |
| footer { | |
| visibility: hidden; | |
| } | |
| /* Premium Animations */ | |
| @keyframes subtleGradient { | |
| 0% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| 100% { background-position: 0% 50%; } | |
| } | |
| @keyframes floatingParticles { | |
| 0% { transform: translateY(0); } | |
| 100% { transform: translateY(-100%); } | |
| } | |
| @keyframes luxuryScan { | |
| 0% { transform: translateX(-150%) scaleX(0.3); opacity: 0; } | |
| 50% { transform: translateX(-50%) scaleX(1); opacity: 0.5; } | |
| 100% { transform: translateX(50%) scaleX(0.3); opacity: 0; } | |
| } | |
| @keyframes goldenFlow { | |
| 0% { background-position: 0% 50%; } | |
| 50% { background-position: 100% 50%; } | |
| 100% { background-position: 0% 50%; } | |
| } | |
| @keyframes premiumGlow { | |
| 0% { opacity: 0.2; transform: scale(1); } | |
| 50% { opacity: 0.4; transform: scale(1.01); } | |
| 100% { opacity: 0.2; transform: scale(1); } | |
| } | |
| @keyframes luxuryBorder { | |
| 0% { opacity: 0.3; } | |
| 50% { opacity: 0.7; } | |
| 100% { opacity: 0.3; } | |
| } | |
| @keyframes luxuryPulse { | |
| 0% { transform: scale(1); opacity: 0.8; } | |
| 50% { transform: scale(1.1); opacity: 1; } | |
| 100% { transform: scale(1); opacity: 0.8; } | |
| } | |
| """ | |
| # Start the API server | |
| def start_api_server(): | |
| # Start uvicorn in a subprocess | |
| process = subprocess.Popen(["uvicorn", "script_search_api:app", "--reload"]) | |
| return process | |
| # Stop the API server | |
| def stop_api_server(process): | |
| process.terminate() | |
| # Register the exit handler | |
| api_process = start_api_server() | |
| atexit.register(stop_api_server, api_process) | |
| async def analyze_with_progress(movie_name, progress=gr.Progress()): | |
| """Handle analysis with progress updates in Gradio""" | |
| try: | |
| async with httpx.AsyncClient(timeout=60.0) as client: | |
| # Start the analysis | |
| response = await client.get( | |
| "http://localhost:8000/api/start_analysis", | |
| params={"movie_name": movie_name} | |
| ) | |
| response.raise_for_status() | |
| task_id = response.json()["task_id"] | |
| # Poll for progress | |
| while True: | |
| progress_response = await client.get( | |
| f"http://localhost:8000/api/progress/{task_id}" | |
| ) | |
| progress_response.raise_for_status() | |
| status = progress_response.json() | |
| # Update Gradio progress | |
| progress(status["progress"], desc=status["status"]) | |
| if status["is_complete"]: | |
| if status["error"]: | |
| return f"Error: {status['error']}" | |
| elif status["result"]: | |
| triggers = status["result"].get("detected_triggers", []) | |
| if not triggers or triggers == ["None"]: | |
| return "β No triggers detected in the content." | |
| else: | |
| trigger_list = "\n".join([f"β’ {trigger}" for trigger in triggers]) | |
| return f"β Triggers Detected:\n{trigger_list}" | |
| break | |
| await asyncio.sleep(0.5) | |
| except Exception as e: | |
| return f"Error: {str(e)}" | |
| def analyze_with_loading(text, progress=gr.Progress()): | |
| """ | |
| Synchronous wrapper for the async analyze_content function with smooth progress updates | |
| """ | |
| # Initialize progress | |
| progress(0, desc="Starting analysis...") | |
| # Initial setup phase - smoother progression | |
| for i in range(25): | |
| time.sleep(0.04) # Slightly longer sleep for smoother animation | |
| progress((i + 1) / 100, desc="Initializing analysis...") | |
| # Pre-processing phase | |
| for i in range(25, 45): | |
| time.sleep(0.03) | |
| progress((i + 1) / 100, desc="Pre-processing content...") | |
| # Perform analysis | |
| progress(0.45, desc="Analyzing content...") | |
| try: | |
| result = asyncio.run(analyze_content(text)) | |
| # Analysis progress simulation | |
| for i in range(45, 75): | |
| time.sleep(0.03) | |
| progress((i + 1) / 100, desc="Processing results...") | |
| except Exception as e: | |
| return f"Error during analysis: {str(e)}" | |
| # Final processing with smooth progression | |
| for i in range(75, 100): | |
| time.sleep(0.02) | |
| progress((i + 1) / 100, desc="Finalizing results...") | |
| # Format the results | |
| triggers = result["detected_triggers"] | |
| if triggers == ["None"]: | |
| return "β No triggers detected in the content." | |
| else: | |
| trigger_list = "\n".join([f"β’ {trigger}" for trigger in triggers]) | |
| return f"β Triggers Detected:\n{trigger_list}" | |
| # Update the Gradio interface with new styling | |
| import gradio as gr | |
| from model.analyzer import analyze_content | |
| import asyncio | |
| import time | |
| import httpx | |
| import subprocess | |
| import atexit | |
| # Keep your existing CSS and server setup code... | |
| # [Previous code until the interface definition remains the same] | |
| # Update the Gradio interface with fixed button handling | |
| with gr.Blocks(css=custom_css, theme=gr.themes.Monochrome()) as iface: | |
| # Title section | |
| gr.HTML(""" | |
| <div class="treat-title"> | |
| <h1 data-text="TREAT R1">TREAT R1</h1> | |
| <p>Trigger Recognition for Enjoyable and Appropriate Television</p> | |
| </div> | |
| """) | |
| with gr.Tabs() as tabs: | |
| with gr.Tab("Content Analysis"): # Changed from TabItem to Tab | |
| with gr.Column(): | |
| input_text = gr.Textbox( | |
| label="ANALYZE CONTENT", | |
| placeholder="Enter the content you want to analyze...", | |
| lines=8 | |
| ) | |
| analyze_btn = gr.Button("β¨ Analyze") | |
| with gr.Tab("Movie Search"): # Changed from TabItem to Tab | |
| with gr.Column(): | |
| search_query = gr.Textbox( | |
| label="SEARCH MOVIES", | |
| placeholder="Type a movie title to search...", | |
| lines=1 | |
| ) | |
| search_button = gr.Button("π Search") | |
| output_text = gr.Textbox( | |
| label="ANALYSIS RESULTS", | |
| lines=5, | |
| interactive=False | |
| ) | |
| status_text = gr.Markdown( | |
| value="" | |
| ) | |
| # Define click events | |
| analyze_btn.click( | |
| fn=analyze_with_loading, | |
| inputs=input_text, | |
| outputs=output_text | |
| ) | |
| search_button.click( | |
| fn=analyze_with_progress, | |
| inputs=search_query, | |
| outputs=output_text | |
| ) | |
| gr.HTML(""" | |
| <div class="footer"> | |
| <p>Made with <span class="heart">π</span> by <a href="https://www.linkedin.com/in/kubermehta/" target="_blank">Kuber Mehta</a></p> | |
| </div> | |
| """) | |
| if __name__ == "__main__": | |
| iface.launch( | |
| share=False, | |
| debug=True, | |
| show_error=True | |
| ) |