Update api/ltx_server.py
Browse files- api/ltx_server.py +24 -69
api/ltx_server.py
CHANGED
|
@@ -397,89 +397,44 @@ class VideoService:
|
|
| 397 |
return out
|
| 398 |
|
| 399 |
|
| 400 |
-
def
|
| 401 |
"""
|
| 402 |
-
Divide
|
| 403 |
-
Args: latents_brutos: tensor [B, C, T, H, W]
|
| 404 |
-
quantidade: número de partes que queremos dividir
|
| 405 |
-
Returns:
|
| 406 |
-
List[Tensor]: lista de `quantidade` partes, cada uma cloneada
|
| 407 |
-
"""
|
| 408 |
-
sum_latent = latents_brutos.shape[2] # dimensão temporal (latentes)
|
| 409 |
-
chunks = []
|
| 410 |
-
|
| 411 |
-
# minimo 5 latentes para dividir
|
| 412 |
-
#min = 5
|
| 413 |
-
#if sum_latent < min or sum_latent//quantidade < min :
|
| 414 |
-
# return [latents_brutos.clone()]
|
| 415 |
-
|
| 416 |
-
# calcular tamanho aproximado de cada parte
|
| 417 |
-
step = sum_latent // quantidade
|
| 418 |
-
overlap = 1
|
| 419 |
-
|
| 420 |
-
print(f"================PODA CAUSAL=================")
|
| 421 |
-
print(f"[DEBUG] TOTAL LATENTES A DIVIDIR /{quantidade} = {sum_latent}")
|
| 422 |
|
| 423 |
-
for i in range(quantidade):
|
| 424 |
-
start = i * step
|
| 425 |
-
end = start + step
|
| 426 |
-
if i == quantidade - 1:
|
| 427 |
-
end = sum_latent
|
| 428 |
-
else:
|
| 429 |
-
end += overlap
|
| 430 |
-
if i > 0:
|
| 431 |
-
start = start - overlap
|
| 432 |
-
chunk = latents_brutos[:, :, start:end, :, :].clone()
|
| 433 |
-
chunks.append(chunk)
|
| 434 |
-
chunk_sum = chunk.shape[2]
|
| 435 |
-
print(f"[DEBUG] chunk{i+1}[:, :, {start}:{end}, :, :] = {chunk_sum}")
|
| 436 |
-
|
| 437 |
-
print(f"================PODA CAUSAL=================")
|
| 438 |
-
return chunks
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
def _dividir_latentes_em_partes(self, latents_brutos, min_latentes_por_chunk: int):
|
| 442 |
-
"""
|
| 443 |
-
Divide o tensor de latentes em várias partes com base no número mínimo de latentes por chunk.
|
| 444 |
-
Cada parte tem sobreposição causal de 1 frame com a anterior.
|
| 445 |
-
|
| 446 |
Args:
|
| 447 |
latents_brutos: tensor [B, C, T, H, W]
|
| 448 |
-
|
| 449 |
-
|
|
|
|
| 450 |
Returns:
|
| 451 |
-
List[
|
| 452 |
"""
|
| 453 |
-
|
| 454 |
-
overlap = 1
|
| 455 |
chunks = []
|
| 456 |
|
| 457 |
-
|
| 458 |
-
|
| 459 |
-
print(f"[DEBUG] Num LATENTES por chunk = {min_latentes_por_chunk}")
|
| 460 |
|
| 461 |
-
|
| 462 |
-
|
|
|
|
|
|
|
|
|
|
| 463 |
|
| 464 |
-
|
| 465 |
-
|
| 466 |
-
|
| 467 |
-
|
|
|
|
|
|
|
|
|
|
| 468 |
chunk = latents_brutos[:, :, start:end, :, :].clone()
|
| 469 |
chunks.append(chunk)
|
| 470 |
-
|
| 471 |
-
print(f"[DEBUG] chunk{i+1}[:, :, {start}:{end}, :, :] = {chunk.shape[2]}")
|
| 472 |
-
|
| 473 |
-
# Avança com sobreposição
|
| 474 |
-
start = end - overlap
|
| 475 |
-
i += 1
|
| 476 |
-
|
| 477 |
-
# Evita loop infinito se o final for atingido
|
| 478 |
-
if start >= total_latents:
|
| 479 |
-
break
|
| 480 |
|
| 481 |
print("================PODA CAUSAL=================")
|
| 482 |
return chunks
|
|
|
|
| 483 |
|
| 484 |
def _concat_crossfade_videos_por_frames(self, mp4_list, out_path, fps=24, crossfade_frames=8):
|
| 485 |
"""
|
|
@@ -749,7 +704,7 @@ class VideoService:
|
|
| 749 |
#lat_a1, lat_a2 = self._dividir_latentes(lat_a)
|
| 750 |
#lat_b1, lat_b2 = self._dividir_latentes(lat_b)
|
| 751 |
#latents_parts = [lat_a1, lat_a2, lat_b1, lat_b2]
|
| 752 |
-
latents_parts = self.
|
| 753 |
|
| 754 |
temp_dir = tempfile.mkdtemp(prefix="ltxv_"); self._register_tmp_dir(temp_dir)
|
| 755 |
results_dir = "/app/output"; os.makedirs(results_dir, exist_ok=True)
|
|
|
|
| 397 |
return out
|
| 398 |
|
| 399 |
|
| 400 |
+
def _dividir_latentes_por_tamanho(self, latents_brutos, num_latente_por_chunk: int, overlap: int = 1):
|
| 401 |
"""
|
| 402 |
+
Divide o tensor de latentes em chunks com tamanho definido em número de latentes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 403 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 404 |
Args:
|
| 405 |
latents_brutos: tensor [B, C, T, H, W]
|
| 406 |
+
num_latente_por_chunk: número de latentes por chunk
|
| 407 |
+
overlap: número de frames que se sobrepõem entre chunks
|
| 408 |
+
|
| 409 |
Returns:
|
| 410 |
+
List[tensor]: lista de chunks cloneados
|
| 411 |
"""
|
| 412 |
+
sum_latent = latents_brutos.shape[2]
|
|
|
|
| 413 |
chunks = []
|
| 414 |
|
| 415 |
+
if num_latente_por_chunk >= sum_latent:
|
| 416 |
+
return [latents_brutos.clone()]
|
|
|
|
| 417 |
|
| 418 |
+
steps = (sum_latent + num_latente_por_chunk - 1) // num_latente_por_chunk # ceil
|
| 419 |
+
print("================PODA CAUSAL=================")
|
| 420 |
+
print(f"[DEBUG] TOTAL LATENTES = {sum_latent}")
|
| 421 |
+
print(f"[DEBUG] Num LATENTES por chunk = {num_latente_por_chunk}")
|
| 422 |
+
print(f"[DEBUG] Número de chunks = {steps}")
|
| 423 |
|
| 424 |
+
for i in range(steps):
|
| 425 |
+
start = i * num_latente_por_chunk
|
| 426 |
+
end = start + num_latente_por_chunk
|
| 427 |
+
if i > 0:
|
| 428 |
+
start -= overlap # sobreposição
|
| 429 |
+
if end > sum_latent:
|
| 430 |
+
end = sum_latent
|
| 431 |
chunk = latents_brutos[:, :, start:end, :, :].clone()
|
| 432 |
chunks.append(chunk)
|
| 433 |
+
print(f"[DEBUG] chunk{i+1}[:, :, {start}:{end}, :, :] = {chunk.shape[2]}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 434 |
|
| 435 |
print("================PODA CAUSAL=================")
|
| 436 |
return chunks
|
| 437 |
+
|
| 438 |
|
| 439 |
def _concat_crossfade_videos_por_frames(self, mp4_list, out_path, fps=24, crossfade_frames=8):
|
| 440 |
"""
|
|
|
|
| 704 |
#lat_a1, lat_a2 = self._dividir_latentes(lat_a)
|
| 705 |
#lat_b1, lat_b2 = self._dividir_latentes(lat_b)
|
| 706 |
#latents_parts = [lat_a1, lat_a2, lat_b1, lat_b2]
|
| 707 |
+
latents_parts = self._dividir_latentes_por_tamanho(latents_cpu,6,1)
|
| 708 |
|
| 709 |
temp_dir = tempfile.mkdtemp(prefix="ltxv_"); self._register_tmp_dir(temp_dir)
|
| 710 |
results_dir = "/app/output"; os.makedirs(results_dir, exist_ok=True)
|