caarleexx commited on
Commit
6f6213d
·
verified ·
1 Parent(s): 46b6b86

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +117 -107
app.py CHANGED
@@ -1,192 +1,186 @@
1
-
2
- # app_refactored_with_postprod.py (FINAL VERSION with LTX Refinement)
3
 
4
  import gradio as gr
5
  import os
6
  import sys
 
7
  import traceback
8
  from pathlib import Path
9
  import torch
10
  import numpy as np
11
  from PIL import Image
12
 
13
- # --- Import dos Serviços de Backend ---
14
 
15
- # Serviço LTX para geração de vídeo base e refinamento de textura
16
- from api.ltx_server_refactored import video_generation_service
17
 
18
- # Serviço SeedVR para upscaling de alta qualidade
19
  from api.seedvr_server import SeedVRServer
20
 
 
 
 
 
 
21
  # Inicializa o servidor SeedVR uma vez, se disponível
22
- seedvr_inference_server = SeedVRServer() if SeedVRServer else None
 
 
 
 
 
 
23
 
24
- # --- ESTADO DA SESSÃO ---
25
  def create_initial_state():
 
 
26
  return {
27
- "low_res_video": None,
28
- "low_res_latents": None,
29
- "refined_video_ltx": None,
30
- "refined_latents_ltx": None,
31
  "used_seed": None
32
  }
33
 
34
- # --- FUNÇÕES WRAPPER PARA A UI ---
35
 
36
- def run_generate_low(prompt, neg_prompt, start_img, height, width, duration, cfg, seed, randomize_seed, progress=gr.Progress(track_tqdm=True)):
37
- """Executa a primeira etapa: geração de um vídeo base em baixa resolução."""
38
- print("UI: Chamando generate_low")
39
- if True:
40
-
 
 
41
  image_filepaths = []
42
  if start_img:
43
- image_filepaths.append(start_img)
44
-
 
 
 
 
45
 
46
- used_seed = None if randomize_seed else seed
47
 
48
- video_path, tensor_path, final_seed = video_generation_service.generate_low_resolution(
 
49
  prompt=prompt, negative_prompt=neg_prompt,
50
- height=height, width=width, duration_secs=duration,
51
- guidance_scale=cfg, seed=used_seed,
52
  image_filepaths=image_filepaths
53
  )
54
-
 
 
 
 
 
 
 
 
 
 
55
  new_state = {
56
- "low_res_video": video_path,
57
- "low_res_latents": tensor_path,
58
- "refined_video_ltx": None,
59
- "refined_latents_ltx": None,
60
  "used_seed": final_seed
61
  }
62
 
 
 
63
  return video_path, new_state, gr.update(visible=True)
64
 
65
- def run_ltx_refinement(state, prompt, neg_prompt, cfg, progress=gr.Progress(track_tqdm=True)):
66
- """Executa o processo de refinamento secundário."""
67
- print("UI: Chamando a função ponte 'apply_secondary_refinement'")
68
-
69
- try:
70
- # AQUI ESTÁ A MUDANÇA: Chamamos a nova função ponte
71
- video_path, tensor_path = video_generation_service.apply_secondary_refinement(
72
- latents_path=state["low_res_latents"],
73
- prompt=prompt,
74
- negative_prompt=neg_prompt,
75
- guidance_scale=cfg,
76
- seed=state["used_seed"]
77
- )
78
-
79
- # Atualiza o estado com os novos artefatos refinados
80
- state["refined_video_ltx"] = video_path
81
- state["refined_latents_ltx"] = tensor_path
82
-
83
- return video_path, state
84
-
85
  except Exception as e:
86
- print(f"[ERRO na UI] Falha durante o refinamento secundário: {e}")
87
  traceback.print_exc()
88
- # Você pode retornar uma mensagem de erro para a UI aqui se quiser
89
- # Ex: return None, state
90
- raise gr.Error(f"Falha no Refinamento: {e}")
91
 
92
-
93
  def run_seedvr_upscaling(state, seed, resolution, batch_size, fps, progress=gr.Progress(track_tqdm=True)):
94
- """Executa o processo de upscaling com SeedVR."""
95
-
96
- video_path = state["low_res_video"]
 
 
97
  print(f"▶️ Iniciando processo de upscaling SeedVR para o vídeo: {video_path}")
98
 
99
- if True:
100
  def progress_wrapper(p, desc=""):
101
  progress(p, desc=desc)
 
102
  output_filepath = seedvr_inference_server.run_inference(
103
- file_path=video_path, seed=seed, resolution=resolution,
104
- batch_size=batch_size, fps=fps, progress=progress_wrapper
105
  )
