Update api/ltx_server_refactored.py
Browse files- api/ltx_server_refactored.py +8 -114
api/ltx_server_refactored.py
CHANGED
|
@@ -527,6 +527,13 @@ class VideoService:
|
|
| 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.
|
|
@@ -534,6 +541,7 @@ class VideoService:
|
|
| 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)
|
|
@@ -574,120 +582,6 @@ class VideoService:
|
|
| 574 |
return final_video_path, final_latents_path
|
| 575 |
|
| 576 |
|
| 577 |
-
|
| 578 |
-
def apply_secondary_refinement2(
|
| 579 |
-
self,
|
| 580 |
-
latents_path: str,
|
| 581 |
-
prompt: str,
|
| 582 |
-
negative_prompt: str,
|
| 583 |
-
guidance_scale: float,
|
| 584 |
-
seed: int,
|
| 585 |
-
# Novo parâmetro para controlar a micro-fragmentação do VAE no worker
|
| 586 |
-
num_decode_chunks_per_worker: int = 2
|
| 587 |
-
) -> Tuple[str, str]:
|
| 588 |
-
"""
|
| 589 |
-
Orquestra o pipeline de Pós-Produção: Upscale, Denoise em Chunks (coletando tensores),
|
| 590 |
-
e Costura final dos tensores para salvar.
|
| 591 |
-
"""
|
| 592 |
-
print("\n======================================================================")
|
| 593 |
-
print("====== [INFO] Iniciando Pós-Produção: Refinamento em Chunks e Costura Final ======")
|
| 594 |
-
print("======================================================================\n")
|
| 595 |
-
|
| 596 |
-
temp_dir_orchestrator = tempfile.mkdtemp(prefix="refine_orchestrator_")
|
| 597 |
-
self._register_tmp_dir(temp_dir_orchestrator)
|
| 598 |
-
|
| 599 |
-
# --- ETAPA 1: Upscale Espacial do Tensor Completo ---
|
| 600 |
-
print("[LOG] Etapa 1: Aplicando Upscale Espacial nos latentes de baixa resolução...")
|
| 601 |
-
self._set_generation_environment()
|
| 602 |
-
|
| 603 |
-
low_res_latents = torch.load(latents_path)
|
| 604 |
-
with torch.no_grad(), torch.autocast(device_type=self.device.split(':')[0], dtype=self.runtime_autocast_dtype, enabled=(self.device == 'cuda')):
|
| 605 |
-
latents_hd_upscaled = self._upsample_and_filter_latents(low_res_latents.to(self.device))
|
| 606 |
-
|
| 607 |
-
latents_hd_upscaled_cpu = latents_hd_upscaled.cpu()
|
| 608 |
-
print(f" [LOG] Upscale concluído. Novo shape de latentes HD: {latents_hd_upscaled_cpu.shape}")
|
| 609 |
-
del latents_hd_upscaled, low_res_latents
|
| 610 |
-
torch.cuda.empty_cache()
|
| 611 |
-
|
| 612 |
-
# --- ETAPA 2: Fragmentar, Processar em Chunks e Coletar Tensores ---
|
| 613 |
-
print("\n[LOG] Etapa 2: Fragmentando e processando cada chunk para obter tensores de pixels e latentes...")
|
| 614 |
-
total_latents = latents_hd_upscaled_cpu.shape[2]
|
| 615 |
-
sobreposicao = 2
|
| 616 |
-
num_divisoes = 3
|
| 617 |
-
tamanho_base = (total_latents - 1) // num_divisoes
|
| 618 |
-
|
| 619 |
-
if tamanho_base < sobreposicao:
|
| 620 |
-
raise ValueError("Latentes muito curtos para dividir em 3. Use o refinamento direto ou reduza o número de chunks.")
|
| 621 |
-
|
| 622 |
-
pontos_de_corte = [
|
| 623 |
-
(0, tamanho_base + sobreposicao),
|
| 624 |
-
(tamanho_base - sobreposicao, (2 * tamanho_base) + sobreposicao),
|
| 625 |
-
((2 * tamanho_base) - sobreposicao, total_latents)
|
| 626 |
-
]
|
| 627 |
-
hd_chunks_to_process = [latents_hd_upscaled_cpu[:, :, s:e, :, :] for s, e in pontos_de_corte]
|
| 628 |
-
|
| 629 |
-
pixel_chunks_list = []
|
| 630 |
-
refined_latent_chunks_list = []
|
| 631 |
-
|
| 632 |
-
for i, chunk in enumerate(hd_chunks_to_process):
|
| 633 |
-
print(f"\n --> Processando o Chunk {i+1}/{len(hd_chunks_to_process)}...")
|
| 634 |
-
chunk_path = os.path.join(temp_dir_orchestrator, f"hd_chunk_to_process_{i}.pt")
|
| 635 |
-
torch.save(chunk, chunk_path)
|
| 636 |
-
chunk_seed = seed + i + 1
|
| 637 |
-
|
| 638 |
-
# Chamamos a função worker, que retorna os tensores computados
|
| 639 |
-
pixel_chunk, refined_latent_chunk = self.refine_texture_only(
|
| 640 |
-
latents_path=chunk_path,
|
| 641 |
-
prompt=prompt, negative_prompt=negative_prompt,
|
| 642 |
-
guidance_scale=guidance_scale, seed=chunk_seed,
|
| 643 |
-
num_decode_chunks=num_decode_chunks_per_worker # Passando o controle da micro-fragmentação
|
| 644 |
-
)
|
| 645 |
-
pixel_chunks_list.append(pixel_chunk)
|
| 646 |
-
refined_latent_chunks_list.append(refined_latent_chunk)
|
| 647 |
-
print(f" --> Tensores do Chunk {i+1} recebidos.")
|
| 648 |
-
|
| 649 |
-
# --- ETAPA 3: Costurar os Tensores (Pixels e Latentes) ---
|
| 650 |
-
print("\n[LOG] Etapa 3: Costurando os tensores de pixels e latentes...")
|
| 651 |
-
|
| 652 |
-
# Costura de Pixels
|
| 653 |
-
final_pixel_tensor = self._stitch_chunks(
|
| 654 |
-
chunks_list=pixel_chunks_list,
|
| 655 |
-
num_divisoes=num_divisoes,
|
| 656 |
-
total_original_items=total_latents,
|
| 657 |
-
sobreposicao_items=sobreposicao,
|
| 658 |
-
item_multiplier=8,
|
| 659 |
-
domain_name="Pixels (Final)"
|
| 660 |
-
)
|
| 661 |
-
|
| 662 |
-
# Costura de Latentes
|
| 663 |
-
final_latents_hd = self._stitch_chunks(
|
| 664 |
-
chunks_list=refined_latent_chunks_list,
|
| 665 |
-
num_divisoes=num_divisoes,
|
| 666 |
-
total_original_items=total_latents,
|
| 667 |
-
sobreposicao_items=sobreposicao,
|
| 668 |
-
item_multiplier=1,
|
| 669 |
-
domain_name="Latentes (Final)"
|
| 670 |
-
)
|
| 671 |
-
|
| 672 |
-
# --- ETAPA 4: Salvar os Artefatos Finais ---
|
| 673 |
-
print("\n[LOG] Etapa 4: Salvando o vídeo MP4 e o tensor de latentes finais...")
|
| 674 |
-
|
| 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 |
-
final_latents_path = self._save_latents_to_disk(
|
| 682 |
-
final_latents_hd,
|
| 683 |
-
f"final_hd_stitched_{seed}",
|
| 684 |
-
seed
|
| 685 |
-
)
|
| 686 |
-
|
| 687 |
-
# A limpeza final dos tensores da CPU é feita implicitamente ao sair da função
|
| 688 |
-
print(f"\n[SUCCESS] Pós-Produção completa! Vídeo final: {final_video_path}")
|
| 689 |
-
return final_video_path, final_latents_path
|
| 690 |
-
|
| 691 |
def refine_texture_only(
|
| 692 |
self,
|
| 693 |
latents_path: str,
|
|
|
|
| 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 |
+
|
| 532 |
+
# Preparar condicionamento a partir de imagens de entrada, se houver
|
| 533 |
+
conditioning_items = []
|
| 534 |
+
conditioning_items.append(ConditioningItem(chunk_path, 0, 1.0))
|
| 535 |
+
print(f" [LOG] tensor de condition '{chunk_path}' preparada como condicionante.")
|
| 536 |
+
|
| 537 |
|
| 538 |
# A chamada a `refine_texture_only` internamente chamará `_set_generation_environment`,
|
| 539 |
# trazendo o Transformer de volta para a GPU e (se otimizado) movendo o VAE para a CPU.
|
|
|
|
| 541 |
latents_path=chunk_path,
|
| 542 |
prompt=prompt, negative_prompt=negative_prompt,
|
| 543 |
guidance_scale=guidance_scale, seed=chunk_seed,
|
| 544 |
+
conditioning_items=conditioning_items
|
| 545 |
num_decode_chunks=num_decode_chunks_per_worker
|
| 546 |
)
|
| 547 |
pixel_chunks_list.append(pixel_chunk)
|
|
|
|
| 582 |
return final_video_path, final_latents_path
|
| 583 |
|
| 584 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 585 |
def refine_texture_only(
|
| 586 |
self,
|
| 587 |
latents_path: str,
|