EuuIia commited on
Commit
85f06ad
·
verified ·
1 Parent(s): 29c78f7

Update api/ltx_server.py

Browse files
Files changed (1) hide show
  1. api/ltx_server.py +43 -54
api/ltx_server.py CHANGED
@@ -473,6 +473,7 @@ class VideoService:
473
  pass
474
 
475
 
 
476
  def generate(
477
  self,
478
  prompt,
@@ -575,11 +576,10 @@ class VideoService:
575
  print(f"[DEBUG] media_items shape={tuple(media.shape)}")
576
 
577
  latents = None
578
- multi_scale_pipeline = None
579
-
580
- # ltx_server.py (dentro da função generate)
581
-
582
  try:
 
 
583
  if improve_texture:
584
  if not self.latent_upsampler:
585
  raise ValueError("Upscaler espacial não carregado.")
@@ -617,7 +617,6 @@ class VideoService:
617
 
618
  print(f"[DEBUG] Passo 1: Dimensões reduzidas e ajustadas para {height_p1}x{width_p1}")
619
 
620
- ctx = torch.autocast(device_type="cuda", dtype=self.runtime_autocast_dtype) if self.device == "cuda" else contextlib.nullcontext()
621
  with ctx:
622
  first_pass_result = self.pipeline(**first_pass_kwargs)
623
 
@@ -656,14 +655,24 @@ class VideoService:
656
  "skip_block_list": second_pass_args.get("skip_block_list"),
657
  })
658
 
659
- strength = second_pass_args.get("strength", second_pass_args.get("denoising_strength", 0.7))
660
- second_pass_kwargs["strength"] = strength
661
- print(f"[DEBUG] Passo 2: Denoising strength definido para {strength}")
 
 
 
 
 
 
 
 
 
 
 
662
 
663
- if "timesteps" in second_pass_kwargs:
664
- del second_pass_kwargs["timesteps"]
665
- if "guidance_timesteps" in second_pass_kwargs:
666
- del second_pass_kwargs["guidance_timesteps"]
667
 
668
  second_pass_kwargs["latents"] = latents_high_res
669
 
@@ -672,8 +681,9 @@ class VideoService:
672
 
673
  latents = second_pass_result.images
674
  log_tensor_info(latents, "Latentes Finais (Passo 2)")
675
-
676
  else:
 
677
  single_pass_kwargs = call_kwargs.copy()
678
  first_pass_config = self.config.get("first_pass", {})
