Update api/ltx_server_refactored.py
Browse files- api/ltx_server_refactored.py +121 -7
api/ltx_server_refactored.py
CHANGED
|
@@ -554,7 +554,7 @@ class VideoService:
|
|
| 554 |
|
| 555 |
self._finalize()
|
| 556 |
|
| 557 |
-
final_video_path, final_latents_path = self.refine_texture_only(
|
| 558 |
latents_path=tensor_path,
|
| 559 |
prompt=prompt,
|
| 560 |
negative_prompt=negative_prompt,
|
|
@@ -570,10 +570,123 @@ class VideoService:
|
|
| 570 |
return final_video_path, final_latents_path, used_seed
|
| 571 |
|
| 572 |
|
| 573 |
-
|
| 574 |
-
|
| 575 |
-
|
| 576 |
def apply_secondary_refinement(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 577 |
self,
|
| 578 |
latents_path: str,
|
| 579 |
prompt: str,
|
|
@@ -707,18 +820,19 @@ class VideoService:
|
|
| 707 |
|
| 708 |
video_path_out = self._save_video_from_tensor(pixel_tensor, "refined_video_final", used_seed, temp_dir)
|
| 709 |
latents_path_out = self._save_latents_to_disk(final_latents_cpu, "latents_refined_final", used_seed)
|
| 710 |
-
|
|
|
|
| 711 |
print(" [LOG] Tarefa concluída. Restaurando ambiente de GERAÇÃO na GPU para a próxima execução...")
|
| 712 |
self._set_generation_environment()
|
| 713 |
|
| 714 |
print(" [LOG] Liberando tensores finais da memória da CPU.")
|
| 715 |
-
del
|
| 716 |
self._finalize()
|
| 717 |
|
| 718 |
print("\n======================================================================")
|
| 719 |
print("============ [SUCCESS] ETAPA 2 Concluída com Sucesso =============")
|
| 720 |
print("======================================================================\n")
|
| 721 |
-
return video_path_out, latents_path_out
|
| 722 |
|
| 723 |
|
| 724 |
|
|
|
|
| 554 |
|
| 555 |
self._finalize()
|
| 556 |
|
| 557 |
+
final_video_path, final_latents_path, _ = self.refine_texture_only(
|
| 558 |
latents_path=tensor_path,
|
| 559 |
prompt=prompt,
|
| 560 |
negative_prompt=negative_prompt,
|
|
|
|
| 570 |
return final_video_path, final_latents_path, used_seed
|
| 571 |
|
| 572 |
|
| 573 |
+
|
|
|
|
|
|
|
| 574 |
def apply_secondary_refinement(
|
| 575 |
+
self,
|
| 576 |
+
low_res_latents_path: str,
|
| 577 |
+
prompt: str,
|
| 578 |
+
negative_prompt: str,
|
| 579 |
+
guidance_scale: float,
|
| 580 |
+
seed: int
|
| 581 |
+
) -> Tuple[str, str]:
|
| 582 |
+
"""
|
| 583 |
+
Orquestra o pipeline de Pós-Produção de forma elegante:
|
| 584 |
+
1. Upscale dos latentes de baixa resolução.
|
| 585 |
+
2. Processa cada chunk usando `refine_texture_only`, coletando os TENSORES DE PIXELS.
|
| 586 |
+
3. Costura os tensores de pixels na memória e salva o MP4 final.
|
| 587 |
+
"""
|
| 588 |
+
print("\n======================================================================")
|
| 589 |
+
print("====== [INFO] Iniciando Pós-Produção: Costura de Tensores de Pixels ======")
|
| 590 |
+
print("======================================================================\n")
|
| 591 |
+
|
| 592 |
+
temp_dir_orchestrator = tempfile.mkdtemp(prefix="refine_orchestrator_")
|
| 593 |
+
self._register_tmp_dir(temp_dir_orchestrator)
|
| 594 |
+
|
| 595 |
+
# --- ETAPA 1: Upscale Espacial do Tensor Completo ---
|
| 596 |
+
print("[LOG] Etapa 1: Aplicando Upscale Espacial nos latentes de baixa resolução...")
|
| 597 |
+
self._set_generation_environment()
|
| 598 |
+
|
| 599 |
+
low_res_latents = torch.load(low_res_latents_path)
|
| 600 |
+
with torch.no_grad(), torch.autocast(device_type=self.device.split(':')[0], dtype=self.runtime_autocast_dtype, enabled=(self.device == 'cuda')):
|
| 601 |
+
latents_hd_upscaled = self._upsample_and_filter_latents(low_res_latents.to(self.device))
|
| 602 |
+
|
| 603 |
+
latents_hd_upscaled_cpu = latents_hd_upscaled.cpu()
|
| 604 |
+
print(f" [LOG] Upscale concluído. Novo shape de latentes HD: {latents_hd_upscaled_cpu.shape}")
|
| 605 |
+
del latents_hd_upscaled, low_res_latents
|
| 606 |
+
torch.cuda.empty_cache()
|
| 607 |
+
|
| 608 |
+
# --- ETAPA 2: Fragmentar e Processar cada Chunk para Obter Tensores de Pixels ---
|
| 609 |
+
print("\n[LOG] Etapa 2: Fragmentando e processando cada chunk para obter tensores de pixels...")
|
| 610 |
+
total_latents = latents_hd_upscaled_cpu.shape[2]
|
| 611 |
+
sobreposicao = 2
|
| 612 |
+
num_divisoes = 3
|
| 613 |
+
tamanho_base = (total_latents - 1) // num_divisoes
|
| 614 |
+
|
| 615 |
+
pontos_de_corte = [
|
| 616 |
+
(0, tamanho_base + sobreposicao),
|
| 617 |
+
(tamanho_base - sobreposicao, (2 * tamanho_base) + sobreposicao),
|
| 618 |
+
((2 * tamanho_base) - sobreposicao, total_latents)
|
| 619 |
+
]
|
| 620 |
+
hd_chunks_to_process = [latents_hd_upscaled_cpu[:, :, s:e, :, :] for s, e in pontos_de_corte]
|
| 621 |
+
|
| 622 |
+
pixel_chunks_list = []
|
| 623 |
+
# Também coletaremos os latentes refinados de cada chunk para a costura final de latentes
|
| 624 |
+
refined_latent_chunk_paths = []
|
| 625 |
+
|
| 626 |
+
for i, chunk in enumerate(hd_chunks_to_process):
|
| 627 |
+
print(f"\n --> Processando para Pixels o Chunk {i+1}/{len(hd_chunks_to_process)}...")
|
| 628 |
+
chunk_path = os.path.join(temp_dir_orchestrator, f"hd_chunk_to_process_{i}.pt")
|
| 629 |
+
torch.save(chunk, chunk_path)
|
| 630 |
+
chunk_seed = seed + i + 1
|
| 631 |
+
|
| 632 |
+
# Chamamos a função worker e pegamos todos os seus retornos
|
| 633 |
+
_, refined_latent_path, pixel_chunk = self.refine_texture_only(
|
| 634 |
+
latents_path=chunk_path,
|
| 635 |
+
prompt=prompt, negative_prompt=negative_prompt,
|
| 636 |
+
guidance_scale=guidance_scale, seed=chunk_seed
|
| 637 |
+
)
|
| 638 |
+
pixel_chunks_list.append(pixel_chunk)
|
| 639 |
+
refined_latent_chunk_paths.append(refined_latent_path)
|
| 640 |
+
print(f" --> Tensor de pixels do Chunk {i+1} recebido. Shape: {pixel_chunk.shape}")
|
| 641 |
+
|
| 642 |
+
# --- ETAPA 3: Costurar os Tensores de Pixels ---
|
| 643 |
+
print("\n[LOG] Etapa 3: Costurando os tensores de pixels na CPU...")
|
| 644 |
+
|
| 645 |
+
frames_p1 = tamanho_base * 8
|
| 646 |
+
parte1_pix = pixel_chunks_list[0][:, :, :frames_p1, :, :]
|
| 647 |
+
|
| 648 |
+
descarte_inicio_p2 = sobreposicao * 8
|
| 649 |
+
frames_p2 = tamanho_base * 8
|
| 650 |
+
parte2_pix = pixel_chunks_list[1][:, :, descarte_inicio_p2 : descarte_inicio_p2 + frames_p2, :, :]
|
| 651 |
+
|
| 652 |
+
descarte_inicio_p3 = sobreposicao * 8
|
| 653 |
+
parte3_pix = pixel_chunks_list[2][:, :, descarte_inicio_p3:, :, :]
|
| 654 |
+
|
| 655 |
+
final_pixel_tensor = torch.cat([parte1_pix, parte2_pix, parte3_pix], dim=2)
|
| 656 |
+
print(f" [LOG] Tensor de pixels final montado. Shape Final: {final_pixel_tensor.shape}")
|
| 657 |
+
del pixel_chunks_list, parte1_pix, parte2_pix, parte3_pix # Limpeza de memória
|
| 658 |
+
|
| 659 |
+
# --- ETAPA 4: Costurar os Latentes (para consistência do estado final) ---
|
| 660 |
+
print("\n[LOG] Etapa 4: Costurando os latentes refinados para o estado final...")
|
| 661 |
+
refined_hd_chunks = [torch.load(path) for path in refined_latent_chunk_paths]
|
| 662 |
+
|
| 663 |
+
parte1_lat = refined_hd_chunks[0][:, :, :tamanho_base, :, :]
|
| 664 |
+
parte2_lat = refined_hd_chunks[1][:, :, sobreposicao : sobreposicao + tamanho_base, :, :]
|
| 665 |
+
parte3_lat = refined_hd_chunks[2][:, :, sobreposicao:, :, :]
|
| 666 |
+
|
| 667 |
+
final_latents_hd = torch.cat([parte1_lat, parte2_lat, parte3_lat], dim=2)
|
| 668 |
+
print(f" [LOG] Latentes HD finais montados. Shape Final: {final_latents_hd.shape}")
|
| 669 |
+
del refined_hd_chunks, parte1_lat, parte2_lat, parte3_lat
|
| 670 |
+
|
| 671 |
+
# --- ETAPA 5: Salvar os Artefatos Finais ---
|
| 672 |
+
print("\n[LOG] Etapa 5: Salvando o vídeo MP4 e o tensor de latentes finais...")
|
| 673 |
+
|
| 674 |
+
# Salva o tensor de pixels costurado como o vídeo final
|
| 675 |
+
final_video_path = self._save_video_from_tensor(
|
| 676 |
+
final_pixel_tensor,
|
| 677 |
+
f"final_progressive_stitched_{seed}",
|
| 678 |
+
seed,
|
| 679 |
+
temp_dir_orchestrator
|
| 680 |
+
)
|
| 681 |
+
|
| 682 |
+
# Salva o tensor de latentes costurado para o estado do app
|
| 683 |
+
final_latents_path = self._save_latents_to_disk(final_latents_hd, "final_hd_stitched", seed)
|
| 684 |
+
|
| 685 |
+
print(f"\n[SUCCESS] Pós-Produção completa! Vídeo final: {final_video_path}")
|
| 686 |
+
return final_video_path, final_latents_path
|
| 687 |
+
|
| 688 |
+
|
| 689 |
+
def apply_secondary_refinement1(
|
| 690 |
self,
|
| 691 |
latents_path: str,
|
| 692 |
prompt: str,
|
|
|
|
| 820 |
|
| 821 |
video_path_out = self._save_video_from_tensor(pixel_tensor, "refined_video_final", used_seed, temp_dir)
|
| 822 |
latents_path_out = self._save_latents_to_disk(final_latents_cpu, "latents_refined_final", used_seed)
|
| 823 |
+
|
| 824 |
+
|
| 825 |
print(" [LOG] Tarefa concluída. Restaurando ambiente de GERAÇÃO na GPU para a próxima execução...")
|
| 826 |
self._set_generation_environment()
|
| 827 |
|
| 828 |
print(" [LOG] Liberando tensores finais da memória da CPU.")
|
| 829 |
+
del final_latents_cpu
|
| 830 |
self._finalize()
|
| 831 |
|
| 832 |
print("\n======================================================================")
|
| 833 |
print("============ [SUCCESS] ETAPA 2 Concluída com Sucesso =============")
|
| 834 |
print("======================================================================\n")
|
| 835 |
+
return video_path_out, latents_path_out, pixel_tensor
|
| 836 |
|
| 837 |
|
| 838 |
|