Carlosxxxxxx commited on
Commit
aff61f5
·
verified ·
1 Parent(s): 289d4f1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +91 -62
app.py CHANGED
@@ -2,9 +2,9 @@
2
  #
3
  # Copyright (C) August 4, 2025 Carlos Rodrigues dos Santos
4
  #
5
- # Versão 9.0.0 (Live Dramatization UI)
6
- # Esta versão implementa a lógica de exibição do chat em tempo real,
7
- # criando o efeito de "digitação" e "pensamento" 100% na camada da UI.
8
 
9
  import gradio as gr
10
  import yaml
@@ -13,7 +13,6 @@ import os
13
  import sys
14
  import shutil
15
  import time
16
- from typing import Dict, Any, Generator
17
 
18
  # --- 1. IMPORTAÇÃO DO FRAMEWORK E CONFIGURAÇÃO ---
19
  import aduc_framework
@@ -44,7 +43,6 @@ try:
44
  logger.info("Interface Gradio inicializada e conectada ao Aduc Framework.")
45
  except Exception as e:
46
  logger.critical(f"ERRO CRÍTICO durante a inicialização: {e}", exc_info=True)
47
- # Bloco de erro para a UI se o framework não iniciar
48
  with gr.Blocks() as demo_error:
49
  gr.Markdown("# ERRO CRÍTICO NA INICIALIZAÇÃO")
50
  gr.Markdown("Não foi possível iniciar o Aduc Framework. Verifique os logs (`aduc_log.txt`) para mais detalhes.")
@@ -52,12 +50,12 @@ except Exception as e:
52
  demo_error.launch()
53
  exit()
54
 
55
- # --- 2. FUNÇÃO WRAPPER (UI <-> FRAMEWORK) ---
56
 
57
  def run_pre_production_wrapper(prompt, num_scenes, ref_files, resolution_str, fast_mode, progress=gr.Progress(track_tqdm=True)):
58
  """
59
- Wrapper que consome os yields do orquestrador e os "dramatiza" para a UI,
60
- criando o efeito de chat em tempo real SEM alterar o backend.
61
  """
62
  if not ref_files:
63
  raise gr.Error("Por favor, forneça pelo menos uma imagem de referência.")
@@ -70,102 +68,133 @@ def run_pre_production_wrapper(prompt, num_scenes, ref_files, resolution_str, fa
70
  resolution=target_resolution, duration_per_fragment=4.0, fast_mode=fast_mode
71
  )
72
 
73
- # --- ESTADO DA UI ---
74
  chatbot_display_history = []
75
  fully_displayed_message_count = 0
 
76
 
77
- # Consome os yields do orquestrador em tempo real
78
  for update in aduc.task_pre_production(params, progress_callback=progress):
79
-
80
  backend_chat_dna = update.get("chat_dna", [])
81
  dna_snapshot = update.get("dna_snapshot", gr.skip())
 
 
82
 
83
- # --- LÓGICA DE DRAMATIZAÇÃO ---
84
- # Processa todas as novas mensagens que chegaram do backend
85
  while len(backend_chat_dna) > fully_displayed_message_count:
86
-
87
  new_message_obj = backend_chat_dna[fully_displayed_message_count]
88
  role = f"**{new_message_obj.get('role', 'Sistema')}**"
89
  content_to_type = new_message_obj.get('content', '')
90
-
91
- # Adiciona um placeholder para a nova mensagem na tela
92
  chatbot_display_history.append([role, ""])
93
-
94
  full_typed_message = ""
95
  for char in content_to_type:
96
  full_typed_message += char
97
- chatbot_display_history[-1][1] = full_typed_message + "▌" # Adiciona cursor
98
- yield {
99
- chat_history_chatbot: chatbot_display_history,
100
- dna_display: dna_snapshot
101
- }
102
  time.sleep(0.02)
103
-
104
- chatbot_display_history[-1][1] = full_typed_message # Remove cursor
105
- yield {
106
- chat_history_chatbot: chatbot_display_history,
107
- dna_display: dna_snapshot
108
- }
109
-
110
  fully_displayed_message_count += 1
111
-
112
- # --- EFEITO DE "PENSANDO" ---
113
  if "Llama, preciso da sua ajuda" in content_to_type:
114
  chatbot_display_history.append([f"**Llama (IA Criativa)**", "..."])
