159 lines
5.0 KiB
Python
159 lines
5.0 KiB
Python
#!/usr/bin/env python3
|
|
"""CLI mínimo que expone el orquestador principal.
|
|
|
|
Este módulo proporciona la función `main()` que construye los adaptadores
|
|
por defecto e invoca `PipelineOrchestrator.run(...)`. Está diseñado para
|
|
reemplazar el antiguo `run_full_pipeline.py` como punto de entrada.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import glob
|
|
import os
|
|
import shutil
|
|
import sys
|
|
import tempfile
|
|
|
|
from whisper_project.usecases.orchestrator import PipelineOrchestrator
|
|
from whisper_project.infra.kokoro_adapter import KokoroHttpClient
|
|
|
|
|
|
def main():
|
|
p = argparse.ArgumentParser()
|
|
p.add_argument("--video", required=True)
|
|
p.add_argument("--srt", help="SRT de entrada (opcional)")
|
|
p.add_argument(
|
|
"--kokoro-endpoint",
|
|
required=False,
|
|
default="https://kokoro.example/api/synthesize",
|
|
help=(
|
|
"Endpoint HTTP de Kokoro (por defecto: "
|
|
"https://kokoro.example/api/synthesize)"
|
|
),
|
|
)
|
|
p.add_argument("--kokoro-key", required=False)
|
|
p.add_argument("--voice", default="em_alex")
|
|
p.add_argument("--kokoro-model", default="model")
|
|
p.add_argument("--whisper-model", default="base")
|
|
p.add_argument(
|
|
"--translate-method",
|
|
choices=[
|
|
"local",
|
|
"gemini",
|
|
"argos",
|
|
"none",
|
|
],
|
|
default="local",
|
|
)
|
|
p.add_argument(
|
|
"--gemini-key",
|
|
default=None,
|
|
help=(
|
|
"API key para Gemini (si eliges "
|
|
"--translate-method=gemini)"
|
|
),
|
|
)
|
|
p.add_argument("--mix", action="store_true")
|
|
p.add_argument("--mix-background-volume", type=float, default=0.2)
|
|
p.add_argument("--keep-chunks", action="store_true")
|
|
p.add_argument("--keep-temp", action="store_true")
|
|
p.add_argument(
|
|
"--dry-run",
|
|
action="store_true",
|
|
help="Simular pasos sin ejecutar",
|
|
)
|
|
args = p.parse_args()
|
|
|
|
video = os.path.abspath(args.video)
|
|
if not os.path.exists(video):
|
|
print("Vídeo no encontrado:", video, file=sys.stderr)
|
|
sys.exit(2)
|
|
|
|
workdir = tempfile.mkdtemp(prefix="full_pipeline_")
|
|
try:
|
|
# construir cliente Kokoro HTTP nativo e inyectarlo en el orquestador
|
|
kokoro_client = KokoroHttpClient(
|
|
args.kokoro_endpoint,
|
|
api_key=args.kokoro_key,
|
|
voice=args.voice,
|
|
model=args.kokoro_model,
|
|
)
|
|
|
|
orchestrator = PipelineOrchestrator(
|
|
kokoro_endpoint=args.kokoro_endpoint,
|
|
kokoro_key=args.kokoro_key,
|
|
voice=args.voice,
|
|
kokoro_model=args.kokoro_model,
|
|
tts_client=kokoro_client,
|
|
)
|
|
|
|
result = orchestrator.run(
|
|
video=video,
|
|
srt=args.srt,
|
|
workdir=workdir,
|
|
translate_method=args.translate_method,
|
|
gemini_api_key=args.gemini_key,
|
|
whisper_model=args.whisper_model,
|
|
mix=args.mix,
|
|
mix_background_volume=args.mix_background_volume,
|
|
keep_chunks=args.keep_chunks,
|
|
dry_run=args.dry_run,
|
|
)
|
|
|
|
# Si no es dry-run, crear una subcarpeta por proyecto en output/
|
|
# (output/<basename-of-video>) y mover allí los artefactos generados.
|
|
final_path = None
|
|
if (
|
|
not args.dry_run
|
|
and result
|
|
and getattr(result, "burned_video", None)
|
|
):
|
|
base = os.path.splitext(os.path.basename(video))[0]
|
|
project_out = os.path.join(os.getcwd(), "output", base)
|
|
try:
|
|
os.makedirs(project_out, exist_ok=True)
|
|
except Exception:
|
|
pass
|
|
|
|
# Mover el vídeo principal
|
|
src = result.burned_video
|
|
dest = os.path.join(project_out, os.path.basename(src))
|
|
try:
|
|
if os.path.abspath(src) != os.path.abspath(dest):
|
|
shutil.move(src, dest)
|
|
final_path = dest
|
|
except Exception:
|
|
final_path = src
|
|
|
|
# También mover otros artefactos que empiecen por el basename
|
|
try:
|
|
pattern = os.path.join(os.getcwd(), f"{base}*")
|
|
for p in glob.glob(pattern):
|
|
# no mover el archivo fuente ya movido
|
|
if os.path.abspath(p) == os.path.abspath(final_path):
|
|
continue
|
|
# mover sólo ficheros regulares
|
|
try:
|
|
if os.path.isfile(p):
|
|
shutil.move(p, os.path.join(project_out, os.path.basename(p)))
|
|
except Exception:
|
|
pass
|
|
except Exception:
|
|
pass
|
|
else:
|
|
# En dry-run o sin resultado, no movemos nada
|
|
final_path = getattr(result, "burned_video", None)
|
|
|
|
print("Flujo completado. Vídeo final:", final_path)
|
|
finally:
|
|
if not args.keep_temp:
|
|
try:
|
|
shutil.rmtree(workdir)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|