106
  final_message = f"✅ Processo SeedVR concluído!\nVídeo salvo em: {output_filepath}"
107
  return gr.update(value=output_filepath, interactive=True), gr.update(value=final_message, interactive=False)
108
-
109
- # --- DEFINIÇÃO DA INTERFACE GRADIO ---
110
- with gr.Blocks() as demo:
111
- gr.Markdown("# LTX Video - Geração e Pós-Produção por Etapas")
 
 
 
 
112
 
113
  app_state = gr.State(value=create_initial_state())
114
 
115
- # --- ETAPA 1: Geração Base ---
116
  with gr.Row():
117
  with gr.Column(scale=1):
118
- gr.Markdown("### Etapa 1: Configurações de Geração")
119
- prompt_input = gr.Textbox(label="Prompt", value="A majestic dragon flying over a medieval castle", lines=3)
120
- neg_prompt_input = gr.Textbox(visible=False, label="Negative Prompt", value="worst quality, blurry, low quality, jittery", lines=2)
121
- start_image = gr.Image(label="Imagem de Início (Opcional)", type="filepath", sources=["upload", "clipboard"])
122
 
123
  with gr.Accordion("Parâmetros Avançados", open=False):
124
- height_input = gr.Slider(label="Height", value=512, step=32, minimum=256, maximum=1024)
125
- width_input = gr.Slider(label="Width", value=704, step=32, minimum=256, maximum=1024)
126
  duration_input = gr.Slider(label="Duração (s)", value=4, step=1, minimum=1, maximum=10)
127
- cfg_input = gr.Slider(label="Guidance Scale (CFG)", value=3.0, step=0.1, minimum=1.0, maximum=10.0)
128
  seed_input = gr.Number(label="Seed", value=42, precision=0)
129
- randomize_seed = gr.Checkbox(label="Randomize Seed", value=True)
130
 
131
- generate_low_btn = gr.Button("1. Gerar Vídeo Base (Low-Res)", variant="primary")
132
 
133
  with gr.Column(scale=1):
134
- gr.Markdown("### Vídeo Base Gerado")
135
- low_res_video_output = gr.Video(label="O resultado da Etapa 1 aparecerá aqui", interactive=False)
136
 
137
- # --- ETAPA 2: Pós-Produção (no rodapé, em abas) ---
138
  with gr.Group(visible=False) as post_prod_group:
139
  gr.Markdown("<hr style='margin-top: 20px; margin-bottom: 20px;'>")
140
- gr.Markdown("## Etapa 2: Pós-Produção")
141
- gr.Markdown("Use o vídeo gerado acima como entrada para as ferramentas abaixo. **O prompt e a CFG da Etapa 1 serão reutilizados.**")
142
 
143
  with gr.Tabs():
144
- # --- ABA LTX REFINEMENT (AGORA FUNCIONAL) ---
145
- with gr.TabItem("🚀 Upscaler Textura (LTX)"):
146
- with gr.Row():
147
- with gr.Column(scale=1):
148
- gr.Markdown("### Parâmetros de Refinamento")
149
- gr.Markdown("Esta etapa reutiliza o prompt, o prompt negativo e a CFG da Etapa 1 para manter a consistência.")
150
- ltx_refine_btn = gr.Button("Aplicar Refinamento de Textura LTX", variant="primary")
151
- with gr.Column(scale=1):
152
- gr.Markdown("### Resultado do Refinamento")
153
- ltx_refined_video_output = gr.Video(label="Vídeo com Textura Refinada (LTX)", interactive=False)
154
-
155
  # --- ABA SEEDVR UPSCALER ---
156
- with gr.TabItem("✨ Upscaler SeedVR"):
157
  with gr.Row():
158
  with gr.Column(scale=1):
159
  gr.Markdown("### Parâmetros do SeedVR")
160
- seedvr_seed = gr.Slider(minimum=0, maximum=999999, value=42, step=1, label="Seed")
161
- seedvr_resolution = gr.Slider(minimum=720, maximum=1440, value=1072, step=8, label="Resolução Vertical (Altura)")
162
  seedvr_batch_size = gr.Slider(minimum=1, maximum=16, value=4, step=1, label="Batch Size por GPU")
163
  seedvr_fps_output = gr.Number(label="FPS de Saída (0 = original)", value=0)
164
  run_seedvr_button = gr.Button("Iniciar Upscaling SeedVR", variant="primary", interactive=(seedvr_inference_server is not None))