115
- yield {
116
- chat_history_chatbot: chatbot_display_history,
117
- dna_display: dna_snapshot
118
- }
119
  time.sleep(1.5)
120
- chatbot_display_history.pop() # Remove o "..."
 
 
121
 
122
- # Garante que o DNA continue atualizando mesmo sem novas mensagens de chat
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  yield {
124
- chat_history_chatbot: chatbot_display_history,
125
- dna_display: dna_snapshot,
126
  }
 
 
 
 
 
 
 
 
127
 
128
  # --- 3. DEFINIÇÃO DA UI ---
129
  with gr.Blocks(css="style.css") as demo:
130
  generation_state_holder = gr.State(value={})
131
 
132
  gr.Markdown("<h1>ADUC-SDR 🎬 - A Sala de Roteiristas de IA</h1>")
133
- gr.Markdown("Observe em tempo real a equipe de IAs especialistas colaborar para criar seu filme.")
134
-
135
- with gr.Row():
136
- with gr.Column(scale=1):
137
- with gr.Accordion("🤖 A Equipe de IA (Ao Vivo)", open=True):
138
- chat_history_chatbot = gr.Chatbot(
139
- label="Conversa da Equipe",
140
- bubble_full_width=False,
141
- height=500,
142
- )
143
-
144
- with gr.Column(scale=1):
145
- with gr.Accordion("🧬 DNA da Produção (Ao Vivo)", open=True):
146
- dna_display = gr.JSON(label="DNA em Construção", scale=2)
147
- with gr.Accordion("🎞️ Resultado Final", open=True):
148
- final_video_output = gr.Video(label="Filme Concluído", interactive=False)
149
-
150
- with gr.Accordion("📋 Briefing do Projeto (Sua Entrada)", open=True):
151
  prompt_input = gr.Textbox(label="Ideia Geral do Filme", value="Um leão majestoso caminha pela savana e ruge para o sol poente.")
152
  with gr.Row():
153
  resolution_selector = gr.Radio(["512x512", "768x768"], value="512x512", label="Resolução Base")
154
  num_scenes_slider = gr.Slider(minimum=2, maximum=5, value=3, step=1, label="Número de Cenas")
155
  ref_image_input = gr.File(label="Imagens de Referência", file_count="multiple", file_types=["image"])
156
  fast_mode_checkbox = gr.Checkbox(label="Modo Rápido (Planejamento em etapa única)", value=False)
157
- start_button = gr.Button("🎬 Enviar Briefing para a Equipe de IA", variant="primary")
158
 
159
- with gr.Accordion("Etapa 2 & 3: Produção e Pós-Produção", open=False, visible=False) as production_accordion:
160
- gr.Markdown("Após a pré-produção, os controles para gerar o vídeo final aparecerão aqui.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
 
162
  # --- 4. CONEXÕES DE EVENTOS ---
163
- start_button.click(
 
 
 
 
 
164
  fn=run_pre_production_wrapper,
165
  inputs=[prompt_input, num_scenes_slider, ref_image_input, resolution_selector, fast_mode_checkbox],
166
- outputs=[chat_history_chatbot, dna_display] # Removidos os outputs que não são mais necessários aqui
167
  )
168
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  # --- 5. INICIALIZAÇÃO DA APLICAÇÃO ---
170
  if __name__ == "__main__":
171
  if os.path.exists(WORKSPACE_DIR):
 
2
  #
3
  # Copyright (C) August 4, 2025 Carlos Rodrigues dos Santos
4
  #
5
+ # Versão 9.1.0 (Reactivated Keyframe Generation UI)
6
+ # Esta versão reintroduz a UI e a lógica para a Etapa 2 (Geração de Keyframes),
7
+ # conectando o resultado da pré-produção (roteiro) com a engine de criação de imagens.
8
 
9
  import gradio as gr
10
  import yaml
 
13
  import sys
14
  import shutil
15
  import time
 
16
 
17
  # --- 1. IMPORTAÇÃO DO FRAMEWORK E CONFIGURAÇÃO ---
18
  import aduc_framework
 
43
  logger.info("Interface Gradio inicializada e conectada ao Aduc Framework.")
44
  except Exception as e:
45
  logger.critical(f"ERRO CRÍTICO durante a inicialização: {e}", exc_info=True)
 
46
  with gr.Blocks() as demo_error:
47
  gr.Markdown("# ERRO CRÍTICO NA INICIALIZAÇÃO")
48
  gr.Markdown("Não foi possível iniciar o Aduc Framework. Verifique os logs (`aduc_log.txt`) para mais detalhes.")
 
50
  demo_error.launch()
51
  exit()
52
 
53
+ # --- 2. FUNÇÕES WRAPPER (UI <-> FRAMEWORK) ---
54
 
55
  def run_pre_production_wrapper(prompt, num_scenes, ref_files, resolution_str, fast_mode, progress=gr.Progress(track_tqdm=True)):
56
  """
57
+ Wrapper para a Etapa 1 (Pré-Produção). Consome os yields do orquestrador e
58
+ "dramatiza" o chat para a UI. Ao final, habilita a Etapa 2.
59
  """
60
  if not ref_files:
61
  raise gr.Error("Por favor, forneça pelo menos uma imagem de referência.")
 
68
  resolution=target_resolution, duration_per_fragment=4.0, fast_mode=fast_mode
69
  )
