"""Whisper Speaker Diarization — Neobrutalism Gradio app (event wiring only).""" import logging import os from pathlib import Path def load_env_file(env_path=".env"): path = Path(env_path) if not path.exists(): return for line in path.read_text(encoding="utf-8").splitlines(): line = line.strip() if not line or line.startswith("#") or "=" not in line: continue key, value = line.split("=", 1) os.environ.setdefault(key.strip(), value.strip().strip('"').strip("'")) load_env_file() from core import cache_manager # noqa: E402 cache_manager.get_model_cache_dir() cache_manager.ensure_dirs() cache_manager.cleanup_old_videos() import gradio as gr # noqa: E402 import gradio_client.utils as _gcu # noqa: E402 # gradio_client 1.5–1.7 raises TypeError on plain bool JSON-schema nodes. # Guard against double-patching: `gradio app.py` reload re-executes this module, # and lambdas resolve their free vars at call time — without the guard, # `_orig_to_py` gets rebound to the previously-installed lambda, causing # infinite recursion when /info is requested. if not getattr(_gcu, "_brut_bool_schema_patched", False): _orig_get_type = _gcu.get_type _orig_to_py = _gcu._json_schema_to_python_type _gcu.get_type = lambda s: "Any" if isinstance(s, bool) else _orig_get_type(s) _gcu._json_schema_to_python_type = lambda s, d=None: ("Any" if s else "None") if isinstance(s, bool) else _orig_to_py(s, d) _gcu._brut_bool_schema_patched = True from core.pipeline_runner import OUTPUT_DIR # noqa: E402 from core.ui import handlers # noqa: E402 from core.ui.layout import build_results_dock, build_stepper # noqa: E402 logging.basicConfig(level=logging.INFO) _STYLES_DIR = Path(__file__).parent / "core" / "styles" _THEME_CSS = (_STYLES_DIR / "neobrutalism.css").read_text(encoding="utf-8") _SEEK_JS = (_STYLES_DIR / "seek.js").read_text(encoding="utf-8") _HEAD = ( '' '' '' f'' ) _THEME = gr.themes.Base(primary_hue="yellow", neutral_hue="stone").set( body_background_fill="#FFF8E7", body_background_fill_dark="#FFF8E7", body_text_color="#000000", body_text_color_dark="#000000", button_primary_background_fill="#FFD23F", button_primary_background_fill_dark="#FFD23F", button_primary_text_color="#000000", button_primary_text_color_dark="#000000", button_secondary_background_fill="#FFFFFF", button_secondary_background_fill_dark="#FFFFFF", button_secondary_text_color="#000000", button_secondary_text_color_dark="#000000", background_fill_primary="#FFFFFF", background_fill_primary_dark="#FFFFFF", background_fill_secondary="#FFF8E7", background_fill_secondary_dark="#FFF8E7", block_background_fill="#FFFFFF", block_background_fill_dark="#FFFFFF", block_label_text_color="#000000", block_label_text_color_dark="#000000", block_title_text_color="#000000", block_title_text_color_dark="#000000", input_background_fill="#FFFFFF", input_background_fill_dark="#FFFFFF", panel_background_fill="#FFFFFF", panel_background_fill_dark="#FFFFFF", border_color_primary="#000000", border_color_primary_dark="#000000", ) # Force light variant always — drop .dark class on root + add .neobrut for CSS scoping _NEOBRUT_BOOTSTRAP = ( "" ) with gr.Blocks(title="Whisper Speaker Diarization", css=_THEME_CSS, head=_HEAD, theme=_THEME) as demo: gr.HTML(_NEOBRUT_BOOTSTRAP) gr.HTML('
WHISPER × DIARIZE v3.1
') with gr.Row(elem_classes="brut-workspace"): with gr.Column(scale=1): stepper = build_stepper() with gr.Column(scale=2): dock = build_results_dock() stepper["yt_btn"].click( handlers.download_youtube_for_ui, [stepper["yt_url"]], [stepper["video_in"], stepper["yt_status"]], ) stepper["run_btn"].click( handlers.run_unified, [stepper["yt_url"], stepper["video_in"], stepper["language"], stepper["num_speakers"]], [ dock["df_out"], dock["csv_out"], dock["srt_out"], dock["sysinfo"], stepper["progress_log"], stepper["error_card"], dock["merged_state"], dock["wav_state"], dock["audio_player"], dock["seek_bus"], stepper["video_in"], ], show_progress="minimal", show_progress_on=[stepper["progress_log"]], ) dock["edit_btn"].click( handlers.enter_edit_mode, [dock["merged_state"]], [dock["df_out"], dock["edit_btn"], dock["apply_btn"], dock["cancel_btn"], dock["edit_mode_state"]], ) dock["cancel_btn"].click( handlers.cancel_edit, [dock["merged_state"]], [dock["df_out"], dock["edit_btn"], dock["apply_btn"], dock["cancel_btn"], dock["edit_mode_state"]], ) dock["apply_btn"].click( handlers.apply_renames, [dock["df_out"], dock["merged_state"]], [dock["df_out"], dock["csv_out"], dock["srt_out"], dock["edit_btn"], dock["apply_btn"], dock["cancel_btn"], dock["edit_mode_state"], dock["merged_state"]], ) dock["df_out"].select( handlers.on_row_select, [dock["merged_state"], dock["edit_mode_state"]], [dock["seek_bus"]], ) demo.queue(default_concurrency_limit=1) if __name__ == "__main__": demo.launch(debug=False, ssr_mode=False, allowed_paths=[str(OUTPUT_DIR)])