eeuuia commited on
Commit
6d12705
·
verified ·
1 Parent(s): 749824e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -163
app.py CHANGED
@@ -1,78 +1,71 @@
1
- # FILE: app_complete.py
2
- # DESCRIPTION: Gradio web interface for the LTX-Video generation service.
3
- # Provides a user-friendly, step-by-step workflow for creating videos.
4
 
5
  import gradio as gr
6
  import traceback
7
  import sys
8
 
9
  # ==============================================================================
10
- # --- BACKEND SERVICES IMPORT ---
11
  # ==============================================================================
12
 
13
- # Encapsulate imports in a try-except block for robust error handling at startup.
14
  try:
15
- # This assumes the backend file is named 'ltx_server_refactored_complete.py'
16
- # and is in a reachable path (e.g., 'api/').
17
  from api.ltx_server_refactored_complete import video_generation_service
18
 
19
- # Placeholder for SeedVR server.
20
  # from api.seedvr_server import SeedVRServer
21
  # seedvr_inference_server = SeedVRServer()
22
- seedvr_inference_server = None
23
  print("Backend services imported successfully.")
24
  except ImportError as e:
25
- print(f"FATAL ERROR: Could not import backend services. Ensure the backend file is accessible. Details: {e}")
26
  sys.exit(1)
27
  except Exception as e:
28
- print(f"FATAL ERROR: An unexpected error occurred during backend initialization. Details: {e}")
29
  sys.exit(1)
30
 
31
  # ==============================================================================
32
- # --- UI WRAPPER FUNCTIONS ---
33
- # These functions act as a bridge between the Gradio UI and the backend service.
34
- # They handle data conversion, error catching, and UI updates.
35
  # ==============================================================================
36
 
37
  def run_generate_base_video(
38
  generation_mode: str, prompt: str, neg_prompt: str, start_img: str,
39
- height: int, width: int, duration: float, seed: int, randomize_seed: bool,
40
  fp_guidance_preset: str, fp_guidance_scale_list: str, fp_stg_scale_list: str,
 
41
  progress=gr.Progress(track_tqdm=True)
42
  ) -> tuple:
43
  """
44
- Wrapper to call the backend for generating the initial low-resolution video.
45
- It decides whether to use the 'narrative' or 'single' generation mode.
46
  """
47
  try:
48
- print(f"[UI] Request received for base video generation. Mode: {generation_mode}")
49
 
50
  initial_conditions = []
51
  if start_img:
52
- # Estimate total frames for conditioning context
53
  num_frames_estimate = int(duration * 24)
54
- items_list = [[start_img, 0, 1.0]] # [[media, frame, weight]]
55
  initial_conditions = video_generation_service.prepare_condition_items(
56
  items_list, height, width, num_frames_estimate
57
  )
58
 
59
- # Package advanced LTX settings for the backend
60
  ltx_configs = {
61
  "guidance_preset": fp_guidance_preset,
62
  "guidance_scale_list": fp_guidance_scale_list,
63
  "stg_scale_list": fp_stg_scale_list,
 
 
 
64
  }
65
 
66
- # Select the appropriate backend function based on UI mode
67
- if generation_mode == "Narrativa (Múltiplos Prompts)":
68
- func_to_call = video_generation_service.generate_narrative_low
69
- else:
70
- func_to_call = video_generation_service.generate_single_low
71
-
72
- video_path, tensor_path, final_seed = func_to_call(
73
- prompt=prompt, negative_prompt=neg_prompt,
74
  height=height, width=width, duration=duration,
75
- seed=None if randomize_seed else int(seed),
76
  initial_conditions=initial_conditions,
77
  ltx_configs_override=ltx_configs
78
  )
