Spaces:
Paused
Paused
Update api/ltx_server.py
Browse files- api/ltx_server.py +57 -5
api/ltx_server.py
CHANGED
|
@@ -572,6 +572,26 @@ class VideoService:
|
|
| 572 |
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
| 573 |
return int(result.stdout.strip())
|
| 574 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 575 |
def _gerar_lista_com_transicoes(self, pasta: str, video_paths: list[str], crossfade_frames: int = 8) -> list[str]:
|
| 576 |
"""
|
| 577 |
Gera uma nova lista de vídeos aplicando transições suaves (blend frame a frame)
|
|
@@ -652,8 +672,23 @@ class VideoService:
|
|
| 652 |
print("===========CONCATECAO CAUSAL=============")
|
| 653 |
print(f"[DEBUG] {nova_lista}")
|
| 654 |
return nova_lista
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 655 |
|
| 656 |
-
def
|
| 657 |
"""
|
| 658 |
Concatena múltiplos MP4s sem reencode usando o demuxer do ffmpeg.
|
| 659 |
ATENÇÃO: todos os arquivos precisam ter mesmo codec, fps, resolução etc.
|
|
@@ -826,7 +861,16 @@ class VideoService:
|
|
| 826 |
except Exception:
|
| 827 |
pass
|
| 828 |
|
| 829 |
-
latents_parts_up = self._dividir_latentes_por_tamanho(latents_cpu_up,15,0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 830 |
|
| 831 |
for latents in latents_parts_up:
|
| 832 |
|
|
@@ -898,7 +942,15 @@ class VideoService:
|
|
| 898 |
except Exception:
|
| 899 |
pass
|
| 900 |
|
| 901 |
-
latents_parts_vae = self._dividir_latentes_por_tamanho(latents_cpu_vae,4,1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 902 |
|
| 903 |
for latents in latents_parts_vae:
|
| 904 |
print(f"[DEBUG] Partição {par}: {tuple(latents.shape)}")
|
|
@@ -937,8 +989,8 @@ class VideoService:
|
|
| 937 |
total_partes = len(partes_mp4)
|
| 938 |
if (total_partes>1):
|
| 939 |
final_vid = os.path.join(results_dir, f"concat_fim_{used_seed}.mp4")
|
| 940 |
-
partes_mp4_fade = self._gerar_lista_com_transicoes(pasta=results_dir, video_paths=partes_mp4, crossfade_frames=8)
|
| 941 |
-
self._concat_mp4s_no_reencode(
|
| 942 |
else:
|
| 943 |
final_vid = partes_mp4[0]
|
| 944 |
|
|
|
|
| 572 |
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
|
| 573 |
return int(result.stdout.strip())
|
| 574 |
|
| 575 |
+
|
| 576 |
+
|
| 577 |
+
def dividir_latentes(latents_brutos):
|
| 578 |
+
total = latents_brutos.shape[2] # dimensão temporal (número de latentes)
|
| 579 |
+
|
| 580 |
+
if total % 2 == 1: # ÍMPAR
|
| 581 |
+
# Ex: 11 → primeira 0..5, segunda 5..10
|
| 582 |
+
cut = total // 2
|
| 583 |
+
primeira = latents_brutos[:, :, :cut+1, :, :].clone()
|
| 584 |
+
segunda = latents_brutos[:, :, cut:, :, :].clone()
|
| 585 |
+
|
| 586 |
+
else: # PAR
|
| 587 |
+
# Ex: 12 → primeira 0..5, segunda 5..11
|
| 588 |
+
cut = total // 2
|
| 589 |
+
primeira = latents_brutos[:, :, :cut, :, :].clone()
|
| 590 |
+
segunda = latents_brutos[:, :, cut-1:, :, :].clone()
|
| 591 |
+
|
| 592 |
+
return primeira, segunda
|
| 593 |
+
|
| 594 |
+
|
| 595 |
def _gerar_lista_com_transicoes(self, pasta: str, video_paths: list[str], crossfade_frames: int = 8) -> list[str]:
|
| 596 |
"""
|
| 597 |
Gera uma nova lista de vídeos aplicando transições suaves (blend frame a frame)
|
|
|
|
| 672 |
print("===========CONCATECAO CAUSAL=============")
|
| 673 |
print(f"[DEBUG] {nova_lista}")
|
| 674 |
return nova_lista
|
| 675 |
+
|
| 676 |
+
def _concat_mp4s_no_reencode(self, mp4_a: str, mp4_b: str, out_path: str):
|
| 677 |
+
# Concat demuxer do ffmpeg (sem reencode)
|
| 678 |
+
import tempfile, subprocess, shlex, os
|
| 679 |
+
with tempfile.NamedTemporaryFile("w", delete=False, suffix=".txt") as f:
|
| 680 |
+
f.write(f"file '{os.path.abspath(mp4_a)}'\n")
|
| 681 |
+
f.write(f"file '{os.path.abspath(mp4_b)}'\n")
|
| 682 |
+
list_path = f.name
|
| 683 |
+
cmd = f"ffmpeg -y -f concat -safe 0 -i {list_path} -c copy {out_path}"
|
| 684 |
+
print(f"[DEBUG] Concat: {cmd}")
|
| 685 |
+
try:
|
| 686 |
+
subprocess.check_call(shlex.split(cmd))
|
| 687 |
+
finally:
|
| 688 |
+
try: os.remove(list_path)
|
| 689 |
+
except Exception: pass
|
| 690 |
|
| 691 |
+
def _concat_mp4s_no_reencode2(self, mp4_list: List[str], out_path: str):
|
| 692 |
"""
|
| 693 |
Concatena múltiplos MP4s sem reencode usando o demuxer do ffmpeg.
|
| 694 |
ATENÇÃO: todos os arquivos precisam ter mesmo codec, fps, resolução etc.
|
|
|
|
| 861 |
except Exception:
|
| 862 |
pass
|
| 863 |
|
| 864 |
+
#latents_parts_up = self._dividir_latentes_por_tamanho(latents_cpu_up,15,0)
|
| 865 |
+
|
| 866 |
+
|
| 867 |
+
lat_aup, lat_bup = dividir_latentes(latents_parts_up)
|
| 868 |
+
print(f"[DEBUG] Partição Aup: {tuple(lat_aup.shape)}")
|
| 869 |
+
print(f"[DEBUG] Partição Bup: {tuple(lat_bup.shape)}")
|
| 870 |
+
|
| 871 |
+
latents_parts_up = [lat_aup, lat_bup]
|
| 872 |
+
|
| 873 |
+
|
| 874 |
|
| 875 |
for latents in latents_parts_up:
|
| 876 |
|
|
|
|
| 942 |
except Exception:
|
| 943 |
pass
|
| 944 |
|
| 945 |
+
#latents_parts_vae = self._dividir_latentes_por_tamanho(latents_cpu_vae,4,1)
|
| 946 |
+
|
| 947 |
+
|
| 948 |
+
lat_a, lat_b = dividir_latentes(latents_cpu_vae)
|
| 949 |
+
print(f"[DEBUG] Partição A: {tuple(lat_a.shape)}")
|
| 950 |
+
print(f"[DEBUG] Partição B: {tuple(lat_b.shape)}")
|
| 951 |
+
|
| 952 |
+
latents_parts_vae = [lat_a, lat_b]
|
| 953 |
+
|
| 954 |
|
| 955 |
for latents in latents_parts_vae:
|
| 956 |
print(f"[DEBUG] Partição {par}: {tuple(latents.shape)}")
|
|
|
|
| 989 |
total_partes = len(partes_mp4)
|
| 990 |
if (total_partes>1):
|
| 991 |
final_vid = os.path.join(results_dir, f"concat_fim_{used_seed}.mp4")
|
| 992 |
+
#partes_mp4_fade = self._gerar_lista_com_transicoes(pasta=results_dir, video_paths=partes_mp4, crossfade_frames=8)
|
| 993 |
+
self._concat_mp4s_no_reencode(partes_mp4, final_vid)
|
| 994 |
else:
|
| 995 |
final_vid = partes_mp4[0]
|
| 996 |
|