Carlex22222 commited on
Commit
d4386a4
·
verified ·
1 Parent(s): b9e2818

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +107 -143
app.py CHANGED
@@ -1,180 +1,144 @@
1
- # app.py (Interface com Abas para SeedVR2 e VINCIE)
2
 
3
  import gradio as gr
4
  import os
5
- import uuid
6
- import shutil
7
  import subprocess
8
- import mimetypes
 
 
 
 
 
9
 
10
- # --- Diretórios Base ---
11
  SEEDVR_DIR = "/app/SeedVR"
12
  VINCIE_DIR = "/app/VINCIE"
 
13
 
14
- # --- Função de Logging em Tempo Real (Reutilizável) ---
15
- def stream_process_to_gradio(command, working_dir):
16
- env = os.environ.copy()
17
- env["PYTHONUNBUFFERED"] = "1"
18
-
19
- log_output = f"Executando no diretório: {working_dir}\n"
20
- log_output += f"Comando: {' '.join(command)}\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
- process = subprocess.Popen(
23
- command,
24
- cwd=working_dir,
25
- stdout=subprocess.PIPE,
26
- stderr=subprocess.STDOUT,
27
- text=True,
28
- encoding='utf-8',
29
- env=env
30
- )
31
 
32
- # Loop para capturar e transmitir a saída
33
  while True:
34
  output = process.stdout.readline()
35
- if output == '' and process.poll() is not None:
36
- break
37
- if output:
38
- log_output += output
39
- yield log_output
40
 
41
- return_code = process.poll()
42
- if return_code != 0:
43
- raise gr.Error(f"A inferência falhou com o código {return_code}. Verifique os logs.")
44
 
45
- # --- Lógica de Inferência para SeedVR2 ---
46
- def run_seedvr2_inference(input_media, seed, res_h, res_w):
47
- if input_media is None: raise gr.Error("Por favor, faça o upload de um arquivo para o SeedVR2.")
48
-
49
  job_id = str(uuid.uuid4())
50
- input_dir = os.path.join("/app", "temp_inputs", job_id)
51
- output_dir = os.path.join("/app", "temp_outputs", job_id)
52
- os.makedirs(input_dir, exist_ok=True); os.makedirs(output_dir, exist_ok=True)
53
-
54
- shutil.copy(input_media, input_dir)
55
 
56
  input_folder_relative = os.path.relpath(input_dir, SEEDVR_DIR)
57
  output_folder_relative = os.path.relpath(output_dir, SEEDVR_DIR)
 
58
 
59
- command = [
60
- "torchrun", "--nproc-per-node=4", "projects/inference_seedvr2_3b.py",
61
- "--video_path", input_folder_relative, "--output_dir", output_folder_relative,
62
- "--seed", str(seed), "--res_h", str(res_h), "--res_w", str(res_w),
63
- ]
64
-
65
- # Limpa as saídas antes de começar
66
- yield None, None, "Iniciando inferência do SeedVR2..."
67
-
68
- # Stream dos logs
69
- for log_update in stream_process_to_gradio(command, SEEDVR_DIR):
70
- yield None, None, log_update
71
-
72
- # Encontra o arquivo de resultado
73
- output_files = [f for f in os.listdir(output_dir) if f.endswith(('.mp4', '.png', '.jpg', '.jpeg'))]
74
- if not output_files: raise gr.Error("Nenhum arquivo de saída do SeedVR2 foi encontrado.")
75
- result_path = os.path.join(output_dir, output_files[0])
76
 
77
- media_type, _ = mimetypes.guess_type(result_path)
78
- if media_type and media_type.startswith("image"):
79
- yield result_path, None, "Concluído!"
80
- else:
81
- yield None, result_path, "Concluído!"
82
 
83
- # --- Lógica de Inferência para VINCIE ---
84
- def run_vincie_inference(input_video, prompt, seed, steps, cfg_scale):
85
- if input_video is None: raise gr.Error("Por favor, faça o upload de um vídeo para o VINCIE.")
 
86
 
87
  job_id = str(uuid.uuid4())
88
- temp_dir = os.path.join("/app", "temp_vincie", job_id)
89
- os.makedirs(temp_dir, exist_ok=True)
90
 
91
- input_video_path = os.path.join(temp_dir, os.path.basename(input_video))
92
- shutil.copy(input_video, input_video_path)
 
93
 
