Skip to content

About

MPT Autopilot — End-to-end YouTube Shorts automation for MoneyPrinterTurbo

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Python Version License: MIT

MPT Autopilot

End-to-end automation for MoneyPrinterTurbo: generate short-video ideas, render them, tag them, and upload them to YouTube — one repository, one command, one config file.

mpt run

That chains four stages, once per language:

refill  →  batch  →  enrich  →  upload
Stage Command What it does
pilot mpt refill asks an LLM for fresh video ideas and appends them to the jobs queue, deduplicated against everything you've already made
batch mpt batch renders pending jobs through the MoneyPrinterTurbo API, with retries, timeout handling, and cache cleanup
enricher mpt enrich generates platform-appropriate hashtags for each rendered video and writes them into its metadata sidecar
uploader mpt upload uploads to YouTube via youtubeuploader, multi-account, with a crash-safe SQLite ledger

Every stage also runs on its own, so you can adopt as much or as little of the chain as you want.

Coming from the four separate tools? This repository merges shorts-pilot, mpt-batch, hashtag-enricher, and yt-shorts-uploader.

Requirements

  • Python 3.10+ and uv
  • A running MoneyPrinterTurbo instance (for the batch stage)
  • An OpenAI-compatible LLM endpoint — OpenAI, Anthropic, Groq, Together, or a local Ollama / vLLM (for refill and enrich)
  • youtubeuploader and a Google Cloud OAuth client (for the upload stage)

You only need the pieces for the stages you actually use.

Install

git clone https://github.com/korosu/mpt-autopilot.git
cd mpt-autopilot
uv sync

cp config.example.yaml config.yaml
cp .env.example .env
cp jobs/jobs.example.yaml jobs.yaml
cp accounts.example.yaml accounts.yaml     # only for the upload stage

Check the wiring before anything runs for real:

uv run mpt run --dry-run

That loads the config, resolves every language, checks each uploader account, and prints what each stage would do — without rendering a video, calling an LLM, or uploading anything.

Configuration

One config.yaml, one section per stage, plus a shared part every stage reads:

telegram_prefix: "mpt-autopilot"

paths:
  jobs_dir: "./jobs"
  exports_dir: "./exports"

langs:                      # shared: one source of truth for every stage
  en:
    label: English
    file_suffix: ""         # jobs.yaml,    seen.txt,    exports/
  es:
    label: Spanish
    file_suffix: "_es"      # jobs_es.yaml, seen_es.txt, exports_es/

pilot:
  generation:
    count: 21
    threshold: 10

batch:
  api_url: "http://127.0.0.1:8080"
  mpt_storage: "/root/MoneyPrinterTurbo/storage"
  mpt_songs_dir: "/root/MoneyPrinterTurbo/resource/songs"

enricher:
  platform: youtube
  max_tags: 5

uploader:
  uploader_binary: "/root/youtubeuploader/youtubeuploader"

pipeline:
  accounts:
    es: spanish-channel     # only if your account isn't named after the language

config.example.yaml is the annotated version, with every key and its default. Two things about it are worth knowing up front:

  • Every relative path resolves against config.yaml's own directory, never your current one. So cron can run mpt --config /srv/mpt/config.yaml run from anywhere and get identical behaviour.
  • langs: is shared, at the top level. A language's file_suffix derives the jobs file, the seen registry, and the exports directory, which is exactly how the stages hand work to each other with no extra configuration.

Secrets — LLM keys and the optional Telegram bot token — go in .env, never in config.yaml. mpt looks for .env next to config.yaml first, then in the current directory.

Usage

Per stage:

mpt refill --lang en                    # generate ideas via LLM
mpt refill --lang en --topic "Why the Moon has no atmosphere"   # skip the LLM
mpt init-seen --dir /videos/en          # register existing videos so refill won't repeat them

mpt batch --lang en                     # render pending jobs
mpt batch --dry-run                     # preview which jobs would run
mpt batch --status                      # seen-registry stats
mpt batch --list-voices es              # browse the 314 bundled Edge TTS voices

mpt enrich --dir ./exports_en           # generate hashtags
mpt enrich --file clip.mp4 --force      # re-generate for one file
mpt enrich --platform tiktok            # different tag limits and prompt

mpt upload --account en                 # upload one channel
mpt upload --all-accounts --limit 5     # every channel, 5 videos each

The whole chain:

mpt run                                 # every configured language
mpt run --lang en                       # one language
mpt run --only batch --only enrich      # a slice of the pipeline
mpt run --skip upload                   # produce everything, upload later
mpt run --continue-on-error             # don't stop a language on the first failure