165
  if not seedvr_inference_server:
166
- gr.Markdown("<p style='color: red;'>Serviço SeedVR não disponível.</p>")
167
  with gr.Column(scale=1):
168
  gr.Markdown("### Resultado do Upscaling")
169
  seedvr_video_output = gr.Video(label="Vídeo com Upscale SeedVR", interactive=False)
170
  seedvr_status_box = gr.Textbox(label="Status do Processamento", value="Aguardando...", lines=3, interactive=False)
171
 
172
  # --- ABA MM-AUDIO ---
173
- with gr.TabItem("🔊 Áudio (MM-Audio)"):
174
  gr.Markdown("*(Funcionalidade futura para adicionar som aos vídeos)*")
175
 
176
- # --- LÓGICA DE EVENTOS DA UI ---
177
 
178
- # Botão da Etapa 1
179
- generate_low_btn.click(
180
- fn=run_generate_low,
181
  inputs=[prompt_input, neg_prompt_input, start_image, height_input, width_input, duration_input, cfg_input, seed_input, randomize_seed],
182
- outputs=[low_res_video_output, app_state, post_prod_group]
183
- )
184
-
185
- # Botão da Aba LTX Refinement
186
- ltx_refine_btn.click(
187
- fn=run_ltx_refinement,
188
- inputs=[app_state, prompt_input, neg_prompt_input, cfg_input],
189
- outputs=[ltx_refined_video_output, app_state]
190
  )
191
 
192
  # Botão da Aba SeedVR
@@ -196,5 +190,21 @@ with gr.Blocks() as demo:
196
  outputs=[seedvr_video_output, seedvr_status_box]
197
  )
198
 
 
199
  if __name__ == "__main__":
 
 
 
 
200
  demo.queue().launch(server_name="0.0.0.0", server_port=7860, debug=True, show_error=True)
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app_final_orchestrator.py
 
2
 
3
  import gradio as gr
4
  import os
5
  import sys
6
+ import time
7
  import traceback
8
  from pathlib import Path
9
  import torch
10
  import numpy as np
11
  from PIL import Image
12
 
13
+ # --- 1. Importação e Inicialização dos Serviços de Backend ---
14
 
15
+ # Importa a classe OrchestratorService, o "cérebro" do nosso sistema
16
+ from api.ltx_server_refactored import OrchestratorService
17
 
18
+ # Importa o serviço de upscaling de alta qualidade
19
  from api.seedvr_server import SeedVRServer
20
 
21
+ # Cria a instância principal do serviço, que decidirá o modo de operação (Single ou Multi-GPU)
22
+ print("[Gradio UI] Criando instância do OrchestratorService...")
23
+ orchestrator_service = OrchestratorService()
24
+ print("[Gradio UI] Instância do OrchestratorService criada.")
25
+
26
  # Inicializa o servidor SeedVR uma vez, se disponível
27
+ try:
28
+ seedvr_inference_server = SeedVRServer() if SeedVRServer else None
29
+ print("[Gradio UI] Serviço SeedVR inicializado.")
30
+ except Exception as e:
31
+ seedvr_inference_server = None
32
+ print(f"[Gradio UI WARNING] Não foi possível inicializar o SeedVRServer: {e}")
33
+
34
 
35
+ # --- 2. Gerenciamento de Estado da Sessão ---
36
  def create_initial_state():
37
+ """Define o estado inicial para cada sessão de usuário."""
38
+ # O estado foi simplificado, pois o LTX agora produz um único vídeo final.
39
  return {
40
+ "final_video_path": None,
41
+ "final_latents_path": None, # Mantido para possíveis futuras funcionalidades
 
 
42
  "used_seed": None
43
  }
44
 
45
+ # --- 3. Funções de Interface (Wrappers para o Backend) ---
46
 
47
+ def run_generation_pipeline(prompt, neg_prompt, start_img, height, width, duration, cfg, seed, randomize_seed, progress=gr.Progress(track_tqdm=True)):
48
+ """
49
+ Executa o pipeline de geração COMPLETO (Geração Base + Refinamento LTX)
50
+ chamando o OrchestratorService. Esta é a função principal da UI.
51
+ """
52
+ print("UI: Chamando o pipeline de geração completo via Orchestrator...")
53
+ try:
54
  image_filepaths = []
55
  if start_img:
56
+ # Salva a imagem temporariamente, pois o Gradio pode limpá-la
57
+ temp_dir = tempfile.mkdtemp()
58
+ img_pil = Image.fromarray(start_img)
59
+ temp_path = os.path.join(temp_dir, "start_image.png")
60
+ img_pil.save(temp_path)
61
+ image_filepaths.append(temp_path)
62
 
