#!/usr/bin/env python3 """Herramienta simple para quemar un archivo .srt en un vídeo usando ffmpeg. Uso: python -m whisper_project.burn_srt --video input.mp4 --srt subs.srt --out output.mp4 Opciones: --style: opcional, cadena de estilos para `subtitles` filter (por ejemplo "FontName=Arial,FontSize=24"). --codec: codec de vídeo de salida (por defecto reencode con libx264). """ from __future__ import annotations import argparse import logging import os import shlex import subprocess import sys def burn_subtitles_ffmpeg(video: str, srt: str, out: str, style: str | None = None, codec: str | None = None) -> None: # Asegurar rutas absolutas video_p = os.path.abspath(video) srt_p = os.path.abspath(srt) out_p = os.path.abspath(out) # Construir filtro subtitles. Escapar correctamente la ruta con shlex.quote # para evitar problemas con espacios y caracteres especiales. quoted_srt = shlex.quote(srt_p) vf = f"subtitles={quoted_srt}" if style: # force_style debe ir separado por ':' en ffmpeg vf = vf + f":force_style='{style}'" cmd = [ "ffmpeg", "-y", "-i", video_p, "-vf", vf, ] # Si se especifica codec, usarlo; si no, reencode por defecto con libx264 if codec: cmd += ["-c:v", codec, "-c:a", "copy", out_p] else: cmd += ["-c:v", "libx264", "-crf", "23", "-preset", "medium", out_p] logging.info("Ejecutando ffmpeg para quemar SRT: %s", " ".join(shlex.quote(c) for c in cmd)) subprocess.run(cmd, check=True) def main(argv: list[str] | None = None) -> int: p = argparse.ArgumentParser(description="Quemar un .srt en un vídeo con ffmpeg") p.add_argument("--video", required=True, help="Vídeo de entrada") p.add_argument("--srt", required=True, help="Archivo SRT a quemar") p.add_argument("--out", required=True, help="Vídeo de salida") p.add_argument("--style", required=False, help="Force style para el filtro subtitles (ej: FontName=Arial,FontSize=24)") p.add_argument("--codec", required=False, help="Codec de vídeo para salida (ej: libx264)") p.add_argument("--verbose", action="store_true") args = p.parse_args(argv) logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO) try: burn_subtitles_ffmpeg(args.video, args.srt, args.out, style=args.style, codec=args.codec) except subprocess.CalledProcessError as e: logging.exception("ffmpeg falló al quemar subtítulos: %s", e) return 2 logging.info("Vídeo con subtítulos guardado en: %s", args.out) return 0 if __name__ == "__main__": raise SystemExit(main())