--config works before or after the subcommand. Every subcommand has its own --help.

In a browser

uv sync --extra web
mpt web                                 # http://127.0.0.1:8765

One page with a stage button per command in a left sidebar and every flag that stage's parser registers, generated by introspecting the parsers themselves. Logs stream in live, one run at a time, with a Cancel button. Single user on localhost, no authentication — see docs/web.md and Web interface below.

Exit codes

Code Meaning
0 succeeded, or nothing to do
1 failure
2 stopped on YouTube's daily upload quota

A quota stop gets its own code so a scheduled wrapper can tell "try again tomorrow" apart from "something is broken". mpt run aggregates across languages with failure taking precedence over a quota stop.

Scheduling

0 */6 * * * cd /srv/mpt && /usr/local/bin/mpt --config /srv/mpt/config.yaml run >> /srv/mpt/logs/run.log 2>&1

Optional Telegram alerts report each run's outcome — set TELEGRAM_TOKEN and TELEGRAM_CHAT_ID in .env, or leave them empty to disable notifications.

Documentation

docs/pilot.md idea generation, themes, dedup, mpt refill / mpt init-seen
docs/batch.md rendering, jobs.yaml, voices, retries, mpt batch
docs/enricher.md hashtag generation, prompts, platform limits, mpt enrich
docs/uploader.md accounts, sidecars, the ledger, mpt upload
docs/pipeline.md mpt run — stage selection, failure handling, scheduling
docs/web.md mpt web — the local browser interface

Web interface

mpt web puts every stage behind one local page — no command line, no remembering flags. Pick a stage in the sidebar; the page lists every flag that stage's parser registers, generated by introspecting the parser itself, so the form can never drift from the CLI. Press Run and the log streams in live, with a Cancel button.

The mpt web page: stage sidebar, the batch stage's flags, and a streaming log

What is in the screenshot, left to right:

  • Sidebar — one button per stage: refill, init-seen, batch, enrich, upload, run, validate. The highlighted one is open.
  • Fill from config / Reset — the pair in the header writes into every stage's fields the values your config.yaml implies, and clears them again. Press it once, then click through the tabs: each one is already filled. The second pair, inside the form, does the same for the open stage only.
  • Pipeline map — refill → batch → enrich → upload, doubling as navigation.
  • Header dots — the current run's state (idle, running with elapsed time, how the last run ended) and the MoneyPrinterTurbo API: green means its task list answers (the endpoint batch really calls), amber means something else owns that port, red means nothing is listening.
  • Run / Cancel / preview — the preview line shows the exact command that will run before you start it.
  • Settings — the header link opens a page about the MoneyPrinterTurbo side: the exact version behind the port (/openapi.json), whether a local process owns it, and a setup wizard — pick how MPT runs (a local systemd service, Docker, or tmux) and name it, and the page derives the restart and logs commands from the answer (saved in its own web-settings.yaml; hand-written web.mpt_restart_command / web.mpt_logs_command keys still win per command). Buttons to restart MPT and to stream its logs live; for tmux the "stream" is a capture-pane poll showing only the new lines. Cancel is also cleaner now: it signals the run first on POSIX and sweeps the dead child's lock markers on Windows, so a cancelled batch never leaves a seen.txt lock behind to block the next one.

A run in flight: the log streaming line by line, the running dot with elapsed time

A run started in a terminal is listed under the form too, read-only — stage, PID, start time, and the tail of that stage's log file when it provably uses this page's config.yaml. While it lives, the page's Run button is disabled (a line in the log pane says why) and the server refuses to start a second run over it — the two would fight over the same jobs files and ledgers.

Screenshots live in assets/. To add or replace one, see assets/README.md for what each file must show. Full details — every control, the fill rules, the API — are in docs/web.md.

Development

uv sync --extra dev --extra web
uv run ruff check . && uv run ruff format --check . && uv run pyright src && uv run pytest tests/ -v

CI runs exactly that on every push and pull request against main (--extra web because the type check covers the Flask layer and the tests cover mpt web).

The layout mirrors the stages:

src/mpt_autopilot/
  cli.py  pipeline.py  config.py  seen.py  notify.py  lock.py  logger.py
  pilot/  batch/  enricher/  uploader/

The four stage packages never import each other — everything shared goes through the top-level modules.

Commit history from all four original repositories is preserved, so git blame and git log --follow reach back into each file's original project:

git log --follow src/mpt_autopilot/pilot/refill.py

License

MIT

About

MPT Autopilot — End-to-end YouTube Shorts automation for MoneyPrinterTurbo

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages