Update api/ltx_server_refactored.py
Browse files- api/ltx_server_refactored.py +111 -110
api/ltx_server_refactored.py
CHANGED
|
@@ -452,128 +452,129 @@ class VideoService:
|
|
| 452 |
return final_video_path, final_latents_path, used_seed
|
| 453 |
|
| 454 |
|
| 455 |
-
# Em ltx_server_refactored.py, dentro da classe VideoService
|
| 456 |
-
|
| 457 |
-
def apply_secondary_refinement(
|
| 458 |
-
self,
|
| 459 |
-
latents_path: str,
|
| 460 |
-
prompt: str,
|
| 461 |
-
negative_prompt: str,
|
| 462 |
-
guidance_scale: float,
|
| 463 |
-
seed: int,
|
| 464 |
-
num_decode_chunks_per_worker: int = 2
|
| 465 |
-
) -> Tuple[str, str]:
|
| 466 |
-
"""
|
| 467 |
-
Orquestra o pipeline de Pós-Produção: Upscale, Denoise em Chunks, e Costura final.
|
| 468 |
-
Gerencia o estado da GPU explicitamente para cada etapa.
|
| 469 |
-
"""
|
| 470 |
-
print("\n======================================================================")
|
| 471 |
-
print("====== [INFO] Iniciando Pós-Produção: Refinamento em Chunks e Costura Final ======")
|
| 472 |
-
print("======================================================================\n")
|
| 473 |
-
|
| 474 |
-
temp_dir_orchestrator = tempfile.mkdtemp(prefix="refine_orchestrator_")
|
| 475 |
-
self._register_tmp_dir(temp_dir_orchestrator)
|
| 476 |
-
|
| 477 |
-
# --- ETAPA 1: Upscale Espacial do Tensor Completo ---
|
| 478 |
-
print("[LOG] Etapa 1: Aplicando Upscale Espacial nos latentes de baixa resolução...")
|
| 479 |
|
| 480 |
-
|
| 481 |
-
|
| 482 |
-
|
| 483 |
-
|
| 484 |
-
|
| 485 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 486 |
|
| 487 |
-
|
| 488 |
-
|
| 489 |
-
self.pipeline.vae.to(self.device)
|
| 490 |
-
print(" [VRAM Manager] VAE movido para a GPU para a etapa de Upscale.")
|
| 491 |
-
if self.latent_upsampler and not next(self.latent_upsampler.parameters()).is_cuda:
|
| 492 |
-
self.latent_upsampler.to(self.device)
|
| 493 |
-
torch.cuda.empty_cache()
|
| 494 |
-
# --- Fim do Gerenciamento de VRAM ---
|
| 495 |
|
| 496 |
-
|
| 497 |
-
|
| 498 |
-
|
| 499 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 500 |
|
| 501 |
-
|
| 502 |
-
|
| 503 |
-
|
| 504 |
-
|
| 505 |
-
|
| 506 |
-
|
| 507 |
-
|
| 508 |
-
|
| 509 |
-
|
| 510 |
-
|
| 511 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 512 |
|
| 513 |
-
|
| 514 |
-
|
|
|
|
|
|
|
|
|
|
| 515 |
|
| 516 |
-
|
| 517 |
-
|
| 518 |
-
|
| 519 |
-
|
| 520 |
-
|
| 521 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 522 |
|
| 523 |
-
|
| 524 |
-
|
| 525 |
-
|
| 526 |
-
|
| 527 |
-
|
| 528 |
-
|
| 529 |
-
|
| 530 |
-
chunk_seed = seed + i + 1
|
| 531 |
-
|
| 532 |
-
# A chamada a `refine_texture_only` internamente chamará `_set_generation_environment`,
|
| 533 |
-
# trazendo o Transformer de volta para a GPU e (se otimizado) movendo o VAE para a CPU.
|
| 534 |
-
pixel_chunk, refined_latent_chunk = self.refine_texture_only(
|
| 535 |
-
latents_path=chunk_path,
|
| 536 |
-
prompt=prompt, negative_prompt=negative_prompt,
|
| 537 |
-
guidance_scale=guidance_scale, seed=chunk_seed,
|
| 538 |
-
num_decode_chunks=num_decode_chunks_per_worker
|
| 539 |
)
|
| 540 |
-
pixel_chunks_list.append(pixel_chunk)
|
| 541 |
-
refined_latent_chunks_list.append(refined_latent_chunk)
|
| 542 |
-
print(f" --> Tensores do Chunk {i+1} recebidos.")
|
| 543 |
-
|
| 544 |
-
# --- ETAPA 3: Costurar os Tensores (Pixels e Latentes) ---
|
| 545 |
-
print("\n[LOG] Etapa 3: Costurando os tensores de pixels e latentes...")
|
| 546 |
|
| 547 |
-
|
| 548 |
-
|
| 549 |
-
|
| 550 |
-
|
| 551 |
-
|
| 552 |
-
|
| 553 |
-
final_latents_hd = self._stitch_chunks(
|
| 554 |
-
chunks_list=refined_latent_chunks_list, num_divisoes=num_divisoes,
|
| 555 |
-
total_original_items=total_latents, sobreposicao_items=sobreposicao,
|
| 556 |
-
item_multiplier=1, domain_name="Latentes (Final)"
|
| 557 |
-
)
|
| 558 |
-
|
| 559 |
-
# --- ETAPA 4: Salvar os Artefatos Finais ---
|
| 560 |
-
print("\n[LOG] Etapa 4: Salvando o vídeo MP4 e o tensor de latentes finais...")
|
| 561 |
|
| 562 |
-
|
| 563 |
-
|
| 564 |
-
|
| 565 |
-
|
| 566 |
-
|
| 567 |
-
|
| 568 |
-
|
| 569 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 570 |
|
| 571 |
-
# Limpeza final
|
| 572 |
-
self._finalize()
|
| 573 |
|
| 574 |
-
|
| 575 |
-
return final_video_path, final_latents_path
|
| 576 |
-
|
| 577 |
def apply_secondary_refinement2(
|
| 578 |
self,
|
| 579 |
latents_path: str,
|
|
|
|
| 452 |
return final_video_path, final_latents_path, used_seed
|
| 453 |
|
| 454 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 455 |
|
| 456 |
+
def apply_secondary_refinement(
|
| 457 |
+
self,
|
| 458 |
+
latents_path: str,
|
| 459 |
+
prompt: str,
|
| 460 |
+
negative_prompt: str,
|
| 461 |
+
guidance_scale: float,
|
| 462 |
+
seed: int,
|
| 463 |
+
num_decode_chunks_per_worker: int = 2
|
| 464 |
+
) -> Tuple[str, str]:
|
| 465 |
+
"""
|
| 466 |
+
Orquestra o pipeline de Pós-Produção: Upscale, Denoise em Chunks, e Costura final.
|
| 467 |
+
Gerencia o estado da GPU explicitamente para cada etapa.
|
| 468 |
+
"""
|
| 469 |
+
print("\n======================================================================")
|
| 470 |
+
print("====== [INFO] Iniciando Pós-Produção: Refinamento em Chunks e Costura Final ======")
|
| 471 |
+
print("======================================================================\n")
|
| 472 |
|
| 473 |
+
temp_dir_orchestrator = tempfile.mkdtemp(prefix="refine_orchestrator_")
|
| 474 |
+
self._register_tmp_dir(temp_dir_orchestrator)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 475 |
|
| 476 |
+
# --- ETAPA 1: Upscale Espacial do Tensor Completo ---
|
| 477 |
+
print("[LOG] Etapa 1: Aplicando Upscale Espacial nos latentes de baixa resolução...")
|
| 478 |
+
|
| 479 |
+
# --- Gerenciamento de VRAM para a Etapa de Upscale ---
|
| 480 |
+
# Descarrega o Transformer (se a otimização estiver ativa) para dar espaço.
|
| 481 |
+
if ENABLE_MEMORY_OPTIMIZATION:
|
| 482 |
+
if next(self.pipeline.transformer.parameters()).is_cuda:
|
| 483 |
+
self.pipeline.transformer.to('cpu')
|
| 484 |
+
print(" [VRAM Manager] Transformer movido para a CPU para a etapa de Upscale.")
|
| 485 |
+
|
| 486 |
+
# Garante que os modelos necessários para o upscale (VAE e Upsampler) estejam na GPU.
|
| 487 |
+
if not next(self.pipeline.vae.parameters()).is_cuda:
|
| 488 |
+
self.pipeline.vae.to(self.device)
|
| 489 |
+
print(" [VRAM Manager] VAE movido para a GPU para a etapa de Upscale.")
|
| 490 |
+
if self.latent_upsampler and not next(self.latent_upsampler.parameters()).is_cuda:
|
| 491 |
+
self.latent_upsampler.to(self.device)
|
| 492 |
+
torch.cuda.empty_cache()
|
| 493 |
+
# --- Fim do Gerenciamento de VRAM ---
|
| 494 |
+
|
| 495 |
+
low_res_latents = torch.load(latents_path)
|
| 496 |
+
with torch.no_grad(), torch.autocast(device_type=self.device.split(':')[0], dtype=self.runtime_autocast_dtype, enabled=(self.device == 'cuda')):
|
| 497 |
+
# Agora o VAE e o latents estarão ambos na GPU
|
| 498 |
+
latents_hd_upscaled = self._upsample_and_filter_latents(low_res_latents.to(self.device))
|
| 499 |
+
|
| 500 |
+
latents_hd_upscaled_cpu = latents_hd_upscaled.cpu()
|
| 501 |
+
print(f" [LOG] Upscale concluído. Novo shape de latents HD: {latents_hd_upscaled_cpu.shape}")
|
| 502 |
+
del latents_hd_upscaled, low_res_latents
|
| 503 |
+
torch.cuda.empty_cache()
|
| 504 |
|
| 505 |
+
# --- ETAPA 2: Fragmentar, Processar em Chunks e Coletar Tensores ---
|
| 506 |
+
print("\n[LOG] Etapa 2: Fragmentando e processando cada chunk para obter tensores de pixels e latentes...")
|
| 507 |
+
total_latents = latents_hd_upscaled_cpu.shape[2]
|
| 508 |
+
sobreposicao = 2
|
| 509 |
+
num_divisoes = 3
|
| 510 |
+
tamanho_base = (total_latents - 1) // num_divisoes
|
| 511 |
+
|
| 512 |
+
if tamanho_base < sobreposicao:
|
| 513 |
+
raise ValueError("Latentes muito curtos para dividir em 3. Use o refinamento direto ou reduza o número de chunks.")
|
| 514 |
+
|
| 515 |
+
pontos_de_corte = [
|
| 516 |
+
(0, tamanho_base + sobreposicao),
|
| 517 |
+
(tamanho_base - sobreposicao, (2 * tamanho_base) + sobreposicao),
|
| 518 |
+
((2 * tamanho_base) - sobreposicao, total_latents)
|
| 519 |
+
]
|
| 520 |
+
hd_chunks_to_process = [latents_hd_upscaled_cpu[:, :, s:e, :, :] for s, e in pontos_de_corte]
|
| 521 |
+
|
| 522 |
+
pixel_chunks_list = []
|
| 523 |
+
refined_latent_chunks_list = []
|
| 524 |
|
| 525 |
+
for i, chunk in enumerate(hd_chunks_to_process):
|
| 526 |
+
print(f"\n --> Processando o Chunk {i+1}/{len(hd_chunks_to_process)}...")
|
| 527 |
+
chunk_path = os.path.join(temp_dir_orchestrator, f"hd_chunk_to_process_{i}.pt")
|
| 528 |
+
torch.save(chunk, chunk_path)
|
| 529 |
+
chunk_seed = seed + i + 1
|
| 530 |
|
| 531 |
+
# A chamada a `refine_texture_only` internamente chamará `_set_generation_environment`,
|
| 532 |
+
# trazendo o Transformer de volta para a GPU e (se otimizado) movendo o VAE para a CPU.
|
| 533 |
+
pixel_chunk, refined_latent_chunk = self.refine_texture_only(
|
| 534 |
+
latents_path=chunk_path,
|
| 535 |
+
prompt=prompt, negative_prompt=negative_prompt,
|
| 536 |
+
guidance_scale=guidance_scale, seed=chunk_seed,
|
| 537 |
+
num_decode_chunks=num_decode_chunks_per_worker
|
| 538 |
+
)
|
| 539 |
+
pixel_chunks_list.append(pixel_chunk)
|
| 540 |
+
refined_latent_chunks_list.append(refined_latent_chunk)
|
| 541 |
+
print(f" --> Tensores do Chunk {i+1} recebidos.")
|
| 542 |
|
| 543 |
+
# --- ETAPA 3: Costurar os Tensores (Pixels e Latentes) ---
|
| 544 |
+
print("\n[LOG] Etapa 3: Costurando os tensores de pixels e latentes...")
|
| 545 |
+
|
| 546 |
+
final_pixel_tensor = self._stitch_chunks(
|
| 547 |
+
chunks_list=pixel_chunks_list, num_divisoes=num_divisoes,
|
| 548 |
+
total_original_items=total_latents, sobreposicao_items=sobreposicao,
|
| 549 |
+
item_multiplier=8, domain_name="Pixels (Final)"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 550 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 551 |
|
| 552 |
+
final_latents_hd = self._stitch_chunks(
|
| 553 |
+
chunks_list=refined_latent_chunks_list, num_divisoes=num_divisoes,
|
| 554 |
+
total_original_items=total_latents, sobreposicao_items=sobreposicao,
|
| 555 |
+
item_multiplier=1, domain_name="Latentes (Final)"
|
| 556 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 557 |
|
| 558 |
+
# --- ETAPA 4: Salvar os Artefatos Finais ---
|
| 559 |
+
print("\n[LOG] Etapa 4: Salvando o vídeo MP4 e o tensor de latentes finais...")
|
| 560 |
+
|
| 561 |
+
final_video_path = self._save_video_from_tensor(
|
| 562 |
+
final_pixel_tensor, f"final_progressive_stitched_{seed}",
|
| 563 |
+
seed, temp_dir_orchestrator
|
| 564 |
+
)
|
| 565 |
+
final_latents_path = self._save_latents_to_disk(
|
| 566 |
+
final_latents_hd, f"final_hd_stitched_{seed}",
|
| 567 |
+
seed
|
| 568 |
+
)
|
| 569 |
+
|
| 570 |
+
# Limpeza final
|
| 571 |
+
self._finalize()
|
| 572 |
+
|
| 573 |
+
print(f"\n[SUCCESS] Pós-Produção completa! Vídeo final: {final_video_path}")
|
| 574 |
+
return final_video_path, final_latents_path
|
| 575 |
|
|
|
|
|
|
|
| 576 |
|
| 577 |
+
|
|
|
|
|
|
|
| 578 |
def apply_secondary_refinement2(
|
| 579 |
self,
|
| 580 |
latents_path: str,
|