94
- # O VINCIE salva a saída em um diretório com o mesmo nome do vídeo de entrada
95
- output_path = os.path.join(temp_dir, "results")
96
-
97
- command = [
98
- "python", "inference.py",
99
- "--config", "configs/vincie_1024.yaml",
100
- "--pretrained_model_path", "./pretrained_models",
101
- "--input_video", input_video_path,
102
- "--output_folder", output_path,
103
- "--prompt", str(prompt),
104
- "--seed", str(seed),
105
- "--num_inference_steps", str(int(steps)),
106
- "--guidance_scale", str(cfg_scale),
107
- ]
108
 
109
- # Limpa a saída antes de começar
110
- yield None, "Iniciando inferência do VINCIE..."
111
-
112
- # Stream dos logs
113
- for log_update in stream_process_to_gradio(command, VINCIE_DIR):
114
- yield None, log_update
115
-
116
- # Encontra o arquivo de resultado (VINCIE tem uma estrutura de saída aninhada)
117
- result_files = list(os.walk(output_path))
118
- found_file = None
119
- for root, _, files in result_files:
120
- for file in files:
121
- if file.endswith('.mp4'):
122
- found_file = os.path.join(root, file)
123
- break
124
- if found_file:
125
- break
126
-
127
- if not found_file: raise gr.Error("Nenhum arquivo de saída do VINCIE foi encontrado.")
128
-
129
- yield found_file, "Concluído!"
130
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
- # --- Interface Gradio com Abas ---
133
  with gr.Blocks() as demo:
134
- gr.Markdown("# 🚀 Interface de Inferência Unificada")
135
 
136
  with gr.Tabs():
137
- with gr.TabItem("SeedVR2 (Restauração de Vídeo/Imagem)"):
 
138
  with gr.Row():
139
  with gr.Column(scale=1):
140
- seedvr2_input = gr.Video(label="Upload de Vídeo ou Imagem")
141
- seedvr2_seed = gr.Number(value=666, label="Seed")
142
- with gr.Accordion("Configurações Avançadas", open=False):
143
- seedvr2_h = gr.Number(value=720, label="Altura")
144
- seedvr2_w = gr.Number(value=1280, label="Largura")
145
- seedvr2_button = gr.Button("Executar SeedVR2", variant="primary")
146
  with gr.Column(scale=2):
147
- seedvr2_img_out = gr.Image(label="Saída de Imagem")
148
- seedvr2_vid_out = gr.Video(label="Saída de Vídeo")
149
- seedvr2_logs = gr.Textbox(label="Logs em Tempo Real", lines=10, autoscroll=True)
150
-
151
- seedvr2_button.click(
152
- fn=run_seedvr2_inference,
153
- inputs=[seedvr2_input, seedvr2_seed, seedvr2_h, seedvr2_w],
154
- outputs=[seedvr2_img_out, seedvr2_vid_out, seedvr2_logs]
155
- )
156
- gr.Examples(
157
- examples=[["./SeedVR/01.mp4"], ["./SeedVR/02.mp4"]],
158
- inputs=[seedvr2_input]
159
- )
160
-
161
- with gr.TabItem("VINCIE (Edição de Vídeo com Prompt)"):
162
  with gr.Row():
163
  with gr.Column(scale=1):
164
- vincie_input = gr.Video(label="Upload de Vídeo")
165
- vincie_prompt = gr.Textbox(label="Prompt", lines=3, placeholder="Ex: a man wearing a spacesuit")
166
- vincie_seed = gr.Number(label="Seed", value=1234)
167
- vincie_steps = gr.Slider(label="Passos de Inferência", minimum=1, maximum=100, value=50, step=1)
168
- vincie_cfg = gr.Slider(label="Escala do CFG", minimum=1.0, maximum=15.0, value=7.5, step=0.5)
169
- vincie_button = gr.Button("Executar VINCIE", variant="primary")
170
  with gr.Column(scale=2):
171
- vincie_vid_out = gr.Video(label="Saída de Vídeo")
172
- vincie_logs = gr.Textbox(label="Logs em Tempo Real", lines=10, autoscroll=True)
173
-
174
- vincie_button.click(
175
- fn=run_vincie_inference,
176
- inputs=[vincie_input, vincie_prompt, vincie_seed, vincie_steps, vincie_cfg],
177
- outputs=[vincie_vid_out, vincie_logs]
178
- )
179
-
180
- demo.queue(max_size=10).launch()
 
1
+ # app.py (Interface final com 3 abas: SeedVR, V-INT Edit, V-INT Pipeline)
2
 
3
  import gradio as gr
4
  import os
 
 
5
  import subprocess
6
+ import shutil
7
+ import uuid
8
+ from huggingface_hub import snapshot_download
9
+ import spaces
10
+
11
+ # --- 1. CONFIGURAÇÃO E DOWNLOAD DOS MODELOS ---
12
 
 
13
  SEEDVR_DIR = "/app/SeedVR"
