File size: 9,475 Bytes
501fd32
 
 
 
7b07f9a
 
 
501fd32
 
 
 
 
 
 
77de316
501fd32
51363f0
99c6a62
 
501fd32
7b07f9a
ffc9fa5
7b07f9a
a1bea49
 
e45d488
a1bea49
 
 
 
 
 
 
 
ffc9fa5
7b07f9a
ffc9fa5
 
 
 
a1bea49
b410aef
a1bea49
7b07f9a
a1bea49
b410aef
a1bea49
52e5575
aff61f5
668caac
7b07f9a
 
 
33ed0b3
 
e45d488
 
7b07f9a
e45d488
7b07f9a
 
b410aef
 
7b07f9a
b410aef
 
 
 
 
 
 
 
aff61f5
 
b410aef
aff61f5
 
b410aef
 
 
aff61f5
b410aef
aff61f5
 
 
 
 
7b07f9a
aff61f5
 
7b07f9a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
aff61f5
7b07f9a
 
 
 
aff61f5
 
b410aef
33ed0b3
b410aef
99c6a62
77de316
aff61f5
77de316
ffc9fa5
77de316
 
7b07f9a
77de316
7b07f9a
aff61f5
7b07f9a
aff61f5
7b07f9a
aff61f5
 
7b07f9a
 
 
aff61f5
7b07f9a
aff61f5
 
52e5575
 
aff61f5
7b07f9a
aff61f5
52e5575
7b07f9a
aff61f5
52e5575
7b07f9a
aff61f5
 
 
7b07f9a
aff61f5
 
99c6a62
501fd32
7b07f9a
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
# 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("<h1>ADUC-SDR 🎬 - A Sala de Roteiristas de IA</h1>")
    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()