63
+ used_seed = None if randomize_seed else int(seed)
64
 
65
+ # Chamada unificada para o backend. O orquestrador lida com a complexidade.
66
+ result = orchestrator_service.generate_video(
67
  prompt=prompt, negative_prompt=neg_prompt,
68
+ height=int(height), width=int(width), duration_secs=float(duration),
69
+ guidance_scale=float(cfg), seed=used_seed,
70
  image_filepaths=image_filepaths
71
  )
72
+
73
+ # O backend tem retornos diferentes dependendo do modo, a UI se adapta a isso.
74
+ if isinstance(result, tuple) and len(result) == 3:
75
+ # Modo Single-GPU retorna (video_path, latents_path, seed)
76
+ video_path, tensor_path, final_seed = result
77
+ else:
78
+ # Modo Multi-GPU retorna apenas video_path
79
+ video_path = result
80
+ tensor_path = None # Latentes não são passados de volta no fluxo multi-gpu
81
+ final_seed = used_seed if used_seed is not None else "N/A"
82
+
83
  new_state = {
84
+ "final_video_path": video_path,
85
+ "final_latents_path": tensor_path,
 
 
86
  "used_seed": final_seed
87
  }
88
 
89
+ # O resultado já é o vídeo refinado, que é exibido diretamente.
90
+ # O grupo de pós-produção é ativado para o próximo passo.
91
  return video_path, new_state, gr.update(visible=True)
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  except Exception as e:
94
+ print(f"[ERRO na UI] Falha durante a geração: {e}")
95
  traceback.print_exc()
96
+ raise gr.Error(f"Falha na Geração: {e}")
 
 
97
 
 
98
  def run_seedvr_upscaling(state, seed, resolution, batch_size, fps, progress=gr.Progress(track_tqdm=True)):
99
+ """Executa o processo de upscaling com SeedVR no vídeo gerado."""
100
+ video_path = state.get("final_video_path")
101
+ if not video_path or not os.path.exists(video_path):
102
+ raise gr.Error("Nenhum vídeo foi gerado ainda ou o arquivo não foi encontrado. Por favor, execute a Etapa 1 primeiro.")
103
+
104
  print(f"▶️ Iniciando processo de upscaling SeedVR para o vídeo: {video_path}")
105
 
106
+ try:
107
  def progress_wrapper(p, desc=""):
108
  progress(p, desc=desc)
109
+
110
  output_filepath = seedvr_inference_server.run_inference(
111
+ file_path=video_path, seed=int(seed), resolution=int(resolution),
112
+ batch_size=int(batch_size), fps=int(fps), progress=progress_wrapper
113
  )
114
  final_message = f"✅ Processo SeedVR concluído!\nVídeo salvo em: {output_filepath}"
115
  return gr.update(value=output_filepath, interactive=True), gr.update(value=final_message, interactive=False)
116
+ except Exception as e:
117
+ print(f"[ERRO na UI] Falha durante o upscaling SeedVR: {e}")
118
+ traceback.print_exc()
119
+ raise gr.Error(f"Falha no Upscaling SeedVR: {e}")
120
+
121
+ # --- 4. Definição da Interface Gráfica com Gradio ---
122
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
123
+ gr.Markdown("# LTX Video Studio: Geração e Pós-Produção")
124
 
125
  app_state = gr.State(value=create_initial_state())
126
 
127
+ # --- ETAPA 1: Geração Principal (Unificada) ---
128
  with gr.Row():
129
  with gr.Column(scale=1):
130
+ gr.Markdown("### Etapa 1: Gerar Vídeo (Base + Refinamento LTX)")
131
+ prompt_input = gr.Textbox(label="Prompt", value="A majestic dragon flying over a medieval castle, cinematic, epic", lines=3)
132
+ neg_prompt_input = gr.Textbox(label="Negative Prompt", value="worst quality, blurry, low quality, jittery, watermark, text", lines=2)
133
+ start_image = gr.Image(label="Imagem de Início (Opcional)", type="numpy", sources=["upload", "clipboard"])
134
 
135
  with gr.Accordion("Parâmetros Avançados", open=False):
136
+ height_input = gr.Slider(label="Altura (Height)", value=512, step=64, minimum=256, maximum=1024)
137
+ width_input = gr.Slider(label="Largura (Width)", value=896, step=64, minimum=256, maximum=1536)
138
  duration_input = gr.Slider(label="Duração (s)", value=4, step=1, minimum=1, maximum=10)
