Spaces:
Paused
Paused
| #!/usr/bin/env python3 | |
| """ | |
| SeedVR UI (Gradio) — CLI torchrun | |
| - Upload único: vídeo (.mp4) ou imagem (.png/.jpg/.jpeg/.webp). | |
| - Parâmetros: seed, res_h, res_w, sp_size. | |
| - Executa via torchrun com NUM_GPUS (do ambiente). | |
| - Exibe vídeo se a entrada for vídeo; imagem se for imagem. | |
| """ | |
| import os | |
| import mimetypes | |
| from pathlib import Path | |
| from typing import Optional | |
| import gradio as gr | |
| from services.seed_server import SeedVRServer | |
| # Instância única do servidor (clona repo, baixa modelo, cria symlink) | |
| server = SeedVRServer() | |
| # Paths padrão (para allowed_paths e debug) | |
| OUTPUT_ROOT = Path(os.getenv("OUTPUT_ROOT", "/app/outputs")) | |
| CKPTS_ROOT = Path(os.getenv("CKPTS_ROOT", "/app/ckpts/SeedVR2-3B")) | |
| def _is_video(path: str) -> bool: | |
| mime, _ = mimetypes.guess_type(path) | |
| return (mime or "").startswith("video") or str(path).lower().endswith(".mp4") | |
| def _is_image(path: str) -> bool: | |
| mime, _ = mimetypes.guess_type(path) | |
| if mime and mime.startswith("image"): | |
| return True | |
| return str(path).lower().endswith((".png", ".jpg", ".jpeg", ".webp")) | |
| def ui_infer( | |
| input_path: Optional[str], | |
| seed: int, | |
| res_h: int, | |
| res_w: int, | |
| sp_size: int, | |
| ): | |
| if not input_path or not Path(input_path).exists(): | |
| gr.Warning("Arquivo de entrada ausente ou inválido.") | |
| return None, None | |
| is_vid = _is_video(input_path) | |
| is_img = _is_image(input_path) | |
| if not (is_vid or is_img): | |
| gr.Warning("Tipo de arquivo não suportado. Envie .mp4, .png, .jpg, .jpeg ou .webp.") | |
| return None, None | |
| try: | |
| video_out, image_out, _ = server.run_inference( | |
| file_path=input_path, | |
| seed=int(seed), | |
| res_h=int(res_h), | |
| res_w=int(res_w), | |
| sp_size=int(sp_size), | |
| ) | |
| except Exception as e: | |
| gr.Warning(f"Erro na inferência: {e}") | |
| return None, None | |
| if is_vid: | |
| if video_out and Path(video_out).exists(): | |
| return None, video_out | |
| if image_out and Path(image_out).exists(): | |
| return image_out, None | |
| gr.Warning("Nenhum resultado encontrado.") | |
| return None, None | |
| else: | |
| if image_out and Path(image_out).exists(): | |
| return image_out, None | |
| if video_out and Path(video_out).exists(): | |
| return None, video_out | |
| gr.Warning("Nenhum resultado encontrado.") | |
| return None, None | |
| with gr.Blocks(title="SeedVR (CLI torchrun)") as demo: | |
| gr.Markdown( | |
| "\n".join([ | |
| "# SeedVR — Restauração (CLI torchrun)", | |
| "- Envie um vídeo (.mp4) ou uma imagem (.png/.jpg/.jpeg/.webp).", | |
| "- A execução utiliza torchrun com múltiplas GPUs.", | |
| ]) | |
| ) | |
| with gr.Row(): | |
| inp = gr.File(label="Entrada (vídeo .mp4 ou imagem)", type="filepath") | |
| with gr.Row(): | |
| seed = gr.Number(label="Seed", value=int(os.getenv("SEED", "42")), precision=0) | |
| res_h = gr.Number(label="Altura (res_h)", value=int(os.getenv("RES_H", "720")), precision=0) | |
| res_w = gr.Number(label="Largura (res_w)", value=int(os.getenv("RES_W", "1280")), precision=0) | |
| sp_size = gr.Number(label="sp_size", value=int(os.getenv("SP_SIZE", "4")), precision=0) | |
| run = gr.Button("Restaurar", variant="primary") | |
| out_image = gr.Image(label="Resultado (imagem)") | |
| out_video = gr.Video(label="Resultado (vídeo)") | |
| run.click( | |
| ui_infer, | |
| inputs=[inp, seed, res_h, res_w, sp_size], | |
| outputs=[out_image, out_video], | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch( | |
| server_name=os.getenv("GRADIO_SERVER_NAME", "0.0.0.0"), | |
| server_port=int(os.getenv("GRADIO_SERVER_PORT", os.getenv("PORT", "7860"))), | |
| allowed_paths=[str(OUTPUT_ROOT), str(CKPTS_ROOT)], | |
| show_error=True, | |
| ) | |