import gradio as gr from app.ui.styles import CSS from app.config import CONFIG def _status_html(msg: str) -> str: """Wrap a status message in the styled status-bar div.""" return f'
{msg}
' def build_ui(assistant) -> gr.Blocks: auto_start_js = """ function() { setInterval(function() { let clickTarget = function(btn) { let text = (btn.textContent || btn.innerText || '').toLowerCase().trim(); if (text === 'click to access webcam' || text === 'record') { btn.click(); } }; // Check Shadow DOMs document.querySelectorAll('*').forEach(function(el) { if (el.shadowRoot) { el.shadowRoot.querySelectorAll('button').forEach(clickTarget); } }); // Check regular DOM document.querySelectorAll('button').forEach(clickTarget); }, 1000); // Check every second indefinitely } """ with gr.Blocks(title=f"{CONFIG.APP_NAME} v{CONFIG.APP_VERSION}", js=auto_start_js) as demo: gr.HTML('
') status_bar = gr.HTML(_status_html("✅ Ready — Press D to describe")) gr.Markdown(f"# 👁️ {CONFIG.APP_NAME}") rt_state = gr.State(True) with gr.Row(): with gr.Column(scale=1): # Controls at the top with gr.Row(): describe_btn = gr.Button("🔍 Describe (D)", variant="primary", elem_id="btn-describe") realtime_btn = gr.Button("⚫ Stop Realtime (R)", variant="secondary", elem_id="btn-realtime") with gr.Row(): task_radio = gr.Radio( choices=["Quick Glance", "Detailed Scene", "Immersive Description", "Read Text"], value="Detailed Scene", label="Mode" ) voice_dropdown = gr.Dropdown( choices=["English (US) - Aria", "Hindi - Swara"], value="English (US) - Aria", label="Voice" ) webcam = gr.Image(label="📷 Camera", type="numpy", sources=["webcam"], streaming=True) with gr.Accordion("Upload Image", open=False): upload = gr.Image(label="📁 Upload", type="numpy", sources=["upload"]) with gr.Column(scale=1): caption_box = gr.Textbox(label="📝 Description", lines=6, interactive=False) audio_player = gr.Audio(label="🔊 Audio", type="filepath", autoplay=True) with gr.Row(): repeat_btn = gr.Button("🔁 Repeat (P)", elem_id="btn-repeat") stop_btn = gr.Button("⏹ Stop (Esc)", elem_id="btn-stop") components = { "webcam": webcam, "upload": upload, "task_radio": task_radio, "voice_dropdown": voice_dropdown, "describe_btn": describe_btn, "realtime_btn": realtime_btn, "caption_box": caption_box, "audio_player": audio_player, "status_bar": status_bar, "rt_state": rt_state, "repeat_btn": repeat_btn, "stop_btn": stop_btn } from app.ui.events import wire_events wire_events(demo, components, assistant) return demo