Update deformes4D_engine.py
Browse files- deformes4D_engine.py +14 -38
deformes4D_engine.py
CHANGED
|
@@ -21,8 +21,7 @@ import gradio as gr
|
|
| 21 |
import subprocess
|
| 22 |
import gc
|
| 23 |
|
| 24 |
-
|
| 25 |
-
from audio_specialist import audio_specialist_singleton
|
| 26 |
from ltx_manager_helpers import ltx_manager_singleton
|
| 27 |
from gemini_helpers import gemini_singleton
|
| 28 |
from upscaler_specialist import upscaler_specialist_singleton
|
|
@@ -60,26 +59,10 @@ class Deformes4DEngine:
|
|
| 60 |
|
| 61 |
# --- MÉTODOS AUXILIARES ---
|
| 62 |
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
try:
|
| 68 |
-
subprocess.run(cmd, check=True, capture_output=True, text=True, encoding='utf-8')
|
| 69 |
-
logger.info(f"Áudio extraído com sucesso para {output_audio_path}")
|
| 70 |
-
return output_audio_path
|
| 71 |
-
except subprocess.CalledProcessError:
|
| 72 |
-
logger.warning(f"Não foi possível extrair o áudio de {os.path.basename(video_path)}. O vídeo pode ser silencioso.")
|
| 73 |
-
return None
|
| 74 |
-
|
| 75 |
-
def _combine_video_and_audio_ffmpeg(self, video_path: str, audio_path: str, output_path: str):
|
| 76 |
-
"""Combina um vídeo (sem som) com um arquivo de áudio."""
|
| 77 |
-
cmd = ['ffmpeg', '-y', '-i', video_path, '-i', audio_path, '-c:v', 'copy', '-c:a', 'aac', '-shortest', output_path]
|
| 78 |
-
try:
|
| 79 |
-
subprocess.run(cmd, check=True, capture_output=True, text=True, encoding='utf-8')
|
| 80 |
-
logger.info(f"Áudio e vídeo combinados com sucesso em {output_path}")
|
| 81 |
-
except subprocess.CalledProcessError as e:
|
| 82 |
-
raise gr.Error(f"Falha ao combinar áudio e vídeo: {e.stderr}")
|
| 83 |
|
| 84 |
@torch.no_grad()
|
| 85 |
def latents_to_pixels(self, latent_tensor: torch.Tensor, decode_timestep: float = 0.05) -> torch.Tensor:
|
|
@@ -98,11 +81,6 @@ class Deformes4DEngine:
|
|
| 98 |
tensor = (tensor * 2.0) - 1.0
|
| 99 |
return self.pixels_to_latents(tensor)
|
| 100 |
|
| 101 |
-
@torch.no_grad()
|
| 102 |
-
def pixels_to_latents(self, tensor: torch.Tensor) -> torch.Tensor:
|
| 103 |
-
tensor = tensor.to(self.device, dtype=self.vae.dtype)
|
| 104 |
-
return vae_encode(tensor, self.vae, vae_per_channel_normalize=True)
|
| 105 |
-
|
| 106 |
# --- NÚCLEO DA LÓGICA ADUC-SDR ---
|
| 107 |
def generate_full_movie(self, keyframes: list, global_prompt: str, storyboard: list,
|
| 108 |
seconds_per_fragment: float, trim_percent: int,
|
|
@@ -111,7 +89,7 @@ class Deformes4DEngine:
|
|
| 111 |
progress: gr.Progress = gr.Progress()):
|
| 112 |
|
| 113 |
num_transitions_to_generate = len(keyframes) - 1
|
| 114 |
-
TOTAL_STEPS = num_transitions_to_generate +
|
| 115 |
current_step = 0
|
| 116 |
|
| 117 |
FPS = 24
|
|
@@ -211,10 +189,11 @@ class Deformes4DEngine:
|
|
| 211 |
gc.collect()
|
| 212 |
torch.cuda.empty_cache()
|
| 213 |
|
| 214 |
-
# --- ATO
|
| 215 |
-
|
| 216 |
progress(current_step / TOTAL_STEPS, desc="Aprimoramento final (HD)...")
|
| 217 |
hq_silent_video_path = os.path.join(self.workspace_dir, f"{base_name}_hq_silent.mp4")
|
|
|
|
| 218 |
try:
|
| 219 |
hd_specialist_singleton.process_video(
|
| 220 |
input_video_path=refined_silent_video_path,
|
|
@@ -226,12 +205,12 @@ class Deformes4DEngine:
|
|
| 226 |
os.rename(refined_silent_video_path, hq_silent_video_path)
|
| 227 |
|
| 228 |
current_step += 1
|
| 229 |
-
progress(current_step / TOTAL_STEPS, desc="Finalizando
|
| 230 |
final_video_path = os.path.join(self.workspace_dir, f"{base_name}_FINAL.mp4")
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
logger.info(f"Processo concluído! Vídeo final salvo em: {
|
| 234 |
-
yield {"final_path":
|
| 235 |
|
| 236 |
def refine_latents(self, latents: torch.Tensor,
|
| 237 |
fps: int = 24,
|
|
@@ -240,7 +219,6 @@ class Deformes4DEngine:
|
|
| 240 |
motion_prompt: str = "refining video, improving details, cinematic quality") -> torch.Tensor:
|
| 241 |
"""
|
| 242 |
Aplica um passe de refinamento (denoise) em um tensor latente.
|
| 243 |
-
[CORRIGIDO] Calcula os frames de pixel de forma a alinhar com a lógica do VAE causal.
|
| 244 |
"""
|
| 245 |
logger.info(f"Refinando tensor latente com shape {latents.shape} para refinamento.")
|
| 246 |
|
|
@@ -251,8 +229,6 @@ class Deformes4DEngine:
|
|
| 251 |
|
| 252 |
pixel_height = latent_h * vae_scale_factor
|
| 253 |
pixel_width = latent_w * vae_scale_factor
|
| 254 |
-
|
| 255 |
-
# A fórmula inversa para o VAE causal: (N_latente - 1) * FatorDeEscala
|
| 256 |
pixel_frames = (num_latent_frames - 1) * video_scale_factor
|
| 257 |
|
| 258 |
refined_latents_tensor, _ = self.ltx_manager.refine_latents(
|
|
|
|
| 21 |
import subprocess
|
| 22 |
import gc
|
| 23 |
|
| 24 |
+
# Importações de especialistas, com o de áudio removido
|
|
|
|
| 25 |
from ltx_manager_helpers import ltx_manager_singleton
|
| 26 |
from gemini_helpers import gemini_singleton
|
| 27 |
from upscaler_specialist import upscaler_specialist_singleton
|
|
|
|
| 59 |
|
| 60 |
# --- MÉTODOS AUXILIARES ---
|
| 61 |
|
| 62 |
+
@torch.no_grad()
|
| 63 |
+
def pixels_to_latents(self, tensor: torch.Tensor) -> torch.Tensor:
|
| 64 |
+
tensor = tensor.to(self.device, dtype=self.vae.dtype)
|
| 65 |
+
return vae_encode(tensor, self.vae, vae_per_channel_normalize=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
@torch.no_grad()
|
| 68 |
def latents_to_pixels(self, latent_tensor: torch.Tensor, decode_timestep: float = 0.05) -> torch.Tensor:
|
|
|
|
| 81 |
tensor = (tensor * 2.0) - 1.0
|
| 82 |
return self.pixels_to_latents(tensor)
|
| 83 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
# --- NÚCLEO DA LÓGICA ADUC-SDR ---
|
| 85 |
def generate_full_movie(self, keyframes: list, global_prompt: str, storyboard: list,
|
| 86 |
seconds_per_fragment: float, trim_percent: int,
|
|
|
|
| 89 |
progress: gr.Progress = gr.Progress()):
|
| 90 |
|
| 91 |
num_transitions_to_generate = len(keyframes) - 1
|
| 92 |
+
TOTAL_STEPS = num_transitions_to_generate + 3 # Fragmentos + Renderização + HD
|
| 93 |
current_step = 0
|
| 94 |
|
| 95 |
FPS = 24
|
|
|
|
| 189 |
gc.collect()
|
| 190 |
torch.cuda.empty_cache()
|
| 191 |
|
| 192 |
+
# --- ATO III: MASTERIZAÇÃO FINAL (APENAS HD) ---
|
| 193 |
+
current_step += 1
|
| 194 |
progress(current_step / TOTAL_STEPS, desc="Aprimoramento final (HD)...")
|
| 195 |
hq_silent_video_path = os.path.join(self.workspace_dir, f"{base_name}_hq_silent.mp4")
|
| 196 |
+
|
| 197 |
try:
|
| 198 |
hd_specialist_singleton.process_video(
|
| 199 |
input_video_path=refined_silent_video_path,
|
|
|
|
| 205 |
os.rename(refined_silent_video_path, hq_silent_video_path)
|
| 206 |
|
| 207 |
current_step += 1
|
| 208 |
+
progress(current_step / TOTAL_STEPS, desc="Finalizando...")
|
| 209 |
final_video_path = os.path.join(self.workspace_dir, f"{base_name}_FINAL.mp4")
|
| 210 |
+
os.rename(hq_silent_video_path, final_video_path)
|
| 211 |
+
|
| 212 |
+
logger.info(f"Processo concluído! Vídeo final (silencioso) salvo em: {final_video_path}")
|
| 213 |
+
yield {"final_path": final_video_path}
|
| 214 |
|
| 215 |
def refine_latents(self, latents: torch.Tensor,
|
| 216 |
fps: int = 24,
|
|
|
|
| 219 |
motion_prompt: str = "refining video, improving details, cinematic quality") -> torch.Tensor:
|
| 220 |
"""
|
| 221 |
Aplica um passe de refinamento (denoise) em um tensor latente.
|
|
|
|
| 222 |
"""
|
| 223 |
logger.info(f"Refinando tensor latente com shape {latents.shape} para refinamento.")
|
| 224 |
|
|
|
|
| 229 |
|
| 230 |
pixel_height = latent_h * vae_scale_factor
|
| 231 |
pixel_width = latent_w * vae_scale_factor
|
|
|
|
|
|
|
| 232 |
pixel_frames = (num_latent_frames - 1) * video_scale_factor
|
| 233 |
|
| 234 |
refined_latents_tensor, _ = self.ltx_manager.refine_latents(
|