Open Source · Python 3.11 · MIT License

Desglose técnico de
MoneyPrinterTurbo

Un generador automático de vídeos cortos impulsado por IA. Ingresa un tema y el sistema orquesta una pipeline completa: generación de guion con LLM, síntesis de voz, búsqueda de stock footage, subtitulado automático y composición final — todo sin intervención manual.

20+LLM Providers
6TTS Engines
3Stock Video APIs
8Idiomas UI
2Modos de despliegue
📝Script
🔑Keywords
🎙️Audio
📄Subtítulos
🎬Stock Videos
Composición
ARQUITECTURA

Arquitectura del sistema

El proyecto sigue un patrón MVC (Model-View-Controller) clásico, con FastAPI como backend REST, Streamlit como interfaz web, y una cola de tareas asíncrona para ejecutar los pipelines de generación de vídeo.

Controller
FastAPI + Streamlit
Service Layer
LLM · TTS · Sub · Material · Video
Model
Pydantic Schemas
Task Queue
ThreadPool + Redis (opt.)
Video Engine
MoviePy + FFmpeg
Storage
Cache · Tasks · Models
Flujo de datos
HTTP Request ──▶ Controller ──▶ TaskManager Service Layer ┌────────────────────┼────────────────────┐ ▼ ▼ ▼ LLM Service TTS Service Material (guion + terms) (audio + timestamps) (stock videos) │ │ │ └────────────────────┼────────────────────┘ Video Service (composición final)
🧩
Principios de diseño
  • Provider abstraction — Cada servicio (LLM, TTS) define una interfaz común y los providers concretos se seleccionan por configuración.
  • Pipeline state machine — El orquestador (task.py) avanza paso a paso; cada etapa puede ser un punto de parada (stop_at).
  • Task queue — Las solicitudes de generación se encolan con ThreadPoolExecutor y opcionalmente Redis para persistencia.
  • Graceful degradation — Si un provider TTS falla, se intenta con el siguiente; si no hay stock footage, se usan clips locales o color sólido.
PIPELINE

Pipeline de generación de vídeo

El corazón del proyecto. Un flujo de 6 etapas encadenadas que transforman un tema cualquiera en un vídeo corto completo con voz, música, subtítulos y transiciones.

📝
1. Generación de guion (LLM)

Si no se proporciona un guion manual, el sistema llama al LLM configurado para redactar un texto adaptado al formato de vídeo corto. Soporta más de 20 providers con una interfaz unificada: OpenAI, Gemini, DeepSeek, Groq, Claude (vía LiteLLM), Ollama (local), y muchos más.

app/services/llm.pyPython
def generate_script(params: VideoParams) -> str:
    prompt = build_script_prompt(
        subject=params.video_subject,
        paragraphs=params.paragraph_number,
        language=params.video_language
    )
    for attempt in range(5):
        try:
            resp = llm_request(prompt)
            return clean_script(resp)
        except Exception as e:
            logger.warning(f"Attempt {attempt+1} failed: {e}")
    raise RuntimeError("Script generation failed")

El prompt incluye el tema, número de párrafos, idioma y un system prompt que instruye al modelo a escribir para formato de vídeo corto (oraciones directas, transiciones naturales). La respuesta se limpia de caracteres markdown antes de devolverla.

OpenAI Gemini DeepSeek Groq Ollama (local) Claude (LiteLLM) Moonshot Qwen
🔑
2. Generación de términos de búsqueda

Una vez listo el guion, se pide al LLM que genere entre 5 y 8 keywords en inglés para buscar stock footage. Con la opción match_materials_to_script, los términos se ordenan cronológicamente para que el metraje coincida con la narrativa.

app/services/llm.pyPython
def generate_terms(script: str, style: str, language: str) -> list:
    prompt = f"Generate 5-8 English search terms for stock video about:\n{script}"
    for attempt in range(5):
        raw = llm_request(prompt)
        try:
            terms = json.loads(raw)
            if isinstance(terms, list) and len(terms) >= 3:
                return terms
        except json.JSONDecodeError:
            match = re.findall(r'"([^"]+)"', raw)
            if match: return match

El LLM devuelve un array JSON. Si el parseo falla, un regex extrae los strings entre comillas como fallback. Esto asegura robustez ante respuestas mal formateadas.

🎙️
3. Síntesis de voz (TTS)

El texto del guion se convierte en audio mediante uno de 6 motores TTS. El sistema selecciona el provider según la configuración y maneja automáticamente la obtención de timestamps palabra por palabra para sincronizar subtítulos.

