Spaces:
Paused
Paused
| # 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.") |