Spaces:
Paused
Paused
File size: 6,414 Bytes
fb56537 |
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 |
# aduc_framework/aduc_sdr.py
#
# Versão 16.0.0 (Maestro de Produção Integrado)
# - Implementa o método `task_produce_movie` para delegar a produção de vídeo
# ao especialista `Planner5D`, ativando o pipeline de produção iterativo.
# - Atua como a ponte final entre a interface do usuário (UI) e o complexo
# fluxo de trabalho de geração de vídeo cena a cena.
# - Utiliza o sistema de `yield from` para transmitir de forma eficiente as
# atualizações de estado do `Planner5D` de volta para a UI.
import logging
import os
from typing import Generator
# Importa os especialistas de alto nível (Engenheiros)
from .engineers.composer_2D import composer_2d_singleton as Composer2D
from .engineers.planner_5D import planner_5d_singleton as Planner5D
# Importa as estruturas de dados (o DNA Digital)
from .types import GenerationState, PreProductionParams, ProductionParams, MediaRef
from .director import AducDirector
logger = logging.getLogger(__name__)
class AducSdr:
"""
O Maestro do framework ADUC-SDR. Orquestra os especialistas (Engineers)
e gerencia o fluxo de dados através do Diretor (estado persistente).
"""
def __init__(self, workspace_root: str):
self.workspace_root = workspace_root
self.director: AducDirector | None = None
self.composer_2d = Composer2D
self.planner_5d = Planner5D
logger.info("ADUC-SDR Maestro (Arquitetura V2) inicializado e pronto.")
def load_project(self, project_name: str):
"""Carrega um projeto existente ou cria um novo."""
project_path = os.path.join(self.workspace_root, project_name)
self.director = AducDirector(project_path=project_path)
logger.info(f"Projeto '{project_name}' carregado no Diretor.")
def _ensure_project_loaded(self):
"""Garante que um projeto foi carregado antes de executar tarefas."""
if not self.director:
raise RuntimeError("Nenhum projeto foi carregado. Chame `aduc.load_project(project_name)` primeiro.")
def get_current_state(self) -> GenerationState:
"""Retorna o estado completo e atual do projeto."""
self._ensure_project_loaded()
return self.director.get_full_state()
def process_image_for_story(self, image_path: str, filename: str) -> str:
"""Processa uma imagem de referência para um formato padrão."""
self._ensure_project_loaded()
from PIL import Image
size = 480; quality = 40
img = Image.open(image_path).convert("RGB"); img.thumbnail((size, size), Image.Resampling.LANCZOS)
background = Image.new('RGB', (size, size), (0, 0, 0)); img_w, img_h = img.size; offset = ((size - img_w) // 2, (size - img_h) // 2)
background.paste(img, offset)
processed_path = os.path.join(self.director.project_path, filename)
background.save(processed_path, 'JPEG', quality=quality)
return processed_path
def _process_and_yield_updates(self, generator: Generator[GenerationState, None, None]):
"""
Loop genérico para processar atualizações de um especialista, salvar o estado
e repassar para a UI.
"""
for updated_dna in generator:
self.director.load_state_from_dict(updated_dna.model_dump())
if self.director.state.should_checkpoint():
checkpoint_dir = os.path.join(self.director.project_path, "checkpoints")
path = self.director.state.create_checkpoint(checkpoint_dir)
logger.info(f"Checkpoint do projeto salvo em: {path}")
self.director.save_state()
yield self.director.get_full_state()
def task_run_story_and_keyframes(self, params: PreProductionParams) -> Generator[GenerationState, None, None]:
"""
Orquestra a pré-produção (Fase 1), delegando ao Composer2D para criar o storyboard.
"""
self._ensure_project_loaded()
logger.info("Maestro: Iniciando Pré-Produção (Storyboard) com o Composer2D...")
initial_state = self.director.get_full_state()
initial_state.parametros_geracao.pre_producao = params
initial_state.midias_referencia = [
MediaRef(id=i, tag=f"<IMG{i}>", caminho=path)
for i, path in enumerate(params.ref_paths)
]
initial_state.texto_global_historia = None
initial_state.ativos_catalogados = None
initial_state.storyboard_producao = []
initial_state.chat_history.append({
"role": "Sistema",
"content": f"Iniciando pré-produção. {len(params.ref_paths)} imagens de referência foram tageadas para uso pela IA."
})
pre_production_generator = self.composer_2d.compose_storyboard(initial_state)
yield from self._process_and_yield_updates(pre_production_generator)
logger.info("Maestro: Pré-Produção (Fase 1) concluída.")
def task_produce_movie(self, params: ProductionParams) -> Generator[GenerationState, None, None]:
"""
Orquestra a produção completa do filme (Fase 2), delegando ao Planner5D.
"""
self._ensure_project_loaded()
logger.info("Maestro: Iniciando Produção de Vídeo com o Planner5D...")
# 1. Obter o estado atual, que já contém o storyboard da pré-produção.
current_state = self.director.get_full_state()
# 2. Atualizar o estado com os novos parâmetros de produção vindos da UI.
if current_state.parametros_geracao:
current_state.parametros_geracao.producao = params
current_state.chat_history.append({
"role": "Sistema",
"content": f"Parâmetros de produção recebidos. O Diretor de Produção (Planner5D) está assumindo o controle."
})
# Salva os parâmetros no dna.json antes de iniciar o processo longo.
self.director.save_state()
# 3. Chamar o especialista Planner5D com o estado atualizado.
# Ele agora irá controlar o loop de Deformes3D e Deformes4D.
production_generator = self.planner_5d.produce_movie_by_scene(current_state)
# 4. Processar as atualizações, salvar o estado e repassar para a UI em tempo real.
yield from self._process_and_yield_updates(production_generator)
logger.info("Maestro: Produção de vídeo (Fase 2) concluída.") |