app/services/voice.pyPython
def tts(params: VideoParams) -> tuple[str, SubMaker]:
    provider = params.tts_provider
    if provider == "edge":
        return edge_tts_v1(params)
    elif provider == "azure":
        return azure_tts_v2(params)
    elif provider == "siliconflow":
        return siliconflow_tts(params)
    elif provider == "gemini":
        return gemini_tts(params)
    elif provider == "mimo":
        return mimo_tts(params)
    else:
        return no_voice(params)  # silencio + duración estimada
Edge TTS (V1) Gratuito · edge-tts library · 470+ voces
Azure TTS (V2) Pago · SDK Azure Speech · calidad superior
SiliconFlow API REST · modelo CosyVoice2
Gemini TTS gemini-2.5-flash-preview-tts · base64 inline
MiMo TTS Xiaomi · endpoint OpenAI-compatible
No Voice Silencio con FFmpeg anullsrc · duración estimada

Todos los providers devuelven un objeto SubMaker que contiene los timestamps palabra por palabra, esenciales para la generación precisa de subtítulos. Edge TTS los obtiene via eventos WordBoundary; Azure via callbacks del SDK.

📄
4. Generación de subtítulos

Dos providers disponibles: edge (usa los cues de Edge TTS, rápido, sin GPU) y whisper (ejecuta faster-whisper localmente, más preciso pero requiere descarga del modelo ~3GB).

app/services/subtitle.pyPython
def generate_subtitle(audio_path: str, sub_maker: SubMaker,
                       provider: str) -> str:
    if provider == "edge":
        return sub_maker.generate_srt()
    elif provider == "whisper":
        model = WhisperModel("large-v3", device="cuda",
                             compute_type="float16")
        segments, _ = model.transcribe(audio_path)
        return segments_to_srt(segments)

Ambos caminos convergen en una función de corrección post-procesado que alinea los textos del SRT con el guion original usando distancia Levenshtein, asegurando que los subtítulos coincidan exactamente con lo que el LLM generó.

Edge TTS cues faster-whisper (local) Corrección Levenshtein
🎬
5. Descarga de material audiovisual

Para cada término de búsqueda, el sistema consulta 3 APIs de stock video (Pexels, Pixabay, Coverr), descarga los clips de mayor resolución y los almacena en caché con un sistema de deduplicación por hash MD5.

app/services/material.pyPython
def get_video_materials(params: VideoParams) -> list[MaterialInfo]:
    materials = []
    source = params.video_source  # "pexels" | "pixabay" | "coverr" | "local"
    for keyword in params.video_terms:
        api_clips = search_pexels(keyword) if source == "pexels" else ...
        for clip in api_clips:
            hash_key = hashlib.md5(clip.url.encode()).hexdigest()
            if hash_key in seen: continue
            seen.add(hash_key)
            if download_video(clip.url, dest):
                materials.append(MaterialInfo(...))
    return materials
Pexels api.pexels.com/videos/search · API key · filtro orientación
Pixabay pixabay.com/api/videos/ · API key · filtro width
Coverr api.coverr.co/videos · API key · signed URLs
Local Archivos subidos por el usuario en storage/local_videos/

Los clips descargados se validan con MoviePy (duración > 0, FPS > 0). Con match_materials_to_script, los clips se asignan a segmentos específicos del guion en orden cronológico.

6. Composición final del vídeo

La etapa más compleja. MoviePy compone todos los elementos: clips de vídeo, transiciones, subtítulos sincronizados, voz superpuesta y música de fondo. El resultado se codifica con FFmpeg usando el codec configurado.

Proceso interno:
  1. Cada clip fuente se divide en segmentos de max_clip_duration segundos
  2. Se prioriza diversidad: cada clip aparece una vez antes de repetir
  3. Los segmentos se renderizan individualmente con la transición elegida (FadeIn, SlideOut, Shuffle…)
  4. Se concatenan via FFmpeg concat demuxer
  5. Si la duración total < audio, los clips se loopan para llenar
  6. Los subtítulos se renderizan frame a frame como TextClip con wrapping vía PIL
  7. La música de fondo se mezcla con volumen escalado y fadeout
  8. Salida: final-{n}.mp4 + combined-{n}.mp4

Soporta dos relaciones de aspecto: 9:16 (1080×1920, vertical/portrait) y 16:9 (1920×1080, horizontal/landscape). Los clips con relación distinta se centran con barras negras (letterbox). El codec de video se configura vía video_codec (libx264, NVENC, AMF, QSV, VideoToolbox).

MoviePy FFmpeg libx264 NVENC PIL (subtítulos) Transiciones
INTERFAZ