14
  VINCIE_DIR = "/app/VINCIE"
15
+ HF_TOKEN = os.environ.get("HF_TOKEN")
16
 
17
+ @spaces.GPU
18
+ def download_models():
19
+ """Baixa os modelos para SeedVR e V-INT se eles não existirem."""
20
+ # Download do SeedVR
21
+ if not os.path.exists(os.path.join(SEEDVR_DIR, "ckpts", "seedvr2_ema_3b.pth")):
22
+ print("Baixando modelo do SeedVR-3B...")
23
+ snapshot_download(repo_id="ByteDance-Seed/SeedVR2-3B", local_dir=os.path.join(SEEDVR_DIR, "ckpts"), token=HF_TOKEN, local_dir_use_symlinks=False)
24
+ else: print("Modelo do SeedVR já existe.")
25
+
26
+ # Download do V-INT
27
+ if not os.path.exists(os.path.join(VINCIE_DIR, "ckpt", "VINCIE-3B")):
28
+ print("Baixando modelo do VINCIE-3B...")
29
+ snapshot_download(repo_id="ByteDance-Seed/VINCIE-3B", local_dir=os.path.join(VINCIE_DIR, "ckpt", "VINCIE-3B"), token=HF_TOKEN, local_dir_use_symlinks=False)
30
+ else: print("Modelo do VINCIE já existe.")
31
+
32
+ # Download de assets e configs do V-INT (para os exemplos)
33
+ if not os.path.exists(os.path.join(VINCIE_DIR, "assets", "woman_pineapple.png")):
34
+ print("Baixando assets e configs do V-INT...")
35
+ snapshot_download(repo_id="ByteDance-Seed/VINCIE", repo_type="space", local_dir=VINCIE_DIR, token=HF_TOKEN, allow_patterns=["assets/*", "configs/*"], local_dir_use_symlinks=False)
36
+ else: print("Assets e configs do V-INT já existem.")
37
+
38
+ download_models()
39
+
40
+ # --- 2. LÓGICA DE INFERÊNCIA ---
41
+
42
+ def run_subprocess_with_logs(command, cwd):
43
+ """Função genérica para rodar um subprocesso e streamar os logs para o Gradio."""
44
+ log_output = f"Executando comando:\n{' '.join(command)}\n\n"
45
+ yield [], log_output
46
 
47
+ env = os.environ.copy(); env["PYTHONUNBUFFERED"] = "1"
48
+ process = subprocess.Popen(command, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, encoding='utf-8', env=env)
 
 
 
 
 
 
 
49
 
 
50
  while True:
51
  output = process.stdout.readline()
52
+ if output == '' and process.poll() is not None: break
53
+ if output: log_output += output; yield [], log_output
 
 
 
54
 
55
+ if process.poll() != 0: raise gr.Error("A inferência falhou. Verifique os logs.")
 
 
56
 
57
+ def run_seedvr_inference(video_path, seed):
58
+ # (Lógica específica do SeedVR)
59
+ if video_path is None: raise gr.Error("Por favor, faça o upload de um arquivo para o SeedVR.")
 
60
  job_id = str(uuid.uuid4())
61
+ input_dir = os.path.join("/app", "temp_inputs", job_id); os.makedirs(input_dir, exist_ok=True)
62
+ output_dir = os.path.join("/app", "temp_outputs", job_id); os.makedirs(output_dir, exist_ok=True)
63
+ shutil.copy(video_path, input_dir)
 
 
64
 
65
  input_folder_relative = os.path.relpath(input_dir, SEEDVR_DIR)
66
  output_folder_relative = os.path.relpath(output_dir, SEEDVR_DIR)
67
+ command = ["torchrun", "--nproc-per-node=4", "projects/inference_seedvr2_3b.py", "--video_path", input_folder_relative, "--output_dir", output_folder_relative, "--seed", str(seed), "--res_h", "720", "--res_w", "1280"]
68
 
69
+ for gallery, logs in run_subprocess_with_logs(command, SEEDVR_DIR):
70
+ yield None, logs # Retorna None para o output enquanto os logs são atualizados
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
+ output_files = [os.path.join(output_dir, f) for f in os.listdir(output_dir) if f.endswith(('.mp4', '.png'))]
73
+ if not output_files: raise gr.Error("Nenhum arquivo de saída encontrado.")
74
+ yield output_files[0], logs
 
 
75
 
76
+ def run_vincie_edit_inference(files, prompts_str):
77
+ # (Lógica específica para o modo de EDIÇÃO do V-INT)
78
+ if not files: raise gr.Error("Por favor, faça o upload de uma imagem para editar.")
79
+ if not prompts_str: raise gr.Error("Por favor, forneça os prompts de edição.")
80
 
