Spaces:
Runtime error
Runtime error
File size: 13,910 Bytes
501fd32 52e5575 501fd32 51363f0 99c6a62 501fd32 52e5575 ffc9fa5 aabed75 52e5575 ffc9fa5 d4ae81a ffc9fa5 51363f0 ffc9fa5 52e5575 51363f0 ffc9fa5 aabed75 ffc9fa5 33ed0b3 aabed75 52e5575 33ed0b3 52e5575 33ed0b3 52e5575 33ed0b3 52e5575 33ed0b3 501fd32 52e5575 ffc9fa5 52e5575 ffc9fa5 52e5575 ffc9fa5 659e451 52e5575 501fd32 52e5575 501fd32 33ed0b3 501fd32 52e5575 99c6a62 33ed0b3 52e5575 99c6a62 ffc9fa5 52e5575 ffc9fa5 52e5575 ffc9fa5 52e5575 ffc9fa5 52e5575 ffc9fa5 52e5575 ffc9fa5 52e5575 51363f0 52e5575 501fd32 99c6a62 501fd32 52e5575 33ed0b3 52e5575 33ed0b3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
# app.py
#
# Copyright (C) August 4, 2025 Carlos Rodrigues dos Santos
#
# Versão 7.0.0 (Reactive UI & Planner-Composer Architecture)
import gradio as gr
import yaml
import logging
import os
import sys
import shutil
# --- 1. IMPORTAÇÃO DO FRAMEWORK E CONFIGURAÇÃO ---
import aduc_framework
from aduc_framework.types import PreProductionParams, ProductionParams
# Configuração de Tema Cinemático (cinematic_theme)
# (O código do tema permanece o mesmo, omitido para brevidade, mas deve estar aqui)
cinematic_theme = gr.themes.Base(
primary_hue=gr.themes.colors.indigo,
secondary_hue=gr.themes.colors.purple,
neutral_hue=gr.themes.colors.slate,
font=(gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui", "sans-serif"),
).set(
body_background_fill="#111827", body_text_color="#E5E7EB",
button_primary_background_fill="linear-gradient(90deg, #4F46E5, #8B5CF6)",
button_primary_text_color="#FFFFFF", button_secondary_background_fill="#374151",
button_secondary_border_color="#4B5563", button_secondary_text_color="#E5E7EB",
block_background_fill="#1F2937", block_border_width="1px", block_border_color="#374151",
block_label_background_fill="#374151", block_label_text_color="#E5E7EB",
block_title_text_color="#FFFFFF", input_background_fill="#374151",
input_border_color="#4B5563", input_placeholder_color="#9CA3AF",
)
# Configuração de Logging
# (O código de logging permanece o mesmo, omitido para brevidade, mas deve estar aqui)
LOG_FILE_PATH = "aduc_log.txt"
if os.path.exists(LOG_FILE_PATH): os.remove(LOG_FILE_PATH)
log_format = '%(asctime)s - %(levelname)s - [%(name)s:%(funcName)s] - %(message)s'
root_logger = logging.getLogger()
root_logger.setLevel(logging.INFO)
root_logger.handlers.clear()
stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setFormatter(logging.Formatter(log_format))
root_logger.addHandler(stream_handler)
file_handler = logging.FileHandler(LOG_FILE_PATH, mode='w', encoding='utf-8')
file_handler.setFormatter(logging.Formatter(log_format))
root_logger.addHandler(file_handler)
logger = logging.getLogger(__name__)
# Inicialização do Aduc Framework
try:
with open("config.yaml", 'r') as f: config = yaml.safe_load(f)
WORKSPACE_DIR = config['application']['workspace_dir']
aduc = aduc_framework.create_aduc_instance(workspace_dir=WORKSPACE_DIR)
logger.info("Interface Gradio inicializada e conectada ao Aduc Framework.")
except Exception as e:
logger.critical(f"ERRO CRÍTICO durante a inicialização: {e}", exc_info=True)
# Bloco de erro do Gradio, se a inicialização falhar
with gr.Blocks() as demo:
gr.Markdown("# ERRO CRÍTICO NA INICIALIZAÇÃO")
gr.Markdown("Não foi possível iniciar o Aduc Framework. Verifique os logs para mais detalhes.")
gr.Textbox(value=str(e), label="Detalhes do Erro", lines=10)
demo.launch()
exit()
# --- 2. FUNÇÕES WRAPPER (UI <-> FRAMEWORK) ---
def run_pre_production_wrapper(prompt, num_scenes, ref_files, resolution_str, duration_per_fragment, progress=gr.Progress(track_tqdm=True)):
"""
Wrapper reativo para a fase de pré-produção.
Captura os eventos do Composer e atualiza a UI em tempo real.
"""
if not ref_files:
raise gr.Error("Por favor, forneça pelo menos uma imagem de referência.")
target_resolution = int(resolution_str.split('x')[0])
# Processa as imagens de referência
ref_paths = [aduc.process_image_for_story(f.name, target_resolution, f"ref_processed_{i}.png") for i, f in enumerate(ref_files)]
params = PreProductionParams(
prompt=prompt,
num_scenes=int(num_scenes),
ref_paths=ref_paths,
resolution=target_resolution,
duration_per_fragment=duration_per_fragment
)
log_history = ""
# Loop principal que consome o gerador do orquestrador
for update in aduc.task_pre_production(params, progress_callback=progress):
status = update.get("status")
message = update.get("message", "")
# Constrói o histórico de logs para a UI
log_entry = f"[{status.upper()}] {message}\n"
log_history += log_entry
# Gera o dicionário de atualização para os componentes da UI
yield {
log_display_realtime: log_history,
dna_display: update.get("dna_snapshot", gr.skip()),
}
if status == "error":
raise gr.Error(f"Ocorreu um erro no backend: {message}")
if status == "pre_production_complete":
# Quando a pré-produção termina, habilita os próximos passos
yield {
log_display_realtime: log_history,
dna_display: update.get("dna_snapshot"),
keyframe_gallery: gr.update(value=update.get("keyframe_gallery", [])),
step3_accordion: gr.update(visible=True, open=True)
}
# O gerador termina aqui para a pré-produção
return
def run_production_wrapper(current_state_dict, trim_percent, handler_strength, dest_strength, guidance_scale, stg_scale, steps, progress=gr.Progress(track_tqdm=True)):
"""Wrapper para a geração do vídeo principal."""
yield {final_video_output: gr.update(value=None, visible=True, label="🎬 Produzindo seu filme...")}
# Esta função no orquestrador não é um gerador, então a chamamos diretamente.
# Precisaremos do estado atual (DNA) que foi salvo no `generation_state_holder`.
# AducDirector precisará de um método para carregar este estado.
# Por agora, vamos simular passando o dicionário.
# aduc.director.load_state_from_dict(current_state_dict) # Idealmente
production_params = ProductionParams(
trim_percent=int(trim_percent), handler_strength=handler_strength,
destination_convergence_strength=dest_strength, guidance_scale=guidance_scale,
stg_scale=stg_scale, inference_steps=int(steps)
)
# Assumindo que o `task_produce_original_movie` usa o estado já no `aduc.director`
# (que foi atualizado pela pré-produção)
final_video_path, latent_paths, updated_state = aduc.task_produce_original_movie(params=production_params, progress_callback=progress)
yield {
final_video_output: gr.update(value=final_video_path, label="✅ Filme Original Master"),
step4_accordion: gr.update(visible=True, open=True),
original_latents_paths_state: latent_paths,
current_source_video_state: final_video_path,
generation_state_holder: updated_state.model_dump(),
}
# ... (Os wrappers de pós-produção permanecem os mesmos, pois já usam geradores) ...
def get_log_content():
try:
with open(LOG_FILE_PATH, "r", encoding="utf-8") as f:
return f.read()
except FileNotFoundError:
return "Arquivo de log ainda não criado."
# --- 3. DEFINIÇÃO DA UI ---
with gr.Blocks(theme=cinematic_theme, css="style.css") as demo:
# Componentes de Estado
generation_state_holder = gr.State(value={})
original_latents_paths_state = gr.State(value=[])
current_source_video_state = gr.State(value=None)
# Título
gr.Markdown("<h1>ADUC-SDR 🎬 - O Diretor de Cinema IA</h1>")
gr.Markdown("<p>Crie um filme completo com vídeo e áudio, orquestrado por uma equipe de IAs especialistas.</p>")
# Etapa 1: Pré-Produção
with gr.Accordion("Etapa 1: Planejamento (Pré-Produção)", open=True) as step1_accordion:
prompt_input = gr.Textbox(label="Ideia Geral do Filme", value="Um leão majestoso caminha pela savana, senta-se e ruge para o sol poente.")
with gr.Row():
resolution_selector = gr.Radio(["512x512", "768x768", "1024x1024"], value="512x512", label="Resolução Base")
num_scenes_slider = gr.Slider(minimum=2, maximum=10, value=3, step=1, label="Número de Cenas do Filme")
ref_image_input = gr.File(label="Imagens de Referência (Material Bibliográfico)", file_count="multiple", file_types=["image"])
duration_per_fragment_slider = gr.Slider(label="Duração Máxima de cada Ato (s)", minimum=2.0, maximum=10.0, value=4.0, step=0.1)
start_planning_button = gr.Button("Iniciar Planejamento de Pré-Produção", variant="primary")
# Accordion para mostrar o progresso do planejamento em tempo real
with gr.Accordion("🧠 Diário do Planejador (Pré-Produção em Tempo Real)", open=False) as planning_log_accordion:
log_display_realtime = gr.Textbox(label="Log da Conversa com IA", lines=15, interactive=False, autoscroll=True)
dna_display = gr.JSON(label="DNA da Produção (em construção)")
# Etapa 2: Produção
with gr.Accordion("Etapa 2: Produção do Vídeo Original", open=False, visible=False) as step3_accordion:
# ... (Sliders de produção permanecem os mesmos) ...
trim_percent_slider = gr.Slider(minimum=10, maximum=90, value=50, step=5, label="Poda Causal (%)")
handler_strength = gr.Slider(label="Força do Déjà-Vu", minimum=0.0, maximum=1.0, value=0.5, step=0.05)
dest_strength = gr.Slider(label="Força da Âncora Final", minimum=0.0, maximum=1.0, value=0.75, step=0.05)
guidance_scale_slider = gr.Slider(minimum=1.0, maximum=10.0, value=2.0, step=0.1, label="Escala de Orientação")
stg_scale_slider = gr.Slider(minimum=0.0, maximum=1.0, value=0.025, step=0.005, label="Escala STG")
inference_steps_slider = gr.Slider(minimum=10, maximum=50, value=20, step=1, label="Passos de Inferência")
produce_original_button = gr.Button("🎬 Produzir Vídeo Original", variant="primary")
# Etapa 3: Pós-Produção
with gr.Accordion("Etapa 3: Pós-Produção (Opcional)", open=False, visible=False) as step4_accordion:
# ... (Componentes de pós-produção permanecem os mesmos) ...
gr.Markdown("Aplique melhorias ao filme. Cada etapa usa o resultado da anterior como fonte.")
with gr.Accordion("A. Upscaler Latente 2x", open=True):
upscaler_chunk_size_slider = gr.Slider(minimum=1, maximum=10, value=2, step=1, label="Fragmentos por Lote")
run_upscaler_button = gr.Button("Executar Upscaler Latente", variant="secondary")
with gr.Accordion("B. Masterização HD (SeedVR)", open=True):
hd_steps_slider = gr.Slider(minimum=20, maximum=150, value=100, step=5, label="Passos de Inferência HD")
run_hd_button = gr.Button("Executar Masterização HD", variant="secondary")
with gr.Accordion("C. Geração de Áudio", open=True):
audio_prompt_input = gr.Textbox(label="Prompt de Áudio Detalhado (Opcional)", lines=2, placeholder="Descreva os sons, efeitos e música.")
run_audio_button = gr.Button("Gerar Áudio", variant="secondary")
# Saídas Finais e Logs
final_video_output = gr.Video(label="Filme Final (Resultado da Última Etapa)", visible=False, interactive=False)
with gr.Accordion("🖼️ Galeria de Keyframes (Referência)", open=False) as keyframes_accordion:
keyframe_gallery = gr.Gallery(label="Keyframes Gerados", visible=True, object_fit="contain", height="auto")
with gr.Accordion("📝 Log de Sessão (Completo)", open=False) as log_accordion:
log_display_full = gr.Textbox(label="Log da Sessão", lines=20, interactive=False, autoscroll=True)
update_log_button = gr.Button("Atualizar Log Completo")
# --- 4. CONEXÕES DE EVENTOS ---
# Conexão principal para a pré-produção reativa
start_planning_button.click(
fn=lambda: gr.update(open=True), outputs=[planning_log_accordion] # Abre o accordion de log
).then(
fn=run_pre_production_wrapper,
inputs=[prompt_input, num_scenes_slider, ref_image_input, resolution_selector, duration_per_fragment_slider],
outputs=[log_display_realtime, dna_display, keyframe_gallery, step3_accordion]
)
# Conexões para as etapas seguintes
produce_original_button.click(
fn=run_production_wrapper,
inputs=[generation_state_holder, trim_percent_slider, handler_strength, dest_strength, guidance_scale_slider, stg_scale_slider, inference_steps_slider],
outputs=[final_video_output, step4_accordion, original_latents_paths_state, current_source_video_state, generation_state_holder]
)
run_upscaler_button.click(
fn=aduc.task_run_latent_upscaler, # Chamando diretamente se já for um gerador
inputs=[original_latents_paths_state, upscaler_chunk_size_slider],
outputs=[final_video_output] # Assumindo que o wrapper não é mais necessário
).then(
fn=lambda video_path: video_path, inputs=[final_video_output], outputs=[current_source_video_state]
)
run_hd_button.click(
fn=aduc.task_run_hd_mastering,
inputs=[current_source_video_state, hd_steps_slider, prompt_input],
outputs=[final_video_output]
).then(
fn=lambda video_path: video_path, inputs=[final_video_output], outputs=[current_source_video_state]
)
run_audio_button.click(
fn=aduc.task_run_audio_generation,
inputs=[current_source_video_state, audio_prompt_input, prompt_input],
outputs=[final_video_output]
)
# Conexão para atualizar o log completo
update_log_button.click(fn=get_log_content, inputs=[], outputs=[log_display_full])
# Atualiza o state holder com o DNA final quando a pré-produção termina
dna_display.change(fn=lambda data: data, inputs=dna_display, outputs=generation_state_holder)
# --- 5. INICIALIZAÇÃO DA APLICAÇÃO ---
if __name__ == "__main__":
if os.path.exists(WORKSPACE_DIR):
shutil.rmtree(WORKSPACE_DIR)
os.makedirs(WORKSPACE_DIR)
logger.info("Aplicação Gradio iniciada. Lançando interface...")
demo.queue().launch() |