139
+ cfg_input = gr.Slider(label="Guidance Scale (CFG)", value=15.0, step=0.5, minimum=1.0, maximum=20.0)
140
  seed_input = gr.Number(label="Seed", value=42, precision=0)
141
+ randomize_seed = gr.Checkbox(label="Usar Seed Aleatória", value=True)
142
 
143
+ generate_btn = gr.Button("🚀 Gerar Vídeo Completo", variant="primary", scale=2)
144
 
145
  with gr.Column(scale=1):
146
+ gr.Markdown("### Vídeo Gerado e Refinado (LTX)")
147
+ final_video_output = gr.Video(label="O resultado final do LTX aparecerá aqui", interactive=False)
148
 
149
+ # --- ETAPA 2: Pós-Produção Adicional ---
150
  with gr.Group(visible=False) as post_prod_group:
151
  gr.Markdown("<hr style='margin-top: 20px; margin-bottom: 20px;'>")
152
+ gr.Markdown("## Etapa 2: Pós-Produção Adicional")
153
+ gr.Markdown("Use o vídeo gerado acima como entrada para as ferramentas abaixo.")
154
 
155
  with gr.Tabs():
 
 
 
 
 
 
 
 
 
 
 
156
  # --- ABA SEEDVR UPSCALER ---
157
+ with gr.TabItem("✨ Upscaler de Qualidade (SeedVR)"):
158
  with gr.Row():
159
  with gr.Column(scale=1):
160
  gr.Markdown("### Parâmetros do SeedVR")
161
+ seedvr_seed = gr.Slider(minimum=0, maximum=999999, value=42, step=1, label="Seed do Upscaler")
162
+ seedvr_resolution = gr.Slider(minimum=720, maximum=2160, value=1080, step=8, label="Resolução Vertical Final")
163
  seedvr_batch_size = gr.Slider(minimum=1, maximum=16, value=4, step=1, label="Batch Size por GPU")
164
  seedvr_fps_output = gr.Number(label="FPS de Saída (0 = original)", value=0)
165
  run_seedvr_button = gr.Button("Iniciar Upscaling SeedVR", variant="primary", interactive=(seedvr_inference_server is not None))
166
  if not seedvr_inference_server:
167
+ gr.Markdown("<p style='color: red; font-weight: bold;'>Serviço SeedVR não disponível.</p>")
168
  with gr.Column(scale=1):
169
  gr.Markdown("### Resultado do Upscaling")
170
  seedvr_video_output = gr.Video(label="Vídeo com Upscale SeedVR", interactive=False)
171
  seedvr_status_box = gr.Textbox(label="Status do Processamento", value="Aguardando...", lines=3, interactive=False)
172
 
173
  # --- ABA MM-AUDIO ---
174
+ with gr.TabItem("🔊 Áudio (Futuro)"):
175
  gr.Markdown("*(Funcionalidade futura para adicionar som aos vídeos)*")
176
 
177
+ # --- 5. Lógica de Eventos da UI ---
178
 
179
+ # Botão da Etapa 1 chama a função de geração unificada
180
+ generate_btn.click(
181
+ fn=run_generation_pipeline,
182
  inputs=[prompt_input, neg_prompt_input, start_image, height_input, width_input, duration_input, cfg_input, seed_input, randomize_seed],
183
+ outputs=[final_video_output, app_state, post_prod_group]
 
 
 
 
 
 
 
184
  )
185
 
186
  # Botão da Aba SeedVR
 
190
  outputs=[seedvr_video_output, seedvr_status_box]
191
  )
192
 
193
+ # --- 6. Ponto de Entrada da Aplicação ---
194
  if __name__ == "__main__":
195
+ # Garante que os diretórios necessários existem
196
+ os.makedirs("output", exist_ok=True)
197
+
198
+ # Inicia o servidor Gradio
199
  demo.queue().launch(server_name="0.0.0.0", server_port=7860, debug=True, show_error=True)
200
+
201
+ # Bloco para garantir o desligamento limpo dos workers do backend
202
+ try:
203
+ # Mantém o script principal rodando enquanto o Gradio está ativo
204
+ while True:
205
+ time.sleep(1)
206
+ except (KeyboardInterrupt, SystemExit):
207
+ print("\n[Gradio UI] Desligando... Enviando sinal de shutdown para o Orchestrator.")
208
+ if orchestrator_service:
209
+ orchestrator_service.shutdown()
210
+ print("[Gradio UI] Desligamento concluído. Pode fechar o terminal.")