81
  job_id = str(uuid.uuid4())
82
+ output_dir = os.path.join(VINCIE_DIR, "output", job_id)
 
83
 
84
+ image_paths_str = ", ".join([f'"{f.name}"' for f in files])
85
+ prompts_list_str = ", ".join([f'"{p.strip()}"' for p in prompts_str.split(';')])
86
+ command = ["python", "main.py", "configs/generate.yaml", f'generation.positive_prompt.image_path=[{image_paths_str}]', f'generation.positive_prompt.prompts=[{prompts_list_str}]', f'generation.output.dir={output_dir}']
87
 
88
+ for gallery, logs in run_subprocess_with_logs(command, VINCIE_DIR):
89
+ yield gallery, logs
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
+ output_files = [os.path.join(output_dir, f) for f in os.listdir(output_dir) if f.endswith(('.png', '.jpg'))]
92
+ if not output_files: raise gr.Error("Nenhum arquivo de saída encontrado.")
93
+ yield output_files, logs
94
+
95
+ def run_vincie_pipeline_inference(files, final_prompt):
96
+ # (NOVA LÓGICA para o modo de PIPELINE do V-INT)
97
+ if not files: raise gr.Error("Por favor, faça o upload de múltiplas imagens para a composição.")
98
+ if not final_prompt: raise gr.Error("Por favor, forneça o prompt de composição final.")
99
+
100
+ job_id = str(uuid.uuid4())
101
+ output_dir = os.path.join(VINCIE_DIR, "output", job_id)
102
+
103
+ # Gera os prompts de placeholder
104
+ placeholder_prompts = [f"<IMG{i}>: " for i in range(len(files))]
105
+ all_prompts = placeholder_prompts + [final_prompt]
 
 
 
 
 
 
106
 
107
+ image_paths_str = ", ".join([f'"{f.name}"' for f in files])
108
+ prompts_list_str = ", ".join([f'"{p}"' for p in all_prompts])
109
+ command = ["python", "main.py", "configs/generate.yaml", "generation.pad_img_placehoder=False", f'generation.positive_prompt.image_path=[{image_paths_str}]', f'generation.positive_prompt.prompts=[{prompts_list_str}]', f'generation.output.dir={output_dir}']
110
+
111
+ for gallery, logs in run_subprocess_with_logs(command, VINCIE_DIR):
112
+ yield gallery, logs
113
+
114
+ output_files = [os.path.join(output_dir, f) for f in os.listdir(output_dir) if f.endswith(('.png', '.jpg'))]
115
+ if not output_files: raise gr.Error("Nenhum arquivo de saída foi encontrado.")
116
+ yield output_files, logs
117
+
118
+ # --- 3. INTERFACE GRADIO COM 3 ABAS ---
119
 
 
120
  with gr.Blocks() as demo:
121
+ gr.Markdown("<h1><center>Super-Space: SeedVR & V-INT</center></h1>")
122
 
123
  with gr.Tabs():
124
+ # --- ABA SEEDVR ---
125
+ with gr.TabItem("SeedVR (Restauração de Vídeo)"):
126
  with gr.Row():
127
  with gr.Column(scale=1):
128
+ seedvr_input_video = gr.Video(label="Upload de Vídeo")
129
+ seedvr_seed = gr.Number(value=666, label="Seed")
130
+ seedvr_run_button = gr.Button("Executar SeedVR", variant="primary")
 
 
 
131
  with gr.Column(scale=2):
132
+ seedvr_output = gr.Video(label="Vídeo Restaurado")
133
+ seedvr_logs = gr.Textbox(label="Logs", lines=10, interactive=False)
134
+ seedvr_run_button.click(fn=run_seedvr_inference, inputs=[seedvr_input_video, seedvr_seed], outputs=[seedvr_output, seedvr_logs])
135
+
136
+ # --- ABA V-INT EDIÇÃO ---
137
+ with gr.TabItem("V-INT (Edição de Imagem)"):
 
 
 
 
 
 
 
 
 
138
  with gr.Row():
139
  with gr.Column(scale=1):
140
+ vincie_edit_input = gr.Files(label="Upload de Imagem(ns) para Editar", file_types=["image"])
141
+ vincie_edit_prompts = gr.Textbox(label="Prompts de Edição (separados por ';')", lines=5, placeholder="Ex: Add a crown to her head; Change the background...")
142
+ vincie_edit_button = gr.Button("Executar Edição", variant="primary")
 
 
 
143
  with gr.Column(scale=2):
144
+ vincie_edit_output