Spaces:
Sleeping
Sleeping
| # ui.py | |
| """Reusable Gradio components shared across modes.""" | |
| from __future__ import annotations | |
| from dataclasses import dataclass | |
| import gradio as gr | |
| def preset_bar(label: str = "Preset") -> gr.Radio: | |
| """Fast / Balanced / Quality radio. Use as a single component.""" | |
| return gr.Radio( | |
| choices=["Fast", "Balanced", "Quality"], | |
| value="Balanced", | |
| label=label, | |
| container=True, | |
| info="Fast: distilled 8 steps · Balanced: two-stage 30+4 · Quality: HQ res_2s sampler", | |
| ) | |
| def status_banner() -> gr.HTML: | |
| """Status banner: stage chips + progress + memory.""" | |
| return gr.HTML( | |
| value=_render_idle(), | |
| elem_classes=["status-banner"], | |
| ) | |
| def _render_idle() -> str: | |
| return ( | |
| '<div class="status-card status-idle">' | |
| '<div class="status-row"><span class="status-dot"></span>' | |
| '<span class="status-label">Idle</span></div></div>' | |
| ) | |
| def render_status( | |
| stage_index: int, | |
| stage_label: str, | |
| step: int, | |
| total_steps: int, | |
| elapsed_s: float, | |
| eta_s: float, | |
| memory_text: str = "", | |
| ) -> str: | |
| """Render a status banner HTML string for the current event.""" | |
| pct = 0 if total_steps <= 0 else int(100 * step / total_steps) | |
| return ( | |
| f'<div class="status-card">' | |
| f' <div class="status-row">' | |
| f' <span class="status-stage">Stage {stage_index} · {stage_label}</span>' | |
| f' <span class="status-meta">Step {step}/{total_steps} · ' | |
| f" {_fmt_secs(elapsed_s)} elapsed · ~{_fmt_secs(eta_s)} remaining</span>" | |
| f" </div>" | |
| f' <div class="status-bar"><div class="status-fill" style="width:{pct}%"></div></div>' | |
| f' <div class="status-mem">{memory_text}</div>' | |
| f"</div>" | |
| ) | |
| def _fmt_secs(secs: float) -> str: | |
| secs = int(max(0, secs)) | |
| if secs < 60: | |
| return f"{secs}s" | |
| return f"{secs // 60}m {secs % 60}s" | |
| CAMERA_LORAS: list[str] = [ | |
| "none", | |
| "static", | |
| "dolly-in", | |
| "dolly-out", | |
| "dolly-left", | |
| "dolly-right", | |
| "jib-up", | |
| "jib-down", | |
| ] | |
| IC_LORAS_BY_MODE: dict[str, list[str]] = { | |
| "t2v": [], | |
| "a2v": [], | |
| "i2v": ["union", "pose-control"], | |
| "lipsync": ["pose-control"], | |
| "keyframe": ["union"], | |
| "style": ["motion-track", "union"], | |
| } | |
| class LoRAComponents: | |
| camera_lora: gr.Dropdown | |
| camera_strength: gr.Slider | |
| detailer_on: gr.Checkbox | |
| detailer_strength: gr.Slider | |
| ic_lora: gr.Dropdown | None | |
| ic_strength: gr.Slider | None | |
| pose_on: gr.Checkbox | None | |
| def lora_chrome(mode: str) -> LoRAComponents: | |
| """Categorized LoRA controls for a given mode (camera + detailer + IC + pose). | |
| Only LoRAs relevant to the mode are surfaced. Distilled LoRA is auto-applied | |
| by the workflow when the Fast preset is chosen — not exposed here. | |
| """ | |
| with gr.Group(): | |
| gr.Markdown("**📷 Camera Movement**") | |
| camera_lora = gr.Dropdown( | |
| choices=CAMERA_LORAS, | |
| value="none", | |
| label="Camera", | |
| info="Mutually exclusive — pick one camera direction or none.", | |
| ) | |
| camera_strength = gr.Slider( | |
| minimum=0.0, | |
| maximum=1.5, | |
| value=0.8, | |
| step=0.05, | |
| label="Camera strength", | |
| visible=True, | |
| ) | |
| with gr.Group(): | |
| gr.Markdown("**✨ Detailer**") | |
| detailer_on = gr.Checkbox(label="Apply IC-LoRA-Detailer", value=False) | |
| detailer_strength = gr.Slider( | |
| minimum=0.0, | |
| maximum=1.0, | |
| value=0.5, | |
| step=0.05, | |
| label="Detailer strength", | |
| ) | |
| ic_lora = ic_strength = pose_on = None | |
| ic_options = IC_LORAS_BY_MODE.get(mode, []) | |
| if ic_options: | |
| with gr.Group(): | |
| gr.Markdown("**🎯 Image Conditioning**") | |
| ic_lora = gr.Dropdown( | |
| choices=["none"] + ic_options, | |
| value=ic_options[0] if ic_options else "none", | |
| label="IC-LoRA", | |
| ) | |
| ic_strength = gr.Slider( | |
| minimum=0.0, | |
| maximum=1.0, | |
| value=0.5, | |
| step=0.05, | |
| label="IC strength", | |
| ) | |
| if mode in ("i2v", "lipsync"): | |
| with gr.Group(): | |
| gr.Markdown("**🚶 Pose Control**") | |
| pose_on = gr.Checkbox(label="Apply IC-LoRA-Pose-Control", value=False) | |
| return LoRAComponents( | |
| camera_lora=camera_lora, | |
| camera_strength=camera_strength, | |
| detailer_on=detailer_on, | |
| detailer_strength=detailer_strength, | |
| ic_lora=ic_lora, | |
| ic_strength=ic_strength, | |
| pose_on=pose_on, | |
| ) | |