Update deformes4D_engine.py
Browse files- deformes4D_engine.py +27 -29
deformes4D_engine.py
CHANGED
|
@@ -119,40 +119,42 @@ class Deformes4DEngine:
|
|
| 119 |
return output_path
|
| 120 |
|
| 121 |
def generate_full_movie(self, keyframes: list, global_prompt: str, storyboard: list,
|
| 122 |
-
|
| 123 |
-
n_chunks_to_generate: int,
|
| 124 |
-
video_end_chunk: int,
|
| 125 |
-
eco_start_chunk: int,
|
| 126 |
-
handler_start_chunk: int,
|
| 127 |
-
handler_frame_target: int,
|
| 128 |
-
# Parâmetros restantes
|
| 129 |
handler_strength: float, destination_convergence_strength: float,
|
| 130 |
video_resolution: int, use_continuity_director: bool,
|
| 131 |
progress: gr.Progress = gr.Progress()):
|
| 132 |
|
| 133 |
-
# --- Lógica de
|
| 134 |
-
FRAMES_TO_GENERATE = (n_chunks_to_generate - 1) * 8 + 1
|
| 135 |
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
|
|
|
|
|
|
| 139 |
|
| 140 |
-
|
| 141 |
-
|
|
|
|
|
|
|
| 142 |
|
| 143 |
-
#
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
|
| 149 |
logger.info("="*60)
|
| 150 |
logger.info("MODO DE GERAÇÃO: Estratégia de Cauda Longa Dinâmica")
|
| 151 |
-
logger.info(f" -
|
| 152 |
-
logger.info(f" -
|
| 153 |
-
logger.info(f" -
|
| 154 |
-
logger.info(f" - Guia de
|
| 155 |
-
logger.info(f" -
|
|
|
|
| 156 |
logger.info("="*60)
|
| 157 |
|
| 158 |
base_ltx_params = {"guidance_scale": 1.0, "stg_scale": 0.0, "rescaling_scale": 0.15, "num_inference_steps": 20}
|
|
@@ -192,16 +194,12 @@ class Deformes4DEngine:
|
|
| 192 |
if i == 0:
|
| 193 |
img_start = self._preprocess_image_for_latent_conversion(Image.open(start_keyframe_path).convert("RGB"), target_resolution_tuple)
|
| 194 |
conditioning_items.append(LatentConditioningItem(self.pil_to_latent(img_start), 0, 1.0))
|
| 195 |
-
logger.info(" - Condicionamento inicial: Imagem K1 no frame 0.")
|
| 196 |
else:
|
| 197 |
conditioning_items.append(LatentConditioningItem(eco_latent_for_next_loop, 0, 1.0))
|
| 198 |
conditioning_items.append(LatentConditioningItem(handler_latent_for_next_loop, HANDLER_FRAME_TARGET, handler_strength))
|
| 199 |
-
logger.info(f" - Guia de Memória (Eco) aplicada no frame 0 (shape: {eco_latent_for_next_loop.shape}).")
|
| 200 |
-
logger.info(f" - Guia de Evolução (Handler) aplicada no frame {HANDLER_FRAME_TARGET} (shape: {handler_latent_for_next_loop.shape}).")
|
| 201 |
|
| 202 |
img_dest = self._preprocess_image_for_latent_conversion(Image.open(destination_keyframe_path).convert("RGB"), target_resolution_tuple)
|
| 203 |
conditioning_items.append(LatentConditioningItem(self.pil_to_latent(img_dest), DESTINATION_FRAME_TARGET, destination_convergence_strength))
|
| 204 |
-
logger.info(f" - Guia de Destino: Imagem K{start_keyframe_index + 1} no frame {DESTINATION_FRAME_TARGET}.")
|
| 205 |
|
| 206 |
current_ltx_params = {**base_ltx_params, "motion_prompt": motion_prompt}
|
| 207 |
new_full_latents = self._generate_latent_tensor_internal(conditioning_items, current_ltx_params, target_resolution_tuple, FRAMES_TO_GENERATE)
|
|
@@ -211,7 +209,7 @@ class Deformes4DEngine:
|
|
| 211 |
handler_latent_for_next_loop = new_full_latents[:, :, HANDLER_CHUNK_INDICES, :, :].clone()
|
| 212 |
logger.info(f" [GUIAS] Guias para a próxima iteração extraídas. Eco shape: {eco_latent_for_next_loop.shape}, Handler shape: {handler_latent_for_next_loop.shape}.")
|
| 213 |
|
| 214 |
-
latents_for_video = new_full_latents[:, :,
|
| 215 |
logger.info(f" [2. EDIÇÃO] Tensor final para vídeo extraído com {latents_for_video.shape[2]} chunks.")
|
| 216 |
|
| 217 |
base_name = f"fragment_{i}_{int(time.time())}"
|
|
|
|
| 119 |
return output_path
|
| 120 |
|
| 121 |
def generate_full_movie(self, keyframes: list, global_prompt: str, storyboard: list,
|
| 122 |
+
seconds_per_fragment: float, trim_percent: int,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
handler_strength: float, destination_convergence_strength: float,
|
| 124 |
video_resolution: int, use_continuity_director: bool,
|
| 125 |
progress: gr.Progress = gr.Progress()):
|
| 126 |
|
| 127 |
+
# --- Lógica de Controle Dinâmico Baseada em Dois Sliders ---
|
|
|
|
| 128 |
|
| 129 |
+
# 1. Calcular o total de chunks a serem gerados a partir dos segundos
|
| 130 |
+
total_chunks_gerados = max(5, int(round(seconds_per_fragment * 24 / 8)))
|
| 131 |
+
|
| 132 |
+
# 2. Calcular o número de chunks a podar com base na porcentagem, com mínimo de 4
|
| 133 |
+
trim_chunks = max(4, int(round(total_chunks_gerados * (trim_percent / 100))))
|
| 134 |
|
| 135 |
+
# Regra de segurança para evitar que a poda consuma o vídeo inteiro
|
| 136 |
+
if trim_chunks >= total_chunks_gerados:
|
| 137 |
+
trim_chunks = total_chunks_gerados - 1
|
| 138 |
+
logger.warning(f"A poda ({trim_percent}%) era muito grande. Ajustada para {trim_chunks} chunks para deixar 1 chunk de vídeo.")
|
| 139 |
|
| 140 |
+
# 3. Definir fatias e alvos com base nos cálculos
|
| 141 |
+
VIDEO_CHUNK_COUNT = total_chunks_gerados - trim_chunks
|
| 142 |
+
|
| 143 |
+
HANDLER_CHUNK_INDICES = slice(total_chunks_gerados - 2, total_chunks_gerados)
|
| 144 |
+
ECO_CHUNK_INDICES = slice(total_chunks_gerados - 4, total_chunks_gerados - 2)
|
| 145 |
+
|
| 146 |
+
HANDLER_FRAME_TARGET = (trim_chunks - 2) * 8
|
| 147 |
+
FRAMES_TO_GENERATE = (total_chunks_gerados - 1) * 8 + 1
|
| 148 |
+
DESTINATION_FRAME_TARGET = FRAMES_TO_GENERATE - 1
|
| 149 |
|
| 150 |
logger.info("="*60)
|
| 151 |
logger.info("MODO DE GERAÇÃO: Estratégia de Cauda Longa Dinâmica")
|
| 152 |
+
logger.info(f" - Duração Solicitada: {seconds_per_fragment}s -> Geração Bruta: {total_chunks_gerados} chunks")
|
| 153 |
+
logger.info(f" - Poda Solicitada: {trim_percent}% -> Chunks de Poda (Cauda): {trim_chunks}")
|
| 154 |
+
logger.info(f" - Clipe Final por Fragmento: {VIDEO_CHUNK_COUNT} chunks")
|
| 155 |
+
logger.info(f" - Guia de Eco (Memória): Chunks {ECO_CHUNK_INDICES.start}-{ECO_CHUNK_INDICES.stop-1}")
|
| 156 |
+
logger.info(f" - Guia de Handler (Evolução): Chunks {HANDLER_CHUNK_INDICES.start}-{HANDLER_CHUNK_INDICES.stop-1}")
|
| 157 |
+
logger.info(f" - PONTO DE APLICAÇÃO DO HANDLER (DINÂMICO): Frame {HANDLER_FRAME_TARGET}")
|
| 158 |
logger.info("="*60)
|
| 159 |
|
| 160 |
base_ltx_params = {"guidance_scale": 1.0, "stg_scale": 0.0, "rescaling_scale": 0.15, "num_inference_steps": 20}
|
|
|
|
| 194 |
if i == 0:
|
| 195 |
img_start = self._preprocess_image_for_latent_conversion(Image.open(start_keyframe_path).convert("RGB"), target_resolution_tuple)
|
| 196 |
conditioning_items.append(LatentConditioningItem(self.pil_to_latent(img_start), 0, 1.0))
|
|
|
|
| 197 |
else:
|
| 198 |
conditioning_items.append(LatentConditioningItem(eco_latent_for_next_loop, 0, 1.0))
|
| 199 |
conditioning_items.append(LatentConditioningItem(handler_latent_for_next_loop, HANDLER_FRAME_TARGET, handler_strength))
|
|
|
|
|
|
|
| 200 |
|
| 201 |
img_dest = self._preprocess_image_for_latent_conversion(Image.open(destination_keyframe_path).convert("RGB"), target_resolution_tuple)
|
| 202 |
conditioning_items.append(LatentConditioningItem(self.pil_to_latent(img_dest), DESTINATION_FRAME_TARGET, destination_convergence_strength))
|
|
|
|
| 203 |
|
| 204 |
current_ltx_params = {**base_ltx_params, "motion_prompt": motion_prompt}
|
| 205 |
new_full_latents = self._generate_latent_tensor_internal(conditioning_items, current_ltx_params, target_resolution_tuple, FRAMES_TO_GENERATE)
|
|
|
|
| 209 |
handler_latent_for_next_loop = new_full_latents[:, :, HANDLER_CHUNK_INDICES, :, :].clone()
|
| 210 |
logger.info(f" [GUIAS] Guias para a próxima iteração extraídas. Eco shape: {eco_latent_for_next_loop.shape}, Handler shape: {handler_latent_for_next_loop.shape}.")
|
| 211 |
|
| 212 |
+
latents_for_video = new_full_latents[:, :, :VIDEO_CHUNK_COUNT, :, :]
|
| 213 |
logger.info(f" [2. EDIÇÃO] Tensor final para vídeo extraído com {latents_for_video.shape[2]} chunks.")
|
| 214 |
|
| 215 |
base_name = f"fragment_{i}_{int(time.time())}"
|