The Problem
Creating short-form videos for social media normally requires scripting, sourcing stock footage, recording voiceover, adding subtitles, and mixing background music. MoneyPrinterTurbo collapses that pipeline into a single API call or web UI interaction: give it a topic, and it generates the script, fetches royalty-free video clips, synthesizes speech, burns in subtitles, and composites the final MP4.
What This Does
The project is a FastAPI application (app/asgi.py) with a Streamlit web UI (webui/Main.py). It supports multiple LLM providers (OpenAI, DeepSeek, Gemini, Ollama), several TTS backends, and material search via Pexels/Pixabay. The README documents features like 9:16 and 16:9 output, batch generation, and configurable subtitle styling.
The core pipeline lives in app/services/: llm.py for script generation, material.py for clip sourcing, voice.py for TTS, video.py for FFmpeg composition, and task.py for orchestration. app/models/schema.py defines the API contracts and enums.
How It Is Wired
Execution starts at start in app/services/task.py:248, which reaches 109 functions. The traced path from entry to external effect is start -> generate_script -> [model via llm.generate_script]. A typical run: start calls generate_script (LLM call), then search_videos_pexels/search_videos_pixabay (network), generate_audio (TTS), and combine_videos (FFmpeg subprocess). The system touches 22 functions that read/write files, 17 that call a model, 7 that make outbound network calls, and 2 that run external commands.
The hub is app/config/__init__.py, imported by 16 modules. It holds configuration loading and shared utilities; high churn there has wide blast radius. app/utils/utils.py is the workhorse: 21 functions called from 12 files, including get_response (called from 12 places) and to_json. app/services/state.py owns task state via update_task (called from 8 places) and get_task.
app/services/video.py is the FFmpeg orchestrator, running external commands and handling file I/O. app/controllers/v1/video.py is the API front door, translating HTTP requests into service calls. app/services/llm.py normalizes responses from various providers, so the rest of the app sees a consistent interface.
How To Use It
Setup: The repo has pyproject.toml and requirements.txt. Use uv sync --frozen (there's a uv.lock) or pip install -r requirements.txt. Docker users can use docker-compose.yml or docker-compose.gpu.yml.
Configuration: Copy config.example.toml to config.toml and set your API keys for the LLM provider, TTS service, and material sources.
Running it:
# Local
uv sync --frozen
uv run python main.py
# Docker
docker compose up -d
The web UI launches at http://localhost:8501 (Streamlit). The API docs are at http://localhost:8080/docs.
Real-World Use
A content operation could POST a topic to /api/v1/videos (defined in app/controllers/v1/video.py), poll the task status via get_task, and download the finished MP4. The batch mode in the web UI lets an editor generate 5 variants of the same topic and pick the best one, which is the practical workflow for a channel posting daily.
Code Health & Issues
Static analysis found 17 issues (5 high, 12 medium). The high-severity findings:
- High - Deep nesting x10 -
app/models/schema.py,app/controllers/manager/base_manager.py,app/services/llm.pyhave control flow nested 7 levels deep. Early returns and guard clauses would flatten this. - High - Oversized files x2 -
app/services/voice.pyandwebui/Main.pyeach exceed 1,500 lines. Splitting by responsibility would help. - Medium - Hub module -
app/config/__init__.pyhas 16 dependents; keep it stable. - Medium - Duplicated code - 10 repeated 6-line blocks across 5 files.
- Medium - Broad exception handling x3 -
app/services/video.py,app/utils/utils.py,webui/Main.pyswallow exceptions indiscriminately.
SDLC gaps: no CI/CD pipeline (no .github/workflows), no lockfile for requirements.txt (though uv.lock exists), Dockerfile uses mutable base image python:3.11-slim-bullseye without digest pinning, and the image runs as root. Four font files over 5MB (largest 53.2MB) bloat every clone.
The Bottom Line
This is a functional, well-structured video generation pipeline with a clean API boundary and sensible service separation. The main risks are operational: no CI, oversized files, and a root-running container. It's worth using if you need a working short-video generator and are willing to add CI and container hardening before production.