CodeVetter · Repo Unpack · System map
harry0703/MoneyPrinterTurbo
The system is a single-process Python app with three entrypoints that share one orchestration layer. main.py starts uvicorn serving the FastAPI app built in app/asgi.py; webui.sh/webui.bat/Dockerfile start `streamlit run webui/Main.py`; cli.py runs the pipeline synchronously and prints JSON. All routes under /api/v1 are registered in app/router.py and guarded by an optional x-api-key check. Task state lives in an in-memory dict or Redis depending on config, task scheduling in a bounded thread-backed queue, and artifacts on disk under storage/tasks/<task_id>. Deployment is a single Docker image exposing either the WebUI (8501) or API (8080).
- main.py is the API entrypoint: it calls uvicorn.run(app='app.asgi:app', host=config.listen_host, port=config.listen_port) with defaults 0.0.0.0:8080 from config.toml.
- app/asgi.py get_application() builds the FastAPI instance, includes root_api_router, registers HttpException and RequestValidationError handlers, mounts StaticFiles at /tasks (storage/tasks) and / (resource/public), and installs middleware that requires verify_token for /tasks/* and rejects untrusted browser Origins.
- app/router.py aggregates three routers: ping (/ping health check) plus the v1 video and llm controllers; app/controllers/v1/base.py new_router() stamps prefix '/api/v1' and attaches the verify_token dependency to every route.
- webui/Main.py is an ~8,262-line Streamlit application that inserts the repo root into sys.path, loads i18n JSON locales, and submits generation through app/services/webui_task.py; webui.sh picks an interpreter (.venv → uv → PATH streamlit) and scans ports 8501-8599 for a free one.
- cli.py is a third entrypoint exposing every pipeline parameter as argparse flags, a --stop-at stage selector over ('script','terms','audio','subtitle','materials','video'), and a --batch-file mode accepting a JSON array or JSONL manifest capped at 100 tasks / 1 MiB.
- app/services/task.py is the single shared pipeline: start() wraps _run_pipeline(), which all three frontends call, and converts unexpected exceptions into failed task states via _mark_task_failed.
- app/config/config.py loads config.toml (auto-copied from config.example.toml on first run, with a UTF-8 BOM retry path), exposes section dicts wrapped in _SynchronizedConfig, and serializes saves through a reentrant lock plus mkstemp+os.replace atomic writes with an EBUSY fallback for bind-mounted files.
- Task state is pluggable: app/services/state.py picks MemoryState (dict + RLock) or RedisState (per-task Redis hashes, SCAN-paginated listing, Lua-scripted patch_task) based on config.app.enable_redis.
- Task scheduling is pluggable: InMemoryTaskManager uses a bounded queue.Queue while RedisTaskManager pushes JSON jobs onto a Redis list 'task_queue' and maps function names through FUNC_MAP on dequeue; both enforce max_concurrent_tasks (default 5) and max_queued_tasks (default 100) with TaskQueueFullError → HTTP 429.
- Docker packaging is a single python:3.11-slim-bullseye image that apt-installs git+ffmpeg (with Chinese-mirror fallback logic), pip-installs requirements.txt, and by default runs the Streamlit WebUI; docker-compose.yml runs two containers (webui on 127.0.0.1:8501, api on 127.0.0.1:8080) sharing the repo as a volume.
- Filesystem layout is rooted at the repo: utils.storage_dir()/task_dir() create storage/{tasks,cache_videos,local_videos,bgm} on demand, while resource/{fonts,songs,public} hold shipped assets; task artifacts are per-task subdirectories.
- Dependencies are declared in pyproject.toml (moviepy 2.2.1, streamlit 1.59.1, fastapi 0.136.3, edge-tts 7.2.7, faster-whisper, redis, litellm, google-genai, etc.) pinned by uv.lock; requirements.txt duplicates the list 'for legacy pip install support' and the project is configured package=false (not installable).
- docs/skill/SKILL.md + docs/skill/mpt_agent.py ship an agent-facing 'Skill': mpt_agent.py downloads/installs the project under ~/MoneyPrinterTurbo, prompts for missing credentials via exit code 10, and invokes cli.py — making the repo itself an installable tool for external AI agents.