eeuuia commited on
Commit
8bf282e
·
verified ·
1 Parent(s): 90b1312

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -13
app.py CHANGED
@@ -1,6 +1,7 @@
1
  # FILE: app.py
2
  # DESCRIPTION: Final Gradio web interface for the ADUC-SDR Video Suite.
3
- # This version definitively removes the guidance settings from the UI for a streamlined experience.
 
4
 
5
  import gradio as gr
6
  import traceback
@@ -11,22 +12,30 @@ import logging
11
  # ==============================================================================
12
  # --- IMPORTAÇÃO DOS SERVIÇOS DE BACKEND E UTILS ---
13
  # ==============================================================================
 
14
  try:
 
15
  from api.ltx_server_refactored_complete import video_generation_service
 
 
16
  from api.utils.debug_utils import log_function_io
 
 
17
  from api.seedvr_server import seedvr_server_singleton as seedvr_inference_server
 
18
  logging.info("All backend services (LTX, SeedVR) and debug utils imported successfully.")
 
19
  except ImportError as e:
20
  def log_function_io(func): return func
21
- logging.warning(f"Could not import a module. Some services or debug logs may be unavailable. Details: {e}")
22
  if 'video_generation_service' not in locals():
23
  logging.critical(f"FATAL: Main LTX service failed to import.", exc_info=True)
24
  sys.exit(1)
25
  if 'seedvr_inference_server' not in locals():
26
  seedvr_inference_server = None
27
- logging.warning("SeedVR server could not be initialized. Upscaling tab will be disabled.")
28
  except Exception as e:
29
- logging.critical(f"FATAL ERROR during backend initialization. Details: {e}", exc_info=True)
30
  sys.exit(1)
31
 
32
  # ==============================================================================
@@ -37,12 +46,14 @@ except Exception as e:
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,
 
40
  fp_num_inference_steps: int, fp_skip_initial_steps: int, fp_skip_final_steps: int,
41
  progress=gr.Progress(track_tqdm=True)
42
  ) -> tuple:
43
- """Wrapper that collects UI data and calls the backend (without guidance parameters)."""
44
  try:
45
  logging.info(f"[UI] Request received. Selected mode: {generation_mode}")
 
46
  initial_conditions = []
47
  if start_img:
48
  num_frames_estimate = int(duration * 24)
@@ -52,6 +63,9 @@ def run_generate_base_video(
52
  )
53
 
