# app.py # # Copyright (C) August 4, 2025 Carlos Rodrigues dos Santos # # Versão 9.5.0 (Full Planner3D Architecture UI) # Esta versão implementa a UI completa para a nova arquitetura da Etapa 2, # com um chat e galeria dedicados, gerenciados pelo Planner3D. import gradio as gr import yaml import logging import os import sys import shutil import time # --- 1. IMPORTAÇÃO DO FRAMEWORK E CONFIGURAÇÃO --- import aduc_framework from aduc_framework.types import PreProductionParams, ProductionParams # ... (Configuração de Logging e Inicialização do Framework - sem alterações) ... 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__) 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) with gr.Blocks() as demo_error: gr.Markdown("# ERRO CRÍTICO NA INICIALIZAÇÃO") gr.Markdown("Não foi possível iniciar o Aduc Framework.") gr.Textbox(value=str(e), label="Detalhes do Erro", lines=10) demo_error.launch() exit() # --- 2. FUNÇÕES WRAPPER (UI <-> FRAMEWORK) --- def run_pre_production_wrapper(prompt, num_scenes, ref_files, resolution_str, duration_per_fragment, fast_mode): """Wrapper para a Etapa 1 (Pré-Produção - Roteiro).""" 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]) 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, fast_mode=fast_mode ) chatbot_display_history, fully_displayed_message_count, final_dna = [], 0, {} for update in aduc.task_pre_production(params): backend_chat_dna = update.get("chat_dna", []) dna_snapshot = update.get("dna_snapshot", gr.skip()) if update.get("status") == "complete": final_dna = update.get("dna", {}) while len(backend_chat_dna) > fully_displayed_message_count: new_message_obj = backend_chat_dna[fully_displayed_message_count] role = f"**{new_message_obj.get('role', 'Sistema')}**" content_to_type = new_message_obj.get('content', '') chatbot_display_history.append([role, ""]) full_typed_message = "" for char in content_to_type: full_typed_message += char chatbot_display_history[-1][1] = full_typed_message + "▌" yield { chat_history_chatbot: chatbot_display_history, dna_display: dna_snapshot } time.sleep(0.02) chatbot_display_history[-1][1] = full_typed_message yield { chat_history_chatbot: chatbot_display_history, dna_display: dna_snapshot } fully_displayed_message_count += 1 if "Llama, preciso da sua ajuda" in content_to_type: chatbot_display_history.append([f"**Llama (IA Criativa)**", "..."]) yield { chat_history_chatbot: chatbot_display_history, dna_display: dna_snapshot } time.sleep(1.5) chatbot_display_history.pop() yield { chat_history_chatbot: chatbot_display_history, dna_display: dna_snapshot } yield { chat_history_chatbot: chatbot_display_history, dna_display: final_dna, step2_accordion: gr.update(visible=True, open=True) } def run_keyframe_generation_wrapper(current_state_dict): """Wrapper para a Etapa 2. Consome os pacotes do Planner3D e dramatiza a UI.""" chatbot_display_history = [] fully_displayed_message_count = 0 final_dna = current_state_dict for update_package in aduc.task_generate_keyframes(current_state_dict): backend_chat_history = update_package.get("chat", []) gallery_paths = update_package.get("gallery", []) final_dna = update_package.get("dna", final_dna) while len(backend_chat_history) > fully_displayed_message_count: role, content_to_type = backend_chat_history[fully_displayed_message_count] chatbot_display_history.append([role, ""]) full_typed_message = "" for char in content_to_type: full_typed_message += char chatbot_display_history[-1][1] = full_typed_message + "▌" yield { keyframe_chat_chatbot: chatbot_display_history, keyframe_gallery: gr.update(value=gallery_paths), generation_state_holder: final_dna } time.sleep(0.02) chatbot_display_history[-1][1] = full_typed_message yield { keyframe_chat_chatbot: chatbot_display_history, keyframe_gallery: gr.update(value=gallery_paths), generation_state_holder: final_dna } fully_displayed_message_count += 1 if update_package.get("status") == "keyframes_complete": yield { keyframe_chat_chatbot: chatbot_display_history, keyframe_gallery: gr.update(value=gallery_paths), step3_accordion: gr.update(visible=True, open=True), generation_state_holder: final_dna } return # --- 3. DEFINIÇÃO DA UI --- with gr.Blocks(css="style.css") as demo: generation_state_holder = gr.State(value={}) gr.Markdown("

ADUC-SDR 🎬 - A Sala de Roteiristas de IA

") with gr.Accordion("Etapa 1: Planejamento do Roteiro", open=True): prompt_input = gr.Textbox(label="Ideia Geral do Filme", value="Um leão majestoso caminha pela savana e ruge para o sol poente.") with gr.Row(): resolution_selector = gr.Radio(["512x512", "768x768"], value="512x512", label="Resolução Base") num_scenes_slider = gr.Slider(minimum=2, maximum=5, value=3, step=1, label="Número de Cenas") duration_per_fragment_slider = gr.Slider(label="Duração de cada Ato (s)", minimum=2.0, maximum=10.0, value=5.0, step=0.1) ref_image_input = gr.File(label="Imagens de Referência", file_count="multiple", file_types=["image"]) fast_mode_checkbox = gr.Checkbox(label="Modo Rápido", value=False) start_planning_button = gr.Button("📝 Iniciar Planejamento (Etapa 1)", variant="primary") with gr.Accordion("🧠 Diário do Planejador de Roteiro (Ao Vivo)", open=False) as planning_log_accordion: with gr.Row(): chat_history_chatbot = gr.Chatbot(label="Conversa da Equipe de Roteiro", height=500, scale=1) dna_display = gr.JSON(label="DNA da Produção (em construção)", scale=1) with gr.Accordion("Etapa 2: Geração de Keyframes (Cenas-Chave)", open=False, visible=False) as step2_accordion: start_keyframe_button = gr.Button("🖼️ Gerar Keyframes (Etapa 2)", variant="primary") keyframe_chat_chatbot = gr.Chatbot(label="Conversa do Arquiteto Visual e Pintor", bubble_full_width=False, height=300) keyframe_gallery = gr.Gallery(label="Keyframes Gerados (em tempo real)", object_fit="contain", height="auto") with gr.Accordion("Etapa 3: Produção do Vídeo Original", open=False, visible=False) as step3_accordion: produce_original_button = gr.Button("🎬 Produzir Vídeo (Etapa 3)", variant="primary") with gr.Accordion("🎞️ Resultado Final", open=True): final_video_output = gr.Video(label="Filme Concluído", interactive=False) # --- 4. CONEXÕES DE EVENTOS --- start_planning_button.click( fn=lambda: gr.update(open=True), outputs=[planning_log_accordion] ).then( fn=run_pre_production_wrapper, inputs=[prompt_input, num_scenes_slider, ref_image_input, resolution_selector, duration_per_fragment_slider, fast_mode_checkbox], outputs=[chat_history_chatbot, dna_display, step2_accordion] ) dna_display.change(fn=lambda data: data, inputs=dna_display, outputs=generation_state_holder) start_keyframe_button.click( fn=run_keyframe_generation_wrapper, inputs=[generation_state_holder], outputs=[keyframe_chat_chatbot, keyframe_gallery, step3_accordion, 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()