679
  single_pass_kwargs.update(
@@ -693,30 +703,22 @@ class VideoService:
693
  print(f"[DEBUG] Single-pass: timesteps_len={len(schedule) if schedule else 0}")
694
 
695
  print("\n[INFO] Executando pipeline de etapa única...")
696
- t_sp = time.perf_counter()
697
- ctx = torch.autocast(device_type="cuda", dtype=self.runtime_autocast_dtype) if self.device == "cuda" else contextlib.nullcontext()
698
  with ctx:
699
  result = self.pipeline(**single_pass_kwargs)
700
- print(f"[DEBUG] single-pass tempo={time.perf_counter()-t_sp:.3f}s")
701
-
702
- if hasattr(result, "latents"):
703
- latents = result.latents
704
- elif hasattr(result, "images") and isinstance(result.images, torch.Tensor):
705
- latents = result.images
706
- else:
707
- latents = result
708
  print(f"[DEBUG] Latentes (single-pass): shape={tuple(latents.shape)}")
709
 
710
- # Staging e escrita MP4 (simples: VAE pixels → MP4)
711
 
712
  latents_cpu = latents.detach().to("cpu", non_blocking=True)
713
- torch.cuda.empty_cache()
714
- try:
715
- torch.cuda.ipc_collect()
716
- except Exception:
717
- pass
 
718
 
719
- # 2) Divide em duas partes
720
  lat_a, lat_b = self._dividir_latentes(latents_cpu)
721
  lat_a1, lat_a2 = self._dividir_latentes(lat_a)
722
  lat_b1, lat_b2 = self._dividir_latentes(lat_b)
@@ -729,22 +731,19 @@ class VideoService:
729
  partes_mp4 = []
730
  par = 0
731
 
732
- for latents in latents_parts:
733
- print(f"[DEBUG] Partição {par}: {tuple(latents.shape)}")
734
-
735
  par = par + 1
736
  output_video_path = os.path.join(temp_dir, f"output_{used_seed}_{par}.mp4")
737
- final_output_path = None
738
 
739
  print("[DEBUG] Decodificando bloco de latentes com VAE → tensor de pixels...")
740
- # Usar manager com timestep por item; previne target_shape e rota NoneType.decode
741
  pixel_tensor = vae_manager_singleton.decode(
742
- latents.to(self.device, non_blocking=True),
743
  decode_timestep=float(self.config.get("decode_timestep", 0.05))
744
  )
745
  log_tensor_info(pixel_tensor, "Pixel tensor (VAE saída)")
746
 
747
- print("[DEBUG] Codificando MP4 a partir do tensor de pixels (bloco inteiro)...")
748
  video_encode_tool_singleton.save_video_from_tensor(
749
  pixel_tensor,
750
  output_video_path,
@@ -758,9 +757,7 @@ class VideoService:
758
  final_output_path = candidate
759
  print(f"[DEBUG] MP4 parte {par} movido para {final_output_path}")
760
  partes_mp4.append(final_output_path)
761
-
762
  except Exception as e:
763
- final_output_path = output_video_path
764
  print(f"[DEBUG] Falha no move; usando tmp como final: {e}")
765
 
766
  final_concat = os.path.join(results_dir, f"concat_fim_{used_seed}.mp4")
@@ -769,31 +766,23 @@ class VideoService:
769
  self._log_gpu_memory("Fim da Geração")
770
  return final_concat, used_seed
771
 
772
-
773
  except Exception as e:
774
  print("[DEBUG] EXCEÇÃO NA GERAÇÃO:")
775
  print("".join(traceback.format_exception(type(e), e, e.__traceback__)))
776
  raise
777
  finally:
778
  try:
779
- del latents
780
- except Exception:
781
- pass
782
- try:
783
- del multi_scale_pipeline
784
  except Exception:
785
  pass
786
 
787
  gc.collect()
788
- try:
789
- if self.device == "cuda":
790
  torch.cuda.empty_cache()
791
- try:
792
- torch.cuda.ipc_collect()
793
- except Exception:
794
- pass
795
- except Exception as e:
796
- print(f"[DEBUG] Limpeza GPU no finally falhou: {e}")
797
 
798
  try:
799
  self.finalize(keep_paths=[])
@@ -801,4 +790,4 @@ class VideoService:
801
  print(f"[DEBUG] finalize() no finally falhou: {e}")
802
 
803
  print("Criando instância do VideoService. O carregamento do modelo começará agora...")
804
- video_generation_service = VideoService()
 
473
  pass
474
 
475
 
476
+
477
  def generate(
478
  self,
479
  prompt,
 
576
  print(f"[DEBUG] media_items shape={tuple(media.shape)}")
577
 
578
  latents = None
579
+
 
 
 
580
  try:
581
+ ctx = torch.autocast(device_type="cuda", dtype=self.runtime_autocast_dtype) if self.device == "cuda" else contextlib.nullcontext()
582
+
583
  if improve_texture:
584
  if not self.latent_upsampler:
585
  raise ValueError("Upscaler espacial não carregado.")
 
617
 
618
  print(f"[DEBUG] Passo 1: Dimensões reduzidas e ajustadas para {height_p1}x{width_p1}")
619
 
 
620
  with ctx:
621
  first_pass_result = self.pipeline(**first_pass_kwargs)
622
 
 
655
  "skip_block_list": second_pass_args.get("skip_block_list"),
656
  })
657
 
658
+ schedule_p2 = second_pass_args.get("timesteps") or second_pass_args.get("guidance_timesteps")
659
+ if schedule_p2:
660
+ timesteps_para_refinamento = schedule_p2
661
+ print(f"[DEBUG] Passo 2: Usando {len(timesteps_para_refinamento)} timesteps pré-definidos do config para refinamento.")
662
+ else:
663
+ strength_p2 = second_pass_args.get("strength", second_pass_args.get("denoising_strength", 0.4))
664
+ num_steps_passo2_total = second_pass_args.get("num_inference_steps", 20)
665
+
666
+ self.pipeline.scheduler.set_timesteps(num_steps_passo2_total, device=self.device)
667
+ todos_os_timesteps_p2 = self.pipeline.scheduler.timesteps
668
+
669
+ ponto_de_corte = int(len(todos_os_timesteps_p2) * (1.0 - strength_p2))
670
+ timesteps_para_refinamento = todos_os_timesteps_p2[ponto_de_corte:]
671
+ print(f"[DEBUG] Passo 2: Calculando {len(timesteps_para_refinamento)} timesteps manuais (strength ≈ {strength_p2})")
672
 
673
+ second_pass_kwargs["timesteps"] = timesteps_para_refinamento
674
+
675
+ if "strength" in second_pass_kwargs: del second_pass_kwargs["strength"]
 
676
 
677
  second_pass_kwargs["latents"] = latents_high_res
678
 
 
681
 
682
  latents = second_pass_result.images
683
  log_tensor_info(latents, "Latentes Finais (Passo 2)")
684
+
685
  else:
686
+ # --- PASSO ÚNICO (SINGLE-PASS) ---
687
  single_pass_kwargs = call_kwargs.copy()
688
  first_pass_config = self.config.get("first_pass", {})
689
  single_pass_kwargs.update(
 
703
  print(f"[DEBUG] Single-pass: timesteps_len={len(schedule) if schedule else 0}")
704
 
705
  print("\n[INFO] Executando pipeline de etapa única...")
 
 
706
  with ctx:
707
  result = self.pipeline(**single_pass_kwargs)
708
+
709
+ latents = result.images
 
 
 
 
 
 
710
  print(f"[DEBUG] Latentes (single-pass): shape={tuple(latents.shape)}")
711
 
712
+ # --- DECODIFICAÇÃO E CODIFICAÇÃO DE VÍDEO FINAL ---
713
 
714
  latents_cpu = latents.detach().to("cpu", non_blocking=True)
715
+ if self.device == "cuda":
716
+ torch.cuda.empty_cache()
717
+ try:
718
+ torch.cuda.ipc_collect()
719
+ except Exception:
720
+ pass
721
 
 
722
  lat_a, lat_b = self._dividir_latentes(latents_cpu)
723
  lat_a1, lat_a2 = self._dividir_latentes(lat_a)
724
  lat_b1, lat_b2 = self._dividir_latentes(lat_b)
 
731
  partes_mp4 = []
732
  par = 0
733
 
734
+ for part in latents_parts:
735
+ print(f"[DEBUG] Partição {par}: {tuple(part.shape)}")
 
736
  par = par + 1
737
  output_video_path = os.path.join(temp_dir, f"output_{used_seed}_{par}.mp4")
 
738
 
739
  print("[DEBUG] Decodificando bloco de latentes com VAE → tensor de pixels...")
 
740
  pixel_tensor = vae_manager_singleton.decode(
741
+ part.to(self.device, non_blocking=True),
742
  decode_timestep=float(self.config.get("decode_timestep", 0.05))
743
  )
744
  log_tensor_info(pixel_tensor, "Pixel tensor (VAE saída)")
745
 
746
+ print("[DEBUG] Codificando MP4 a partir do tensor de pixels...")
747
  video_encode_tool_singleton.save_video_from_tensor(
748
  pixel_tensor,
749
  output_video_path,
 
757
  final_output_path = candidate
758
  print(f"[DEBUG] MP4 parte {par} movido para {final_output_path}")
759
  partes_mp4.append(final_output_path)
 
760
  except Exception as e:
 
761
  print(f"[DEBUG] Falha no move; usando tmp como final: {e}")
762
 
763
  final_concat = os.path.join(results_dir, f"concat_fim_{used_seed}.mp4")
 
766
  self._log_gpu_memory("Fim da Geração")
767
  return final_concat, used_seed
768
 
 
769
  except Exception as e:
770
  print("[DEBUG] EXCEÇÃO NA GERAÇÃO:")
771
  print("".join(traceback.format_exception(type(e), e, e.__traceback__)))
772
  raise
773
  finally:
774
  try:
775
+ del latents, latents_low_res, latents_high_res, second_pass_result
 
 
 
 
776
  except Exception:
777
  pass
778
 
779
  gc.collect()
780
+ if self.device == "cuda":
781
+ try:
782
  torch.cuda.empty_cache()
783
+ torch.cuda.ipc_collect()
784
+ except Exception as e:
785
+ print(f"[DEBUG] Limpeza GPU no finally falhou: {e}")
 
 
 
786
 
787
  try:
788
  self.finalize(keep_paths=[])
 
790
  print(f"[DEBUG] finalize() no finally falhou: {e}")
791
 
792
  print("Criando instância do VideoService. O carregamento do modelo começará agora...")
793
+ video_generation_service = VideoService()