54
  ltx_configs = {
 
 
 
55
  "num_inference_steps": fp_num_inference_steps,
56
  "skip_initial_inference_steps": fp_skip_initial_steps,
57
  "skip_final_inference_steps": fp_skip_final_steps,
@@ -64,6 +78,7 @@ def run_generate_base_video(
64
  )
65
 
66
  if not video_path: raise RuntimeError("Backend failed to return a valid video path.")
 
67
  new_state = {"low_res_video": video_path, "low_res_latents": tensor_path, "used_seed": final_seed}
68
  logging.info(f"[UI] Base video generation successful. Seed used: {final_seed}, Path: {video_path}")
69
  return video_path, new_state, gr.update(visible=True)
@@ -75,14 +90,16 @@ def run_generate_base_video(
75
 
76
  @log_function_io
77
  def run_ltx_refinement(state: dict, prompt: str, neg_prompt: str, progress=gr.Progress(track_tqdm=True)) -> tuple:
78
- """Wrapper for the LTX texture refinement function."""
79
  if not state or not state.get("low_res_latents"):
80
  raise gr.Error("Error: Please generate a base video in Step 1 before refining.")
 
81
  try:
82
  logging.info(f"[UI] Requesting LTX refinement for latents: {state.get('low_res_latents')}")
83
  video_path, tensor_path = video_generation_service.generate_upscale_denoise(
84
  latents_path=state["low_res_latents"],
85
- prompt=prompt, negative_prompt=neg_prompt,
 
86
  seed=state["used_seed"]
87
  )
88
  state["refined_video_ltx"] = video_path
@@ -96,18 +113,21 @@ def run_ltx_refinement(state: dict, prompt: str, neg_prompt: str, progress=gr.Pr
96
 
97
  @log_function_io
98
  def run_seedvr_upscaling(state: dict, seed: int, resolution: int, batch_size: int, fps: int, progress=gr.Progress(track_tqdm=True)) -> tuple:
99
- """Wrapper for the SeedVR resolution upscaling service."""
100
  if not state or not state.get("low_res_video"):
101
  raise gr.Error("Error: Please generate a base video in Step 1 before upscaling.")
102
  if not seedvr_inference_server:
103
  raise gr.Error("Error: The SeedVR upscaling server is not available.")
 
104
  try:
105
  logging.info(f"[UI] Requesting SeedVR upscaling for video: {state.get('low_res_video')}")
106
  def progress_wrapper(p, desc=""): progress(p, desc=desc)
 
107
  output_filepath = seedvr_inference_server.run_inference(
108
  file_path=state["low_res_video"], seed=int(seed), resolution=int(resolution),
109
  batch_size=int(batch_size), fps=float(fps), progress=progress_wrapper
110
  )
 
111
  status_message = f"✅ Upscaling complete!\nSaved to: {output_filepath}"
112
  logging.info(f"[UI] SeedVR upscaling successful. Path: {output_filepath}")
113
  return gr.update(value=output_filepath), gr.update(value=status_message)
@@ -121,7 +141,7 @@ def run_seedvr_upscaling(state: dict, seed: int, resolution: int, batch_size: in
121
  # ==============================================================================
122
 
123
  def build_ui():
124
- """Builds the entire Gradio application UI."""
125
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo")) as demo:
126
  app_state = gr.State(value={"low_res_video": None, "low_res_latents": None, "used_seed": None})
127
  ui_components = {}
@@ -137,9 +157,9 @@ def build_ui():
137
  return demo
138
 
139
  def _build_generation_controls(ui: dict):
140
- """Builds the UI components for Step 1, with the guidance section removed."""
141
  gr.Markdown("### Configurações de Geração")
142
- ui['generation_mode'] = gr.Radio(label="Modo de Geração", choices=["Simples (Prompt Único)", "Narrativa (Múltiplos Prompts)"], value="Narrativa (Múltiplos Prompts)")
143
  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)
144
  ui['neg_prompt'] = gr.Textbox(label="Negative Prompt", value="blurry, low quality, bad anatomy, deformed", lines=2)
145
  ui['start_image'] = gr.Image(label="Imagem de Início (Opcional)", type="filepath", sources=["upload"])
@@ -156,11 +176,18 @@ def _build_generation_controls(ui: dict):
156
  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.")
157
  ui['fp_skip_initial_steps'] = gr.Slider(label="Pular Passos Iniciais", minimum=0, maximum=100, step=1, value=0)
158
  ui['fp_skip_final_steps'] = gr.Slider(label="Pular Passos Finais", minimum=0, maximum=100, step=1, value=0)
 
 
 
 
 
 
 
159
 
160
  ui['generate_low_btn'] = gr.Button("1. Gerar Vídeo Base", variant="primary")
161
 
162
  def _build_postprod_controls(ui: dict):
163
- """Builds the UI components for Step 2: Post-Production."""
164
  with gr.Group(visible=False) as ui['post_prod_group']:
165
  gr.Markdown("--- \n## Etapa 2: Pós-Produção")
166
  with gr.Tabs():
@@ -188,13 +215,19 @@ def _build_postprod_controls(ui: dict):
188
  ui['seedvr_status_box'] = gr.Textbox(label="Status do SeedVR", value="Aguardando...", lines=3, interactive=False)
189
 
190
  def _register_event_handlers(app_state: gr.State, ui: dict):
191
- """Registers all Gradio event handlers."""
 
 
 
 
 
192
  def update_seed_display(state):
193
  return state.get("used_seed", "N/A")
194
 
195
  gen_inputs = [
196
  ui['generation_mode'], ui['prompt'], ui['neg_prompt'], ui['start_image'],
197
  ui['height'], ui['width'], ui['duration'],
 
198
  ui['fp_num_inference_steps'], ui['fp_skip_initial_steps'], ui['fp_skip_final_steps'],
199
  ]
200
  gen_outputs = [ui['low_res_video_output'], app_state, ui['post_prod_group']]
@@ -214,6 +247,7 @@ def _register_event_handlers(app_state: gr.State, ui: dict):
214
  # ==============================================================================
215
  # --- PONTO DE ENTRADA DA APLICAÇÃO ---
216
  # ==============================================================================
 
217
  if __name__ == "__main__":
218
  log_level = os.environ.get("ADUC_LOG_LEVEL", "INFO").upper()
219
  logging.basicConfig(level=log_level, format='[%(levelname)s] [%(name)s] %(message)s')
 
1
  # FILE: app.py
2
  # DESCRIPTION: Final Gradio web interface for the ADUC-SDR Video Suite.
3
+ # Features dimension sliders locked to multiples of 8, a unified LTX workflow,
4
+ # advanced controls, integrated SeedVR upscaling, and detailed debug logging.
5
 
6
  import gradio as gr
7
  import traceback
 
12
  # ==============================================================================
13
  # --- IMPORTAÇÃO DOS SERVIÇOS DE BACKEND E UTILS ---
14
  # ==============================================================================
15
+
16
  try:
17
+ # Serviço principal para geração LTX
18
  from api.ltx_server_refactored_complete import video_generation_service
19
+
20
+ # Nosso decorador de logging para depuração
21
  from api.utils.debug_utils import log_function_io
22
+
23
+ # Serviço especialista para upscaling de resolução (SeedVR)
24
  from api.seedvr_server import seedvr_server_singleton as seedvr_inference_server
25
+
26
  logging.info("All backend services (LTX, SeedVR) and debug utils imported successfully.")
27
+
28
  except ImportError as e:
29
  def log_function_io(func): return func
30
+ logging.warning(f"Could not import a module, debug logger might be disabled. SeedVR might be unavailable. Details: {e}")
31
  if 'video_generation_service' not in locals():
32
  logging.critical(f"FATAL: Main LTX service failed to import.", exc_info=True)
33
  sys.exit(1)
34
  if 'seedvr_inference_server' not in locals():
35
  seedvr_inference_server = None
36
+ logging.warning("SeedVR server could not be initialized. The SeedVR upscaling tab will be disabled.")
37
  except Exception as e:
38
+ logging.critical(f"FATAL ERROR: An unexpected error occurred during backend initialization. Details: {e}", exc_info=True)
39
  sys.exit(1)
40
 
41
  # ==============================================================================
 
46
  def run_generate_base_video(
47
  generation_mode: str, prompt: str, neg_prompt: str, start_img: str,
48
  height: int, width: int, duration: float,
49
+ fp_guidance_preset: str, fp_guidance_scale_list: str, fp_stg_scale_list: str,
50
  fp_num_inference_steps: int, fp_skip_initial_steps: int, fp_skip_final_steps: int,
51
  progress=gr.Progress(track_tqdm=True)
52
  ) -> tuple:
53
+ """Wrapper para a geração do vídeo base LTX."""
54
  try:
55
  logging.info(f"[UI] Request received. Selected mode: {generation_mode}")
56
+
57
  initial_conditions = []
58
  if start_img:
59
  num_frames_estimate = int(duration * 24)
 
63
  )
64
 
65
  ltx_configs = {
66
+ "guidance_preset": fp_guidance_preset,
67
+ "guidance_scale_list": fp_guidance_scale_list,
68
+ "stg_scale_list": fp_stg_scale_list,
69
  "num_inference_steps": fp_num_inference_steps,
70
  "skip_initial_inference_steps": fp_skip_initial_steps,
71
  "skip_final_inference_steps": fp_skip_final_steps,
 
78
  )
79
 
80
  if not video_path: raise RuntimeError("Backend failed to return a valid video path.")
81
+
82
  new_state = {"low_res_video": video_path, "low_res_latents": tensor_path, "used_seed": final_seed}
83
  logging.info(f"[UI] Base video generation successful. Seed used: {final_seed}, Path: {video_path}")
84
  return video_path, new_state, gr.update(visible=True)
 
90
 
91
  @log_function_io
92
  def run_ltx_refinement(state: dict, prompt: str, neg_prompt: str, progress=gr.Progress(track_tqdm=True)) -> tuple:
93
+ """Wrapper para o refinamento de textura LTX."""
94
  if not state or not state.get("low_res_latents"):
95
  raise gr.Error("Error: Please generate a base video in Step 1 before refining.")
96
+
97
  try:
98
  logging.info(f"[UI] Requesting LTX refinement for latents: {state.get('low_res_latents')}")
99
  video_path, tensor_path = video_generation_service.generate_upscale_denoise(
100
  latents_path=state["low_res_latents"],
101
+ prompt=prompt,
102
+ negative_prompt=neg_prompt,
103
  seed=state["used_seed"]
104
  )
105
  state["refined_video_ltx"] = video_path
 
113
 
114
  @log_function_io
115
  def run_seedvr_upscaling(state: dict, seed: int, resolution: int, batch_size: int, fps: int, progress=gr.Progress(track_tqdm=True)) -> tuple:
116
+ """Wrapper para o upscale de resolução SeedVR."""
117
  if not state or not state.get("low_res_video"):
118
  raise gr.Error("Error: Please generate a base video in Step 1 before upscaling.")
119
  if not seedvr_inference_server:
120
  raise gr.Error("Error: The SeedVR upscaling server is not available.")
121
+
122
  try:
123
  logging.info(f"[UI] Requesting SeedVR upscaling for video: {state.get('low_res_video')}")
124
  def progress_wrapper(p, desc=""): progress(p, desc=desc)
125
+
126
  output_filepath = seedvr_inference_server.run_inference(
127
  file_path=state["low_res_video"], seed=int(seed), resolution=int(resolution),
128
  batch_size=int(batch_size), fps=float(fps), progress=progress_wrapper
129
  )
130
+
131
  status_message = f"✅ Upscaling complete!\nSaved to: {output_filepath}"
132
  logging.info(f"[UI] SeedVR upscaling successful. Path: {output_filepath}")
133
  return gr.update(value=output_filepath), gr.update(value=status_message)
 
141
  # ==============================================================================
142
 
143
  def build_ui():
144
+ """Constrói a interface completa do Gradio."""
145
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="indigo")) as demo:
146
  app_state = gr.State(value={"low_res_video": None, "low_res_latents": None, "used_seed": None})
