Spaces:
Paused
Paused
File size: 7,236 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 138 139 140 141 142 143 |
# aduc_framework/engineers/planner_5D.py
#
# Versão 1.1.0 (Diretor de Produção Alinhado)
# Copyright (C) August 4, 2025 Carlos Rodrigues dos Santos
#
# - Versão finalizada e alinhada com os especialistas Deformes v12+ e VaeManager v2.
# - Cria as Ordens de Serviço (Jobs) usando as definições mais recentes de `types.py`.
# - Delega os cálculos técnicos (ex: poda de frames) para os especialistas,
# focando-se na orquestração de alto nível e no gerenciamento do loop de feedback visual.
import logging
import os
from typing import Generator, Dict, Any
# Importa os especialistas que serão dirigidos
from ..engineers.deformes3D import deformes3d_engine_singleton as Deformes3D
from ..engineers.deformes4D import deformes4d_engine_singleton as Deformes4D
from ..tools.video_encode_tool import video_encode_tool_singleton as VideoTool
# Importa as estruturas de dados (o "DNA" e as "Ordens de Serviço")
from ..types import (
GenerationState,
KeyframeGenerationJob,
VideoGenerationJob,
KeyframeData,
VideoData
)
logger = logging.getLogger(__name__)
class Planner5D:
"""
Atua como o Diretor de Produção. Orquestra a geração de keyframes e vídeos
cena a cena, implementando um loop de feedback para garantir continuidade visual.
"""
def __init__(self):
self.dna: GenerationState | None = None
self.workspace: str | None = None
self.production_params: Dict[str, Any] = {}
self.pre_prod_params: Dict[str, Any] = {}
def produce_movie_by_scene(self, dna: GenerationState) -> Generator[GenerationState, None, None]:
"""
Ponto de entrada para a produção do filme. Executa o loop de produção cena a cena.
"""
self.dna = dna
self.workspace = self.dna.workspace_dir
if not (self.dna.parametros_geracao and self.dna.parametros_geracao.pre_producao and self.dna.parametros_geracao.producao):
raise ValueError("Parâmetros de pré-produção ou produção ausentes no DNA. O processo não pode continuar.")
self.pre_prod_params = self.dna.parametros_geracao.pre_producao.model_dump()
self.production_params = self.dna.parametros_geracao.producao.model_dump()
Deformes3D.initialize(self.workspace)
Deformes4D.initialize(self.workspace)
all_final_scene_clips = []
last_scene_final_frame_path = None
self.dna.chat_history.append({"role": "Planner5D", "content": "Ok, storyboard recebido. Iniciando a produção do filme, cena por cena..."})
yield self.dna
for scene_idx, scene in enumerate(self.dna.storyboard_producao):
scene_title = scene.titulo_cena or f"Cena {scene.id_cena}"
logger.info(f"--- PLANNER 5D: Iniciando Cena {scene.id_cena}: '{scene_title}' ---")
self.dna.chat_history.append({"role": "Planner5D", "content": f"Preparando para filmar a Cena {scene.id_cena}: '{scene_title}'..."})
yield self.dna
# ETAPA 1: GERAÇÃO DE KEYFRAMES
reference_paths = [ref.caminho for ref in self.dna.midias_referencia if ref.caminho]
ref_id_to_path_map = {i: path for i, path in enumerate(reference_paths)}
keyframe_job = KeyframeGenerationJob(
storyboard=[ato.NARRATIVA_VISUAL for ato in scene.atos],
global_prompt=self.dna.texto_global_historia or "",
ref_image_paths=reference_paths,
ref_id_to_path_map=ref_id_to_path_map,
available_ref_ids=list(ref_id_to_path_map.keys()),
keyframe_prefix=f"s{scene.id_cena:02d}",
params=self.pre_prod_params
)
generated_keyframes_data = Deformes3D.generate_keyframes_from_job(keyframe_job)
self.dna.storyboard_producao[scene_idx].keyframes = [KeyframeData(**kf) for kf in generated_keyframes_data]
self.dna.chat_history.append({"role": "Planner5D", "content": f"Cena {scene.id_cena}: {len(generated_keyframes_data)} keyframes criados."})
yield self.dna
for scene_idx, scene in enumerate(self.dna.storyboard_producao):
scene_title = scene.titulo_cena or f"Cena {scene.id_cena}"
logger.info(f"--- PLANNER 5D: Iniciando Gravação de Cena {scene.id_cena}: '{scene_title}' ---")
self.dna.chat_history.append({"role": "Planner5D", "content": f"Filmando a Cena {scene.id_cena}: '{scene_title}'..."})
yield self.dna
# ETAPA 2: GERAÇÃO DO VÍDEO
if len(generated_keyframes_data) < 1:
logger.warning(f"Cena {scene.id_cena} tem menos de 1 keyframes. Pulando geração de vídeo.")
self.dna.chat_history.append({"role": "Planner5D", "content": f"AVISO: Cena {scene.id_cena} não pôde ser filmada (keyframes insuficientes)."})
yield self.dna
continue
self.dna.chat_history.append({"role": "Planner5D", "content": f"Cena {scene.id_cena}: Luz, câmera, ação! Gerando o clipe de vídeo..."})
yield self.dna
# Criando a Ordem de Serviço para Deformes4D com os parâmetros de alto nível
video_job = VideoGenerationJob(
scene_id=scene.id_cena,
global_prompt=self.dna.texto_global_historia or "",
storyboard=[ato.NARRATIVA_VISUAL for ato in scene.atos],
keyframe_paths=[kf['caminho_pixel'] for kf in generated_keyframes_data],
**self.pre_prod_params,
**self.production_params
)
video_result = Deformes4D.generate_movie_clip_from_job(video_job)
scene_clip_path = video_result.get("final_path")
if scene_clip_path:
all_final_scene_clips.append(scene_clip_path)
video_data = video_result.get("video_data", {})
self.dna.storyboard_producao[scene_idx].video_gerado = VideoData(**video_data)
self.dna.caminho_filme_final_bruto = scene_clip_path
self.dna.chat_history.append({"role": "Planner5D", "content": f"Cena {scene.id_cena} filmada! O resultado será usado como ponto de partida para a próxima cena."})
yield self.dna
# ETAPA FINAL: MONTAGEM DO FILME
if not all_final_scene_clips:
self.dna.chat_history.append({"role": "Planner5D", "content": "Produção falhou. Nenhum clipe de vídeo foi gerado."})
yield self.dna
return
self.dna.chat_history.append({"role": "Planner5D", "content": "Todas as cenas foram filmadas. Iniciando a montagem final do filme..."})
yield self.dna
final_movie_path = os.path.join(self.workspace, "filme_final.mp4")
final_movie_path = VideoTool.concatenate_videos(all_final_scene_clips, final_movie_path, self.workspace)
self.dna.caminho_filme_final_bruto = final_movie_path
self.dna.chat_history.append({"role": "Maestro", "content": "Produção concluída! O filme final está pronto para ser assistido."})
yield self.dna
# --- Instância Singleton ---
planner_5d_singleton = Planner5D() |