vumichien's picture
style: update DataFrame label styling and enhance transcript tab
e90f81e
"""Two-pane brutalist layout: 4-step stepper + tabbed results dock."""
import pandas as pd
import gradio as gr
LANGUAGES = [
("Auto-detect", None), ("English", "en"), ("Japanese", "ja"), ("Chinese", "zh"),
("Spanish", "es"), ("French", "fr"), ("German", "de"), ("Korean", "ko"),
("Portuguese", "pt"), ("Russian", "ru"), ("Italian", "it"), ("Vietnamese", "vi"),
("Arabic", "ar"), ("Hindi", "hi"), ("Indonesian", "id"), ("Dutch", "nl"),
("Polish", "pl"), ("Turkish", "tr"), ("Thai", "th"), ("Ukrainian", "uk"),
]
EXAMPLE_URLS = [
"https://www.youtube.com/watch?v=j7BfEzAFuYc&t=32s",
"https://www.youtube.com/watch?v=-UX0X45sYe4",
"https://www.youtube.com/watch?v=7minSgqi-Gw",
]
def _step_header(num: str, title: str) -> gr.HTML:
return gr.HTML(
f'<div class="brut-step-header">'
f'<span class="brut-step-num">{num}</span>'
f'<h3 class="brut-step-title">{title}</h3>'
f'</div>'
)
def build_stepper(languages=LANGUAGES, example_urls=EXAMPLE_URLS) -> dict:
"""4-card stepper: Source / Configure / Process / Review. Returns named handles."""
handles: dict = {}
# Step 1 — Source
with gr.Group(elem_classes=["brut-step-card", "step-1"]):
_step_header("01", "SOURCE")
handles["yt_url"] = gr.Textbox(label="YouTube URL", lines=1, placeholder="https://www.youtube.com/watch?v=...")
handles["video_in"] = gr.Video(label="Video / Audio file")
gr.Examples(examples=example_urls, inputs=[handles["yt_url"]], label="YouTube examples")
with gr.Accordion("Advanced YouTube download", open=False):
handles["yt_btn"] = gr.Button("Download YouTube video")
handles["yt_status"] = gr.Markdown()
# Step 2 — Configure
with gr.Group(elem_classes=["brut-step-card", "step-2"]):
_step_header("02", "CONFIGURE")
handles["language"] = gr.Dropdown(
choices=languages, value=None,
label="Spoken language (auto-detect if blank)",
)
handles["num_speakers"] = gr.Number(
value=0, precision=0,
label="Number of speakers (0 = auto-detect via pyannote)",
)
# Step 3 — Process
with gr.Group(elem_classes=["brut-step-card", "step-3"]):
_step_header("03", "PROCESS")
handles["run_btn"] = gr.Button("PROCESS", variant="primary", elem_classes="brut-primary")
gr.HTML('<small style="font-family: var(--brut-font-mono); font-size: 12px;">Downloads YouTube URL or processes uploaded file.</small>')
# Step 4 — Review
with gr.Group(elem_classes=["brut-step-card", "step-4"]):
_step_header("04", "REVIEW")
handles["progress_log"] = gr.Markdown(value="", elem_classes="brut-log")
handles["error_card"] = gr.Markdown(value="", elem_classes="brut-error-card")
return handles
def build_results_dock() -> dict:
"""Tabbed results dock: Transcript / Audio / Downloads / Diagnostics."""
handles: dict = {}
with gr.Tabs(elem_classes="brut-tabs"):
with gr.TabItem("Transcript"):
handles["df_out"] = gr.DataFrame(
label="Transcript",
value=pd.DataFrame(columns=["Start", "End", "Speaker", "Text"]),
show_label=True,
row_count=(0, "dynamic"),
wrap=True,
elem_classes="brut-df",
interactive=False,
)
with gr.Row():
handles["edit_btn"] = gr.Button("EDIT SPEAKERS")
handles["apply_btn"] = gr.Button("APPLY RENAMES", variant="primary", visible=False)
handles["cancel_btn"] = gr.Button("CANCEL", visible=False)
with gr.TabItem("Audio"):
handles["audio_player"] = gr.Audio(
label="Converted WAV (16kHz mono)",
interactive=False,
show_download_button=True,
elem_id="brut-audio-mount",
elem_classes="brut-audio-player",
value=None,
)
handles["seek_bus"] = gr.HTML(value="", elem_id="brut-seek-bus")
with gr.TabItem("Downloads"):
handles["csv_out"] = gr.File(label="Download CSV")
handles["srt_out"] = gr.File(label="Download SRT")
with gr.TabItem("Diagnostics"):
handles["sysinfo"] = gr.Markdown()
handles["merged_state"] = gr.State(value=None)
handles["edit_mode_state"] = gr.State(value=False)
handles["wav_state"] = gr.State(value=None)
return handles