147
  ui_components = {}
 
157
  return demo
158
 
159
  def _build_generation_controls(ui: dict):
160
+ """Constrói os componentes da UI para a Etapa 1: Geração."""
161
  gr.Markdown("### Configurações de Geração")
162
+ ui['generation_mode'] = gr.Radio(label="Modo de Geração", choices=["Simples (Prompt Único)", "Narrativa (Múltiplos Prompts)"], value="Narrativa (Múltiplos Prompts)", info="Simples para uma ação contínua, Narrativa para uma sequência (uma cena por linha).")
163
  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)
164
  ui['neg_prompt'] = gr.Textbox(label="Negative Prompt", value="blurry, low quality, bad anatomy, deformed", lines=2)
165
  ui['start_image'] = gr.Image(label="Imagem de Início (Opcional)", type="filepath", sources=["upload"])
 
176
  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.")
177
  ui['fp_skip_initial_steps'] = gr.Slider(label="Pular Passos Iniciais", minimum=0, maximum=100, step=1, value=0)
178
  ui['fp_skip_final_steps'] = gr.Slider(label="Pular Passos Finais", minimum=0, maximum=100, step=1, value=0)
179
+ with gr.Tabs():
180
+ with gr.TabItem("Configurações de Guiagem (First Pass)"):
181
+ ui['fp_guidance_preset'] = gr.Dropdown(label="Preset de Guiagem", choices=["Padrão (Recomendado)", "Agressivo", "Suave", "Customizado"], value="Padrão (Recomendado)", info="Controla o comportamento da guiagem durante a difusão.")
182
+ with gr.Group(visible=False) as ui['custom_guidance_group']:
183
+ gr.Markdown("⚠️ Edite as listas em formato JSON. Ex: `[1.0, 2.5, 3.0]`")
184
+ ui['fp_guidance_scale_list'] = gr.Textbox(label="Lista de Guidance Scale", value="[1, 1, 6, 8, 6, 1, 1]")
185
+ ui['fp_stg_scale_list'] = gr.Textbox(label="Lista de STG Scale (Movimento)", value="[0, 0, 4, 4, 4, 2, 1]")
186
 
