124 lines
4.8 KiB
Python
124 lines
4.8 KiB
Python
"""Funciones helper para sintetizar desde SRT.
|
|
|
|
Este módulo mantiene compatibilidad con la antigua utilidad `srt_to_kokoro.py`.
|
|
Contiene `parse_srt_file` y `synth_chunk` delegando a infra.kokoro_utils.
|
|
Se incluye una función `synthesize_from_srt` que documenta la compatibilidad
|
|
con `KokoroHttpClient` (nombre esperado por otros módulos).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from whisper_project.infra.kokoro_utils import parse_srt_file as _parse_srt_file, synth_chunk as _synth_chunk
|
|
|
|
|
|
def parse_srt_file(path: str):
|
|
"""Parsea un .srt y devuelve la lista de subtítulos.
|
|
|
|
Delegado a `whisper_project.infra.kokoro_utils.parse_srt_file`.
|
|
"""
|
|
return _parse_srt_file(path)
|
|
|
|
|
|
def synth_chunk(endpoint: str, text: str, headers: dict, payload_template: Any, timeout: int = 60) -> bytes:
|
|
"""Envía texto al endpoint y devuelve bytes de audio.
|
|
|
|
Delegado a `whisper_project.infra.kokoro_utils.synth_chunk`.
|
|
"""
|
|
return _synth_chunk(endpoint, text, headers, payload_template, timeout=timeout)
|
|
|
|
|
|
def synthesize_from_srt(srt_path: str, out_wav: str, endpoint: str = "", api_key: str = ""):
|
|
"""Compat layer: función con el nombre esperado por scripts legacy.
|
|
|
|
Nota: la implementación completa se encuentra ahora en `KokoroHttpClient`.
|
|
Esta función delega a `parse_srt_file` y `synth_chunk` si se necesita.
|
|
"""
|
|
raise NotImplementedError("Use KokoroHttpClient.synthesize_from_srt or the infra adapter instead")
|
|
|
|
|
|
__all__ = ["parse_srt_file", "synth_chunk", "synthesize_from_srt"]
|
|
#!/usr/bin/env python3
|
|
"""
|
|
srt_to_kokoro.py
|
|
|
|
Leer un archivo .srt y sintetizar cada subtítulo usando una API OpenAPI-compatible (p. ej. Kokoro).
|
|
- Intenta autodetectar un endpoint de síntesis en `--openapi` (URL JSON) buscando paths que contengan 'synth'|'tts'|'text' y que acepten POST.
|
|
- Alternativamente usa `--endpoint` y un `--payload-template` con {text} como placeholder.
|
|
- Guarda fragmentos temporales y los concatena con ffmpeg en un único WAV de salida.
|
|
|
|
Dependencias: requests, srt (pip install requests srt)
|
|
Requiere ffmpeg en PATH.
|
|
|
|
Ejemplos:
|
|
python srt_to_kokoro.py --srt subs.srt --openapi "https://kokoro.../openapi.json" --voice "alloy" --out out.wav --api-key "TOKEN"
|
|
python srt_to_kokoro.py --srt subs.srt --endpoint "https://kokoro.../v1/synthesize" --payload-template '{"text": "{text}", "voice": "alloy"}' --out out.wav
|
|
|
|
"""
|
|
|
|
import argparse
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
from typing import Optional
|
|
|
|
"""
|
|
Thin wrapper CLI que delega en `KokoroHttpClient.synthesize_from_srt`.
|
|
|
|
Conserva la interfaz CLI previa para compatibilidad, pero internamente usa
|
|
el cliente HTTP nativo definido en `whisper_project.infra.kokoro_adapter`.
|
|
"""
|
|
|
|
import argparse
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
|
|
from whisper_project.infra.kokoro_adapter import KokoroHttpClient
|
|
|
|
|
|
def main():
|
|
p = argparse.ArgumentParser()
|
|
p.add_argument("--srt", required=True, help="Ruta al archivo .srt traducido")
|
|
p.add_argument("--endpoint", required=False, help="URL directa del endpoint de síntesis (opcional)")
|
|
p.add_argument("--api-key", required=False, help="Valor para autorización (se envía como header Authorization: Bearer <key>)")
|
|
p.add_argument("--voice", default="em_alex")
|
|
p.add_argument("--model", default="model")
|
|
p.add_argument("--out", required=True, help="Ruta de salida WAV final")
|
|
p.add_argument("--video", required=False, help="Ruta al vídeo original (opcional)")
|
|
p.add_argument("--align", action="store_true", help="Alinear segmentos con timestamps del SRT")
|
|
p.add_argument("--keep-chunks", action="store_true")
|
|
p.add_argument("--mix-with-original", action="store_true")
|
|
p.add_argument("--mix-background-volume", type=float, default=0.2)
|
|
p.add_argument("--replace-original", action="store_true")
|
|
args = p.parse_args()
|
|
|
|
# Construir cliente Kokoro HTTP y delegar la síntesis completa
|
|
endpoint = args.endpoint or os.environ.get("KOKORO_ENDPOINT")
|
|
api_key = args.api_key or os.environ.get("KOKORO_API_KEY")
|
|
if not endpoint:
|
|
print("Debe proporcionar --endpoint o la variable de entorno KOKORO_ENDPOINT", file=sys.stderr)
|
|
sys.exit(2)
|
|
|
|
client = KokoroHttpClient(endpoint, api_key=api_key, voice=args.voice, model=args.model)
|
|
try:
|
|
client.synthesize_from_srt(
|
|
srt_path=args.srt,
|
|
out_wav=args.out,
|
|
video=args.video,
|
|
align=args.align,
|
|
keep_chunks=args.keep_chunks,
|
|
mix_with_original=args.mix_with_original,
|
|
mix_background_volume=args.mix_background_volume,
|
|
)
|
|
print(f"Archivo final generado en: {args.out}")
|
|
except Exception as e:
|
|
print(f"Error durante la síntesis desde SRT: {e}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|