70
 
 
71
  chatbot_display_history = []
72
  fully_displayed_message_count = 0
73
+ final_dna = {}
74
 
 
75
  for update in aduc.task_pre_production(params, progress_callback=progress):
 
76
  backend_chat_dna = update.get("chat_dna", [])
77
  dna_snapshot = update.get("dna_snapshot", gr.skip())
78
+ if update.get("status") == "complete":
79
+ final_dna = update.get("dna", {})
80
 
 
 
81
  while len(backend_chat_dna) > fully_displayed_message_count:
 
82
  new_message_obj = backend_chat_dna[fully_displayed_message_count]
83
  role = f"**{new_message_obj.get('role', 'Sistema')}**"
84
  content_to_type = new_message_obj.get('content', '')
 
 
85
  chatbot_display_history.append([role, ""])
 
86
  full_typed_message = ""
87
  for char in content_to_type:
88
  full_typed_message += char
89
+ chatbot_display_history[-1][1] = full_typed_message + "▌"
90
+ yield { chat_history_chatbot: chatbot_display_history, dna_display: dna_snapshot }
 
 
 
91
  time.sleep(0.02)
92
+ chatbot_display_history[-1][1] = full_typed_message
93
+ yield { chat_history_chatbot: chatbot_display_history, dna_display: dna_snapshot }
 
 
 
 
 
94
  fully_displayed_message_count += 1
 
 
95
  if "Llama, preciso da sua ajuda" in content_to_type:
96
  chatbot_display_history.append([f"**Llama (IA Criativa)**", "..."])
97
+ yield { chat_history_chatbot: chatbot_display_history, dna_display: dna_snapshot }
 
 
 
98
  time.sleep(1.5)
99
+ chatbot_display_history.pop()
100
+
101
+ yield { chat_history_chatbot: chatbot_display_history, dna_display: dna_snapshot }
102
 
103
+ # Retorno final para habilitar a próxima etapa
104
+ yield {
105
+ chat_history_chatbot: chatbot_display_history,
106
+ dna_display: final_dna,
107
+ step2_accordion: gr.update(visible=True, open=True) # HABILITA A ETAPA 2
108
+ }
109
+
110
+
111
+ def run_keyframe_generation_wrapper(current_state_dict, progress=gr.Progress(track_tqdm=True)):
112
+ """
113
+ Wrapper para a Etapa 2 (Geração de Keyframes).
114
+ Chama o orquestrador e atualiza a galeria em tempo real.
115
+ """
116
+ for update in aduc.task_generate_keyframes(current_state_dict, progress_callback=progress):
117
+ keyframe_paths = update.get("keyframe_paths", [])
118
+
119
  yield {
120
+ keyframe_gallery: gr.update(value=keyframe_paths),
121
+ generation_state_holder: update.get("updated_state", gr.skip())
122
  }
123
+
124
+ if update.get("status") == "keyframes_complete":
125
+ yield {
126
+ keyframe_gallery: gr.update(value=keyframe_paths),
127
+ generation_state_holder: update.get("updated_state"),
128
+ step3_accordion: gr.update(visible=True, open=True) # HABILITA A ETAPA 3
129
+ }
130
+ return
131
 
132
  # --- 3. DEFINIÇÃO DA UI ---
133
  with gr.Blocks(css="style.css") as demo:
134
  generation_state_holder = gr.State(value={})
135
 
136
  gr.Markdown("<h1>ADUC-SDR 🎬 - A Sala de Roteiristas de IA</h1>")
137
+
138
+ # ETAPA 1
139
+ with gr.Accordion("Etapa 1: Planejamento do Roteiro", open=True):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  prompt_input = gr.Textbox(label="Ideia Geral do Filme", value="Um leão majestoso caminha pela savana e ruge para o sol poente.")
141
  with gr.Row():
142
  resolution_selector = gr.Radio(["512x512", "768x768"], value="512x512", label="Resolução Base")
143
  num_scenes_slider = gr.Slider(minimum=2, maximum=5, value=3, step=1, label="Número de Cenas")
144
  ref_image_input = gr.File(label="Imagens de Referência", file_count="multiple", file_types=["image"])
145
  fast_mode_checkbox = gr.Checkbox(label="Modo Rápido (Planejamento em etapa única)", value=False)
146
+ start_planning_button = gr.Button("📝 Iniciar Planejamento (Etapa 1)", variant="primary")
147
 
148
+ with gr.Accordion("🧠 Diário do Planejador (Ao Vivo)", open=False) as planning_log_accordion:
149
+ with gr.Row():
150
+ chat_history_chatbot = gr.Chatbot(label="Conversa da Equipe", bubble_full_width=False, height=500, scale=1)
151
+ dna_display = gr.JSON(label="DNA da Produção (em construção)", scale=1)
152
+
153
+ # ETAPA 2 (RESTAURADA)
154
+ with gr.Accordion("Etapa 2: Geração de Keyframes (Cenas-Chave)", open=False, visible=False) as step2_accordion:
155
+ gr.Markdown("O roteiro foi aprovado. Agora, o Diretor de IA irá criar as cenas-chave (keyframes) para cada ato.")
156
+ start_keyframe_button = gr.Button("🖼️ Gerar Keyframes a partir do Roteiro (Etapa 2)", variant="primary")
157
+ keyframe_gallery = gr.Gallery(label="Keyframes Gerados (em tempo real)", visible=True, object_fit="contain", height="auto")
158
+
159
+ # ETAPA 3
160
+ with gr.Accordion("Etapa 3: Produção do Vídeo Original", open=False, visible=False) as step3_accordion:
161
+ gr.Markdown("Com os keyframes definidos, vamos gerar o vídeo principal.")
162
+ # ... (Sliders e botão de produção aqui, se necessário) ...
163
+ produce_original_button = gr.Button("🎬 Produzir Vídeo Original (Etapa 3)", variant="primary")
164
+
165
+ # SAÍDA E LOGS
166
+ with gr.Accordion("🎞️ Resultado Final", open=True):
167
+ final_video_output = gr.Video(label="Filme Concluído", interactive=False)
168
+ # ... (outros componentes de log/pós-produção podem ser adicionados aqui) ...
169
 
170
  # --- 4. CONEXÕES DE EVENTOS ---
171
+
172
+ # Fluxo da Etapa 1
173
+ start_planning_button.click(
174
+ fn=lambda: gr.update(open=True),
175
+ outputs=[planning_log_accordion]
176
+ ).then(
177
  fn=run_pre_production_wrapper,
178
  inputs=[prompt_input, num_scenes_slider, ref_image_input, resolution_selector, fast_mode_checkbox],
179
+ outputs=[chat_history_chatbot, dna_display, step2_accordion]
180
  )
181
 
182
+ # Garante que o estado seja atualizado com o DNA final da Etapa 1
183
+ dna_display.change(
184
+ fn=lambda data: data,
185
+ inputs=dna_display,
186
+ outputs=generation_state_holder
187
+ )
188
+
189
+ # Fluxo da Etapa 2
190
+ start_keyframe_button.click(
191
+ fn=run_keyframe_generation_wrapper,
192
+ inputs=[generation_state_holder],
193
+ outputs=[keyframe_gallery, generation_state_holder, step3_accordion]
194
+ )
195
+
196
+ # (Conexão para Etapa 3 e pós-produção será adicionada aqui depois)
197
+
198
  # --- 5. INICIALIZAÇÃO DA APLICAÇÃO ---
199
  if __name__ == "__main__":
200
  if os.path.exists(WORKSPACE_DIR):