187
  ui['generate_low_btn'] = gr.Button("1. Gerar Vídeo Base", variant="primary")
188
 
189
  def _build_postprod_controls(ui: dict):
190
+ """Constrói os componentes da UI para a Etapa 2: Pós-Produção."""
191
  with gr.Group(visible=False) as ui['post_prod_group']:
192
  gr.Markdown("--- \n## Etapa 2: Pós-Produção")
193
  with gr.Tabs():
 
215
  ui['seedvr_status_box'] = gr.Textbox(label="Status do SeedVR", value="Aguardando...", lines=3, interactive=False)
216
 
217
  def _register_event_handlers(app_state: gr.State, ui: dict):
218
+ """Registra todos os manipuladores de eventos do Gradio."""
219
+ def toggle_custom_guidance(preset_choice: str) -> gr.update:
220
+ return gr.update(visible=(preset_choice == "Customizado"))
221
+
222
+ ui['fp_guidance_preset'].change(fn=toggle_custom_guidance, inputs=ui['fp_guidance_preset'], outputs=ui['custom_guidance_group'])
223
+
224
  def update_seed_display(state):
225
  return state.get("used_seed", "N/A")
226
 
227
  gen_inputs = [
228
  ui['generation_mode'], ui['prompt'], ui['neg_prompt'], ui['start_image'],
229
  ui['height'], ui['width'], ui['duration'],
230
+ ui['fp_guidance_preset'], ui['fp_guidance_scale_list'], ui['fp_stg_scale_list'],
231
  ui['fp_num_inference_steps'], ui['fp_skip_initial_steps'], ui['fp_skip_final_steps'],
232
  ]
233
  gen_outputs = [ui['low_res_video_output'], app_state, ui['post_prod_group']]
 
247
  # ==============================================================================
248
  # --- PONTO DE ENTRADA DA APLICAÇÃO ---
249
  # ==============================================================================
250
+
251
  if __name__ == "__main__":
252
  log_level = os.environ.get("ADUC_LOG_LEVEL", "INFO").upper()
253
  logging.basicConfig(level=log_level, format='[%(levelname)s] [%(name)s] %(message)s')