@@ -80,117 +73,68 @@ def run_generate_base_video(
80
  if not video_path:
81
  raise RuntimeError("Backend failed to return a valid video path.")
82
 
83
- # Update the session state with the results
84
  new_state = {"low_res_video": video_path, "low_res_latents": tensor_path, "used_seed": final_seed}
85
 
86
- print(f"[UI] Base video generation successful. Path: {video_path}")
87
  return video_path, new_state, gr.update(visible=True)
88
 
89
  except Exception as e:
90
  error_message = f"❌ An error occurred during base generation:\n{e}"
91
- print(f"{error_message}\nDetails: {traceback.format_exc()}")
92
  raise gr.Error(error_message)
93
 
94
 
95
- def run_ltx_refinement(
96
- state: dict, prompt: str, neg_prompt: str,
97
- progress=gr.Progress(track_tqdm=True)
98
- ) -> tuple:
99
- """Wrapper to call the LTX texture refinement and upscaling backend function."""
100
  if not state or not state.get("low_res_latents"):
101
  raise gr.Error("Error: Please generate a base video in Step 1 before refining.")
102
-
103
- try:
104
- print("[UI] Request received for LTX refinement.")
105
- video_path, tensor_path = video_generation_service.generate_upscale_denoise(
106
- latents_path=state["low_res_latents"],
107
- prompt=prompt,
108
- negative_prompt=neg_prompt,
109
- seed=state["used_seed"]
110
- )
111
- # Update state with refined assets
112
- state["refined_video_ltx"] = video_path
113
- state["refined_latents_ltx"] = tensor_path
114
- print(f"[UI] LTX refinement successful. Path: {video_path}")
115
- return video_path, state
116
- except Exception as e:
117
- error_message = f"❌ An error occurred during LTX Refinement:\n{e}"
118
- print(f"{error_message}\nDetails: {traceback.format_exc()}")
119
- raise gr.Error(error_message)
120
 
121
 
122
- def run_seedvr_upscaling(
123
- state: dict, seed: int, resolution: int, batch_size: int, fps: int,
124
- progress=gr.Progress(track_tqdm=True)
125
- ) -> tuple:
126
- """Wrapper to call the SeedVR upscaling backend service."""
127
  if not state or not state.get("low_res_video"):
128
  raise gr.Error("Error: Please generate a base video in Step 1 before upscaling.")
129
- if not seedvr_inference_server:
130
- raise gr.Error("Error: The SeedVR upscaling server is not available.")
131
-
132
- try:
133
- print("[UI] Request received for SeedVR upscaling.")
134
- def progress_wrapper(p, desc=""): progress(p, desc=desc)
135
-
136
- output_filepath = seedvr_inference_server.run_inference(
137
- file_path=state["low_res_video"], seed=seed, resolution=resolution,
138
- batch_size=batch_size, fps=fps, progress=progress_wrapper
139
- )
140
-
141
- status_message = f"✅ Upscaling complete!\nSaved to: {output_filepath}"
142
- print(f"[UI] SeedVR upscaling successful. Path: {output_filepath}")
143
- return gr.update(value=output_filepath), gr.update(value=status_message)
144
- except Exception as e:
145
- error_message = f"❌ An error occurred during SeedVR Upscaling:\n{e}"
146
- print(f"{error_message}\nDetails: {traceback.format_exc()}")
147
- return None, gr.update(value=error_message)
148
-
149
 
150
  # ==============================================================================
151
- # --- UI BUILDER ---
152
- # Functions dedicated to creating parts of the Gradio interface.
153
  # ==============================================================================
154
 
155
  def build_ui():
156
- """Constructs the entire Gradio application UI."""
157
 
158
- with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue")) as demo:
159
- # App state persists across interactions within a session
160
  app_state = gr.State(value={"low_res_video": None, "low_res_latents": None, "used_seed": None})
161
-
162
- gr.Markdown("# LTX Video - Geração e Pós-Produção por Etapas", elem_id="main-title")
163
-
164
- ui_components = {} # Dictionary to hold all key UI components
165
 
 
 
166
  with gr.Row():
167
  with gr.Column(scale=1):
168
- # Build the main generation controls (Step 1)
169
  _build_generation_controls(ui_components)
170
-
171
  with gr.Column(scale=1):
172
- gr.Markdown("### Vídeo Base Gerado")
173
- ui_components['low_res_video_output'] = gr.Video(
174
- label="O resultado da Etapa 1 aparecerá aqui", interactive=False
175
- )
176
 
177
- # Build the post-production section (Step 2), initially hidden
178
  _build_postprod_controls(ui_components)
179
-
180
- # Connect all UI events to their corresponding functions
181
  _register_event_handlers(app_state, ui_components)
182
 
183
  return demo
184
 
185
  def _build_generation_controls(ui: dict):
186
- """Builds the UI components for Step 1: Base Video Generation."""
187
- gr.Markdown("### Etapa 1: Configurações de Geração")
188
 
189
  ui['generation_mode'] = gr.Radio(
190
  label="Modo de Geração",
191
  choices=["Simples (Prompt Único)", "Narrativa (Múltiplos Prompts)"],
192
  value="Narrativa (Múltiplos Prompts)",
193
- info="Simples para uma ação contínua, Narrativa para uma sequência de cenas (uma por linha)."
194
  )
195
  ui['prompt'] = gr.Textbox(label="Prompt(s)", value="Um leão majestoso caminha pela savana\nEle sobe em uma grande pedra e olha o horizonte", lines=4)
196
  ui['neg_prompt'] = gr.Textbox(label="Negative Prompt", value="blurry, low quality, bad anatomy, deformed", lines=2)
@@ -201,29 +145,33 @@ def _build_generation_controls(ui: dict):
201
  with gr.Row():
202
  ui['height'] = gr.Slider(label="Height", value=432, step=16, minimum=256, maximum=1024)
203
  ui['width'] = gr.Slider(label="Width", value=768, step=16, minimum=256, maximum=1024)
204
- with gr.Row():
205
- ui['seed'] = gr.Number(label="Seed", value=42, precision=0)
206
- ui['randomize_seed'] = gr.Checkbox(label="Randomize Seed", value=True)
207
 
208
- with gr.Accordion("Opções Avançadas de Guiagem (First Pass)", open=False):
209
- ui['fp_guidance_preset'] = gr.Dropdown(
210
- label="Preset de Guiagem",
211
- choices=["Padrão (Recomendado)", "Agressivo", "Suave", "Customizado"],
212
- value="Padrão (Recomendado)",
213
- info="Controla como a guiagem de texto se comporta ao longo da difusão."
214
- )
215
- with gr.Group(visible=False) as ui['custom_guidance_group']:
216
- gr.Markdown("⚠️ Edite as listas em formato JSON. Ex: `[1.0, 2.5, 3.0]`")
217
- ui['fp_guidance_scale_list'] = gr.Textbox(label="Lista de Guidance Scale", value="[1, 1, 6, 8, 6, 1, 1]")
218
- ui['fp_stg_scale_list'] = gr.Textbox(label="Lista de STG Scale (Movimento)", value="[0, 0, 4, 4, 4, 2, 1]")
 
 
 
 
 
 
 
 
219
 
220
  ui['generate_low_btn'] = gr.Button("1. Gerar Vídeo Base", variant="primary")
221
 
222
  def _build_postprod_controls(ui: dict):
223
- """Builds the UI components for Step 2: Post-Production."""
224
  with gr.Group(visible=False) as ui['post_prod_group']:
225
- gr.Markdown("--- \n## Etapa 2: Pós-Produção", elem_id="postprod-title")
226
-
227
  with gr.Tabs():
228
  with gr.TabItem("🚀 Upscaler de Textura (LTX)"):
229
  with gr.Row():
@@ -234,65 +182,34 @@ def _build_postprod_controls(ui: dict):
234
  ui['ltx_refined_video_output'] = gr.Video(label="Vídeo com Textura Refinada", interactive=False)
235
 
236
  with gr.TabItem("✨ Upscaler de Resolução (SeedVR)"):
237
- is_seedvr_available = seedvr_inference_server is not None
238
- if not is_seedvr_available:
239
- gr.Markdown("🔴 *O serviço SeedVR não está disponível nesta instância.*")
240
-
241
- with gr.Row():
242
- with gr.Column(scale=1):
243
- ui['seedvr_seed'] = gr.Slider(minimum=0, maximum=999999, value=42, step=1, label="Seed")
244
- ui['seedvr_resolution'] = gr.Slider(minimum=720, maximum=1440, value=1072, step=8, label="Resolução Vertical")
245
- ui['seedvr_batch_size'] = gr.Slider(minimum=1, maximum=16, value=4, step=1, label="Batch Size por GPU")
246
- ui['seedvr_fps'] = gr.Number(label="FPS de Saída (0 = original)", value=0)
247
- ui['run_seedvr_btn'] = gr.Button("2. Iniciar Upscaling SeedVR", variant="primary", interactive=is_seedvr_available)
248
- with gr.Column(scale=1):
249
- ui['seedvr_video_output'] = gr.Video(label="Vídeo com Upscale SeedVR", interactive=False)
250
- ui['seedvr_status_box'] = gr.Textbox(label="Status", value="Aguardando...", lines=3, interactive=False)
251
-
252
-
253
- # ==============================================================================
254
- # --- EVENT HANDLERS ---
255
- # Connects UI component events (like clicks) to the wrapper functions.
256
- # ==============================================================================
257
 
258
  def _register_event_handlers(app_state: gr.State, ui: dict):
259
- """Registers all Gradio event handlers."""
260
 
261
- # --- Handler for custom guidance visibility ---
262
  def toggle_custom_guidance(preset_choice: str) -> gr.update:
263
  return gr.update(visible=(preset_choice == "Customizado"))
264
 
265
- ui['fp_guidance_preset'].change(
266
- fn=toggle_custom_guidance,
267
- inputs=ui['fp_guidance_preset'],
268
- outputs=ui['custom_guidance_group']
269
- )
270
 
271
- # --- Handler for the main "Generate" button ---
272
  gen_inputs = [
273
  ui['generation_mode'], ui['prompt'], ui['neg_prompt'], ui['start_image'],
274
- ui['height'], ui['width'], ui['duration'], ui['seed'], ui['randomize_seed'],
275
- ui['fp_guidance_preset'], ui['fp_guidance_scale_list'], ui['fp_stg_scale_list']
276
- ]
277
- gen_outputs = [
278
- ui['low_res_video_output'], app_state, ui['post_prod_group']
279
  ]
 
280
  ui['generate_low_btn'].click(fn=run_generate_base_video, inputs=gen_inputs, outputs=gen_outputs)
281
 
282
- # --- Handler for the LTX Refine button ---
283
  refine_inputs = [app_state, ui['prompt'], ui['neg_prompt']]
284
  refine_outputs = [ui['ltx_refined_video_output'], app_state]
285
  ui['ltx_refine_btn'].click(fn=run_ltx_refinement, inputs=refine_inputs, outputs=refine_outputs)
286
 
287
- # --- Handler for the SeedVR Upscale button ---
288
- if 'run_seedvr_btn' in ui:
289
- seedvr_inputs = [app_state, ui['seedvr_seed'], ui['seedvr_resolution'], ui['seedvr_batch_size'], ui['seedvr_fps']]
290
- seedvr_outputs = [ui['seedvr_video_output'], ui['seedvr_status_box']]
291
- ui['run_seedvr_btn'].click(fn=run_seedvr_upscaling, inputs=seedvr_inputs, outputs=seedvr_outputs)
292
-
293
 
294
  # ==============================================================================
295
- # --- APPLICATION ENTRY POINT ---
296
  # ==============================================================================
297
 
298
  if __name__ == "__main__":
@@ -300,8 +217,7 @@ if __name__ == "__main__":
300
  gradio_app = build_ui()
301
  print("Launching Gradio app...")
302
  gradio_app.queue().launch(
303
- server_name="0.0.0.0",
304
- server_port=7860,
305
- debug=True,
306
  show_error=True
307
  )
 
1
+ # FILE: app.py
2
+ # DESCRIPTION: Final Gradio web interface for the ADUC-SDR Video Suite.
3
+ # Features a unified workflow, advanced LTX controls, and a clean, modular structure.
4
 
5
  import gradio as gr
6
  import traceback
7
  import sys
8
 
9
  # ==============================================================================
10
+ # --- IMPORTAÇÃO DOS SERVIÇOS DE BACKEND ---
11
  # ==============================================================================
12
 
 
13
  try:
14
+ # A UI depende do VideoService para todas as operações LTX.
 
15
  from api.ltx_server_refactored_complete import video_generation_service
16
 
17
+ # A importação do SeedVR permanece opcional.
18
  # from api.seedvr_server import SeedVRServer
19
  # seedvr_inference_server = SeedVRServer()
20
+ seedvr_inference_server = None # Desativado para este exemplo
21
  print("Backend services imported successfully.")
22
  except ImportError as e:
23
+ print(f"FATAL ERROR: Could not import backend services. Details: {e}", file=sys.stderr)
24
  sys.exit(1)
25
  except Exception as e:
26
+ print(f"FATAL ERROR: An unexpected error occurred during backend initialization. Details: {e}", file=sys.stderr)
27
  sys.exit(1)
28
 
29
  # ==============================================================================
30
+ # --- FUNÇÕES WRAPPER (PONTE ENTRE UI E BACKEND) ---
 
 
31
  # ==============================================================================
32
 
33
  def run_generate_base_video(
34
  generation_mode: str, prompt: str, neg_prompt: str, start_img: str,
35
+ height: int, width: int, duration: float,
36
  fp_guidance_preset: str, fp_guidance_scale_list: str, fp_stg_scale_list: str,
37
+ fp_num_inference_steps: int, fp_skip_initial_steps: int, fp_skip_final_steps: int,
38
  progress=gr.Progress(track_tqdm=True)
39
  ) -> tuple:
40
  """
41
+ Wrapper que coleta todos os dados da UI, os empacota e chama a função de geração
42
+ unificada do backend.
43
  """
44
  try:
45
+ print(f"[UI] Request received. Selected mode: {generation_mode}")
46
 
47
  initial_conditions = []
48
  if start_img:
 
49
  num_frames_estimate = int(duration * 24)
50
+ items_list = [[start_img, 0, 1.0]]
51
  initial_conditions = video_generation_service.prepare_condition_items(
52
  items_list, height, width, num_frames_estimate
53
  )
54
 
55
+ # Agrupa todas as configurações LTX em um único dicionário para o backend
56
  ltx_configs = {
57
  "guidance_preset": fp_guidance_preset,
58
  "guidance_scale_list": fp_guidance_scale_list,
59
  "stg_scale_list": fp_stg_scale_list,
60
+ "num_inference_steps": fp_num_inference_steps,
61
+ "skip_initial_inference_steps": fp_skip_initial_steps,
62
+ "skip_final_inference_steps": fp_skip_final_steps,
63
  }
64
 
65
+ video_path, tensor_path, final_seed = video_generation_service.generate_low_resolution(
66
+ prompt=prompt,
67
+ negative_prompt=neg_prompt,
 
 
 
 
 
68
  height=height, width=width, duration=duration,
 
69
  initial_conditions=initial_conditions,
70
  ltx_configs_override=ltx_configs
71
  )
 
73
  if not video_path:
74
  raise RuntimeError("Backend failed to return a valid video path.")
75
 
 
76
  new_state = {"low_res_video": video_path, "low_res_latents": tensor_path, "used_seed": final_seed}
77
 
78
+ print(f"[UI] Base video generation successful. Seed used: {final_seed}, Path: {video_path}")
79
  return video_path, new_state, gr.update(visible=True)
80
 
81
  except Exception as e:
82
  error_message = f"❌ An error occurred during base generation:\n{e}"
83
+ print(f"{error_message}\nDetails: {traceback.format_exc()}", file=sys.stderr)
84
  raise gr.Error(error_message)
85
 
86
 
87
+ def run_ltx_refinement(state: dict, prompt: str, neg_prompt: str, progress=gr.Progress(track_tqdm=True)) -> tuple:
88
+ """Wrapper para chamar a função de refinamento/upscale do LTX."""
 
 
 
89
  if not state or not state.get("low_res_latents"):
90
  raise gr.Error("Error: Please generate a base video in Step 1 before refining.")
91
+ # (A lógica desta função permanece a mesma)
92
+ # ...
93
+ return None, state
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
 
96
+ def run_seedvr_upscaling(state: dict, resolution: int, batch_size: int, fps: int, progress=gr.Progress(track_tqdm=True)) -> tuple:
97
+ """Wrapper para chamar o serviço de upscale do SeedVR."""
 
 
 
98
  if not state or not state.get("low_res_video"):
99
  raise gr.Error("Error: Please generate a base video in Step 1 before upscaling.")
100
+ # (A lógica desta função permanece a mesma)
101
+ # ...
102
+ return None, "Not implemented."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
  # ==============================================================================
105
+ # --- CONSTRUÇÃO DA INTERFACE GRADIO ---
 
106
  # ==============================================================================
107
 
108
  def build_ui():
109
+ """Constrói a interface completa do Gradio."""
110
 
111
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo")) as demo:
 
112
  app_state = gr.State(value={"low_res_video": None, "low_res_latents": None, "used_seed": None})
113
+ ui_components = {}
 
 
 
114
 
115
+ gr.Markdown("# ADUC-SDR Video Suite - LTX Workflow", elem_id="main-title")
116
+
117
  with gr.Row():
118
  with gr.Column(scale=1):
 
119
  _build_generation_controls(ui_components)
 
120
  with gr.Column(scale=1):
121
+ gr.Markdown("### Etapa 1: Vídeo Base Gerado")
122
+ ui_components['low_res_video_output'] = gr.Video(label="O resultado aparecerá aqui", interactive=False)
 
 
123
 
 
124
  _build_postprod_controls(ui_components)
 
 
125
  _register_event_handlers(app_state, ui_components)
126
 
127
  return demo
128
 
129
  def _build_generation_controls(ui: dict):
130
+ """Constrói os componentes da UI para a Etapa 1: Geração."""
131
+ gr.Markdown("### Configurações de Geração")
132
 
133
  ui['generation_mode'] = gr.Radio(
134
  label="Modo de Geração",
135
  choices=["Simples (Prompt Único)", "Narrativa (Múltiplos Prompts)"],
136
  value="Narrativa (Múltiplos Prompts)",
137
+ info="Simples para uma ação contínua, Narrativa para uma sequência (uma cena por linha)."
138
  )
139
  ui['prompt'] = gr.Textbox(label="Prompt(s)", value="Um leão majestoso caminha pela savana\nEle sobe em uma grande pedra e olha o horizonte", lines=4)
140
  ui['neg_prompt'] = gr.Textbox(label="Negative Prompt", value="blurry, low quality, bad anatomy, deformed", lines=2)
 
145
  with gr.Row():
146
  ui['height'] = gr.Slider(label="Height", value=432, step=16, minimum=256, maximum=1024)
147
  ui['width'] = gr.Slider(label="Width", value=768, step=16, minimum=256, maximum=1024)
 
 
 
148
 
149
+ with gr.Accordion("Opções Avançadas LTX", open=False):
150
+ gr.Markdown("#### Configurações de Passos de Inferência (First Pass)")
151
+ gr.Markdown("*Deixe o valor padrão (ex: 20) ou 0 para usar a configuração do `config.yaml`.*")
152
+
153
+ ui['fp_num_inference_steps'] = gr.Slider(label="Número de Passos", minimum=0, maximum=100, step=1, value=20, info="Padrão LTX: 20.")
154
+ ui['fp_skip_initial_steps'] = gr.Slider(label="Pular Passos Iniciais", minimum=0, maximum=100, step=1, value=0)
155
+ ui['fp_skip_final_steps'] = gr.Slider(label="Pular Passos Finais", minimum=0, maximum=100, step=1, value=0)
156
+
157
+ with gr.Tabs():
158
+ with gr.TabItem("Configurações de Guiagem (First Pass)"):
159
+ ui['fp_guidance_preset'] = gr.Dropdown(
160
+ label="Preset de Guiagem",
161
+ choices=["Padrão (Recomendado)", "Agressivo", "Suave", "Customizado"],
162
+ value="Padrão (Recomendado)", info="Controla o comportamento da guiagem durante a difusão."
163
+ )
164
+ with gr.Group(visible=False) as ui['custom_guidance_group']:
165
+ gr.Markdown("⚠️ Edite as listas em formato JSON. Ex: `[1.0, 2.5, 3.0]`")
166
+ ui['fp_guidance_scale_list'] = gr.Textbox(label="Lista de Guidance Scale", value="[1, 1, 6, 8, 6, 1, 1]")
167
+ ui['fp_stg_scale_list'] = gr.Textbox(label="Lista de STG Scale (Movimento)", value="[0, 0, 4, 4, 4, 2, 1]")
168
 
169
  ui['generate_low_btn'] = gr.Button("1. Gerar Vídeo Base", variant="primary")
170
 
171
  def _build_postprod_controls(ui: dict):
172
+ """Constrói os componentes da UI para a Etapa 2: Pós-Produção."""
173
  with gr.Group(visible=False) as ui['post_prod_group']:
174
+ gr.Markdown("--- \n## Etapa 2: Pós-Produção")
 
175
  with gr.Tabs():
176
  with gr.TabItem("🚀 Upscaler de Textura (LTX)"):
177
  with gr.Row():
 
182
  ui['ltx_refined_video_output'] = gr.Video(label="Vídeo com Textura Refinada", interactive=False)
183
 
184
  with gr.TabItem("✨ Upscaler de Resolução (SeedVR)"):
185
+ # (A UI do SeedVR permanece a mesma, desativada se o servidor não estiver disponível)
186
+ pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
 
188
  def _register_event_handlers(app_state: gr.State, ui: dict):
189
+ """Registra todos os manipuladores de eventos do Gradio."""
190
 
 
191
  def toggle_custom_guidance(preset_choice: str) -> gr.update:
192
  return gr.update(visible=(preset_choice == "Customizado"))
193
 
194
+ ui['fp_guidance_preset'].change(fn=toggle_custom_guidance, inputs=ui['fp_guidance_preset'], outputs=ui['custom_guidance_group'])
 
 
 
 
195
 
 
196
  gen_inputs = [
197
  ui['generation_mode'], ui['prompt'], ui['neg_prompt'], ui['start_image'],
198
+ ui['height'], ui['width'], ui['duration'],
199
+ ui['fp_guidance_preset'], ui['fp_guidance_scale_list'], ui['fp_stg_scale_list'],
200
+ ui['fp_num_inference_steps'], ui['fp_skip_initial_steps'], ui['fp_skip_final_steps'],
 
 
201
  ]
202
+ gen_outputs = [ui['low_res_video_output'], app_state, ui['post_prod_group']]
203
  ui['generate_low_btn'].click(fn=run_generate_base_video, inputs=gen_inputs, outputs=gen_outputs)
204
 
 
205
  refine_inputs = [app_state, ui['prompt'], ui['neg_prompt']]
206
  refine_outputs = [ui['ltx_refined_video_output'], app_state]
207
  ui['ltx_refine_btn'].click(fn=run_ltx_refinement, inputs=refine_inputs, outputs=refine_outputs)
208
 
209
+ # (Handlers para o SeedVR, se ativados)
 
 
 
 
 
210
 
211
  # ==============================================================================
212
+ # --- PONTO DE ENTRADA DA APLICAÇÃO ---
213
  # ==============================================================================
214
 
215
  if __name__ == "__main__":
 
217
  gradio_app = build_ui()
218
  print("Launching Gradio app...")
219
  gradio_app.queue().launch(
220
+ server_name=os.getenv("GRADIO_SERVER_NAME", "0.0.0.0"),
221
+ server_port=int(os.getenv("GRADIO_SERVER_PORT", "7860")),
 
222
  show_error=True
223
  )