Web Interface (Streamlit)

Una aplicación Streamlit de página única que expone toda la funcionalidad del pipeline en una UI de tres columnas con configuración en vivo y logs en tiempo real.

🖥️
Layout de 3 columnas
Columna Izquierda
Guion · Idioma · Prompt personalizado · Keywords manuales
Columna Central
Proveedor video · Transiciones · Ratio · Duración · TTS · Música
Columna Derecha
Fuente · Color · Posición · Tamaño · Stroke · BG de subtítulos
Panel colapsable inferior
Configuración LLM · API Keys (Pexels/Pixabay/Coverr)

El panel inferior colapsable ("Basic Settings") permite configurar el provider LLM y las API keys de los servicios de stock video sin salir de la interfaz.

🌐
Internacionalización (i18n)

La UI carga textos desde archivos JSON en webui/i18n/. Soporta 8 idiomas: español, inglés, chino, alemán, ruso, vietnamita, turco y portugués. La selección de idioma persiste en la sesión de Streamlit.

en.json zh.json es.json de.json ru.json vi.json tr.json pt.json
📋
Logging en vivo

Durante la generación, Loguru emite logs estructurados que se capturan y muestran en un bloque de código dentro de Streamlit. El usuario ve en tiempo real qué etapa se está ejecutando, qué provider TTS se usó, cuántos clips se descargaron, etc.

CONFIGURACIÓN

Configuración y despliegue

Toda la configuración reside en un archivo TOML con secciones para la aplicación, providers LLM, TTS, stock video y opciones de UI.

⚙️
Estructura del config.toml
config.tomlTOML
# Proveedor LLM principal
llm_provider = "openai"
openai_api_key = "sk-..."
openai_base_url = "https://api.openai.com/v1"
openai_model_name = "gpt-4o-mini"

# Stock video
video_source = "pexels"
pexels_api_keys = ["..."]
pixabay_api_keys = ["..."]
coverr_api_keys = ["..."]

# TTS
tts_provider = "edge"
subtitle_provider = "edge"

# Whisper (local STT)
[whisper]
model_size = "large-v3"
device = "CPU"
compute_type = "int8"
🐳
Modos de despliegue
docker-compose Dos servicios: WebUI (:8501) + API (:8080)
docker-compose.gpu Variante con NVIDIA CUDA para Whisper GPU
Dockerfile.gpu Build desde imagen CUDA base
Directo (Python) uvicorn app.asgi:app + streamlit run webui/Main.py
CLI python cli.py --subject "Tema" para generación headless
Redis Cola de tareas persistente (opcional, enable_redis=true)
STACK

Tecnologías y dependencias

El stack técnico completo del proyecto, con las versiones utilizadas y el rol de cada componente en la arquitectura.

Dependencia Versión Función
Python3.11Runtime principal
FastAPI0.136.3Framework REST API
Uvicorn0.32.1Servidor ASGI
Streamlit1.58.0Interfaz web de usuario
MoviePy2.2.1Composición y edición de vídeo
FFmpegCodificación y concat de video
Pillow (PIL)Medición de texto y wrapping para subtítulos
edge-tts7.2.7Síntesis de voz gratuita (Azure Cognitive Services edge)
faster-whisper1.1.0Speech-to-text local (subtítulos por Whisper)
pydub0.25.1Manipulación de audio (Gemini/MiMo TTS)
openaiSDK para OpenAI y providers compatibles
google-generativeaiSDK para Gemini (LLM + TTS)
LiteLLMGateway unificado para 100+ providers LLM
dashscopeSDK para Qwen (通义千问)
azure-cognitiveservices-speechSDK Azure Speech (TTS V2)
httpxCliente HTTP async para API externas
loguru0.7.3Logging estructurado
tomlParseo de configuración
pydanticValidación de esquemas y datos
redisCola de tareas persistente (opcional)
requests2.33.1HTTP para APIs de stock video
uvGestor de paquetes y entornos
DockerContainerización (CPU + GPU variants)
🔌
Patrones de integración destacados
  • Provider rotator — Las API keys de Pexels/Pixabay se rotan automáticamente si se proporcionan múltiples, distribuyendo la carga.
  • Dual-mode subtitle — Edge TTS para velocidad (sin GPU) vs Whisper para precisión (GPU recomendada). El sistema hace fallback automático.
  • Codec fallback chain — Si el codec HW (NVENC/AMF/QSV) falla, degrada a libx264 automáticamente.
  • Graceful TTS degradation — Si el TTS principal falla tras reintentos, el sistema puede continuar con silencio ("No Voice") en lugar de abortar.