Update api/ltx_server.py
Browse files- api/ltx_server.py +2 -40
api/ltx_server.py
CHANGED
|
@@ -436,45 +436,7 @@ class VideoService:
|
|
| 436 |
print("================PODA CAUSAL=================")
|
| 437 |
return chunks
|
| 438 |
|
| 439 |
-
|
| 440 |
-
"""
|
| 441 |
-
Concatena múltiplos MP4s sem reencode usando o demuxer do ffmpeg.
|
| 442 |
-
- Silencia logs do ffmpeg.
|
| 443 |
-
- Valida cada item e mostra metadados antes de concatenar.
|
| 444 |
-
"""
|
| 445 |
-
if not mp4_list or len(mp4_list) < 2:
|
| 446 |
-
raise ValueError("Forneça pelo menos dois arquivos MP4 para concatenar.")
|
| 447 |
-
|
| 448 |
-
valid_list = []
|
| 449 |
-
for mp4 in mp4_list:
|
| 450 |
-
if not os.path.exists(mp4):
|
| 451 |
-
print(f"⚠️ Arquivo não encontrado: {mp4}")
|
| 452 |
-
continue
|
| 453 |
-
info = self._get_video_info(mp4)
|
| 454 |
-
if info:
|
| 455 |
-
valid_list.append(mp4)
|
| 456 |
-
|
| 457 |
-
if len(valid_list) < 2:
|
| 458 |
-
raise RuntimeError("Menos de dois vídeos válidos para concatenar.")
|
| 459 |
-
|
| 460 |
-
with tempfile.NamedTemporaryFile("w", delete=False, suffix=".txt") as f:
|
| 461 |
-
for mp4 in valid_list:
|
| 462 |
-
f.write(f"file '{os.path.abspath(mp4)}'\n")
|
| 463 |
-
list_path = f.name
|
| 464 |
-
|
| 465 |
-
cmd = f"ffmpeg -hide_banner -loglevel warning -y -f concat -safe 0 -i {list_path} -c copy {out_path}"
|
| 466 |
-
print(f"[DEBUG] Concat: {cmd}")
|
| 467 |
-
|
| 468 |
-
try:
|
| 469 |
-
subprocess.check_call(shlex.split(cmd))
|
| 470 |
-
print(f"✅ Concatenação concluída: {out_path}")
|
| 471 |
-
self._get_video_info(out_path)
|
| 472 |
-
finally:
|
| 473 |
-
try:
|
| 474 |
-
os.remove(list_path)
|
| 475 |
-
except Exception:
|
| 476 |
-
pass
|
| 477 |
-
|
| 478 |
|
| 479 |
def _get_video_info(self, path: str) -> dict:
|
| 480 |
"""Retorna metadados essenciais do vídeo (DNA)."""
|
|
@@ -850,7 +812,7 @@ class VideoService:
|
|
| 850 |
print(f"[DEBUG] Falha no move; usando tmp como final: {e}")
|
| 851 |
|
| 852 |
final_concat = os.path.join(results_dir, f"concat_fim_{used_seed}.mp4")
|
| 853 |
-
partes_mp4_fade = self._gerar_lista_com_transicoes(pasta=results_dir, video_paths=partes_mp4, crossfade_frames=
|
| 854 |
self._concat_mp4s_no_reencode(partes_mp4_fade, final_concat)
|
| 855 |
|
| 856 |
|
|
|
|
| 436 |
print("================PODA CAUSAL=================")
|
| 437 |
return chunks
|
| 438 |
|
| 439 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 440 |
|
| 441 |
def _get_video_info(self, path: str) -> dict:
|
| 442 |
"""Retorna metadados essenciais do vídeo (DNA)."""
|
|
|
|
| 812 |
print(f"[DEBUG] Falha no move; usando tmp como final: {e}")
|
| 813 |
|
| 814 |
final_concat = os.path.join(results_dir, f"concat_fim_{used_seed}.mp4")
|
| 815 |
+
partes_mp4_fade = self._gerar_lista_com_transicoes(pasta=results_dir, video_paths=partes_mp4, crossfade_frames=8)
|
| 816 |
self._concat_mp4s_no_reencode(partes_mp4_fade, final_concat)
|
| 817 |
|
| 818 |
|