Industrial-scale short-form video factory: idea → script → TTS voiceover → stock/AI footage → ffmpeg assembly with subtitles → metadata → publish. Fully automated, config-driven, with a TUI for humans and a CLI for cron.
Русская версия — ниже.
- Python 3.12+
- ffmpeg on your
PATH(the assembly engine) - Internet access (edge-tts, stock/AI APIs, your LLM provider, YouTube)
Install ffmpeg: winget install Gyan.FFmpeg (Windows) · brew install ffmpeg (macOS) · sudo apt install ffmpeg (Debian/Ubuntu) · sudo pacman -S ffmpeg (Arch).
Works on Linux, macOS, and Windows. Create a virtualenv and install:
python -m venv .venv
# Linux/macOS:
source .venv/bin/activate
# Windows (PowerShell):
# .venv\Scripts\Activate.ps1
pip install -r requirements.txt
pip install -e .
cp .env.example .env # fill in your keys (Windows: copy .env.example .env)Nix / NixOS
The repo ships a shell.nix with Python 3.12, ffmpeg, and DejaVu fonts:
nix-shell # creates and activates .venv on first entry
pip install -r requirements.txt && pip install -e ..env keys:
| Key | Needed for | Where to get |
|---|---|---|
DEEPSEEK_API_KEY |
LLM (provider deepseek) |
platform.deepseek.com |
GEMINI_API_KEY |
LLM (provider gemini, has a free tier) |
aistudio.google.com |
OPENROUTER_API_KEY |
LLM (provider openrouter, has :free models) |
openrouter.ai |
PEXELS_API_KEY |
stock footage (primary) | pexels.com/api |
PIXABAY_API_KEY |
stock footage (fallback) | pixabay.com/api/docs |
Only the key for the provider selected in configs/slopgen.toml [llm] (or TUI → Configuration → LLM) is required. Everything else is key-free: edge-tts needs no key, YouTube uses OAuth (a client JSON, not an API key). Footage can stay key-free too via the local provider (assets/footage/).
# interactive: pick everything in the TUI, press START, walk away
slopgen
# headless: a MODE comes first, then its arguments
slopgen info en cyber # minute-of-info clip
slopgen info ru story --ad example_vpn --ad-mode both --push yt_main -n 5
slopgen --preset daily_en # a preset is an info run
# AI drama: a narrated story with a recurring cast + AI-generated shots
slopgen drama ru --scenario "Две подруги ссорятся из-за тайны" \
--cast example --duration-min 2 --tol 20 --parts 3
slopgen drama en --orchestration my_chain --ad example_vpn --dry-run
# generate without publishing (demo assets included)
slopgen info en cyber --ad example_vpn --dry-runSingle-part output lands in output/<timestamp>_<type|mode>_<lang>/<n>/final.mp4 + metadata.json.
Multi-part dramas produce part_01.mp4, part_02.mp4, ... together in that same <n>/ directory.
The first positional argument is the mode: info (the minute-of-info clip) or
drama (the AI web drama). Each mode shapes the rest of the line. Running
slopgen with no mode opens the TUI.
info LANG TYPE [flags]
| Argument / flag | Meaning |
|---|---|
LANG TYPE |
positional: language (en/ru) and content type (story/cyber/psych/facts) |
--idea "..." |
your own topic; omit to let the LLM invent one |
--visuals NAME |
visuals profile from configs/visuals/ (default classic) |
--duration N |
target spoken length in seconds (default 45; >60 is fine, Shorts allow up to 3 min). A hint for the LLM, not a hard cap |
--profanity N |
swearing level in the narration, 0 (clean) … 100 (constant); in the TUI it's a slider on the Content step |
--ad NAME |
ad contract from configs/ads/ |
--ad-mode |
overlay (corner animation + caption), native (spoken mention + ad clip), both |
--push NAME |
account from configs/accounts/; omit → save locally |
-n, --count N |
videos per run |
--preset NAME |
load a parameter bundle from configs/presets/ |
--resume DIR |
continue a crashed run from its output dir (the folder holding checkpoint.json) |
-b, --break STAGE |
stop for review after this stage (repeatable): idea script tts footage subtitles assemble metadata |
--subs |
subtitle style: word_pop / phrases / karaoke |
--tts-rate N |
speech rate offset in percent (-50 … +50); info mode only, drama keeps the natural speed |
--clean-subs |
swap profanity out of the burned-in subtitles; the voiceover keeps every word |
--out DIR |
output dir override |
--dry-run |
generate but don't publish (dev tool; picking "save locally" does the same) |
--keep-temp |
keep intermediate ffmpeg files |
drama LANG [flags] — shares --ad, --ad-mode, --profanity, --push, -n/--count, --subs, --clean-subs, -b/--break, --out, --dry-run, --keep-temp with info, plus:
| Flag | Meaning |
|---|---|
LANG |
positional: narration language (en/ru) |
--scenario "..." |
the plot/premise; omit to let the LLM invent one |
--cast A,B |
comma-separated character names from configs/characters/ |
--orchestration NAME |
AI-generator chain from configs/orchestration/ (default: one wan2.1 stage) |
--duration-min N |
target length in minutes |
--clip-s N |
AVERAGE length of one generated clip in seconds (0 = each generator's own); the writer sizes each beat around it |
--visual-notes "…" |
constraints on what the shots may SHOW, never on the story ("all weapons are toy ones") |
--clean-subs |
swap profanity out of the burned-in subtitles; the voiceover keeps every word |
--tol N |
how many seconds the finished video may run over/under the target |
--parts N |
split one drama into N publishable parts; script cuts are planned as cliffhangers |
--voice ID |
edge-tts narrator voice (default per language) |
Global (before the mode, or standalone): --resume DIR, and the inspectors
--list-types --list-ads --list-accounts --list-presets --list-visuals
--list-characters --list-orchestrations.
Subcommands that reopen a run which parked itself, each straight into the screen
it is waiting on: slopgen gather [DIR] (hand-made clips) and slopgen review [DIR]
(a breakpoint). Omit the directory and the latest such run is found.
Parameter priority (info mode): CLI flags > preset > account defaults > global defaults. An account config can carry its own default language/type/ad, so slopgen info --push yt_main alone is a valid command. Drama builds its parameters directly from its own flags (no preset/account merge yet).
Crash recovery. Every run is checkpointed to <out>/<stamp>_<type>_<lang>/checkpoint.json after each pipeline stage. If a run dies partway (network drop, killed process), the finished stages' outputs (TTS audio, downloaded footage, the job state) are kept, and the failing stage + error are recorded. Re-run with slopgen --resume <that dir> to skip the completed stages and continue from the point of failure — already-finished videos are left untouched, unfinished ones pick up where they stopped. When a run ends with failures, the summary prints the exact --resume command to use.
Breakpoints. Tick any pipeline stage on the wizard's Summary step (or pass --break STAGE, repeatable) and the run parks right after that stage instead of walking on — the checkpoint holds it in a review state, and a review screen shows what the stage produced as a list of editable lines:
| Breakpoint | What you get |
|---|---|
idea |
the chosen topic, before a single line is written |
script |
the script as written — per scene: the spoken line, its shot prompt (or search terms), the cast in frame, the generator and the clip length. The only place to fix a shot before it is generated |
tts |
every voiced fragment with the length that came out; edit a line and 🔊 re-voice it right there (▶ to listen), as many takes as you like — only that line is re-synthesized |
footage |
the shot prompt (drama) or search queries (info) per scene; changed scenes get their footage remade |
subtitles |
the generated .ass files as text, written straight back to disk |
assemble |
the rendered file(s) — inspect-only, watch them before publishing |
metadata |
title, description and tags, right before publish |
The screen is master-detail: the stage's items are cards on the left — + adds one, ▲ ▼ reorder, ✖ drops — and the open card's fields are edited on the right. A drama scene carries its spoken line, its shot prompt, who is in it (added and removed one by one from the run's cast), which generator makes it and how long the clip runs. Fields are editable by hand (except the .ass files, where a wholesale model rewrite would mangle the cue timings), and an AI edit line sits under the list. At the script breakpoint it works on the scene list as a whole and may do anything the instruction asks — rewrite any field, reorder, merge, split, add or drop scenes, recast them, switch generators — carrying each scene's identity along so an untouched one keeps the audio and clip already made for it. Elsewhere it rewrites the free-text lines: describe the change ("shorter", "make scene 3 angrier", "split this beat in two") and the model rewrites the whole set — for script/voiceover it may also change how many fragments there are. Press Continue and the run picks up from there; a breakpoint fires once per video, so a re-run of the stage you just edited won't park again. With -n >1 the videos queue up and are reviewed one after another. Both modes support it. Headless runs print slopgen review <dir> to reopen the parked run (same as slopgen gather for manual clips).
slopgen with no arguments. Custom Minecraft theme, no footer — the top bar holds the RU/EN interface-language toggle, the <- back button and the command Palette.
- Home — centered menu, arrow keys + Enter.
- Generate — first pick a mode (minute-of-info or AI drama), then a step-by-step wizard with a vertical step list on the left. Info: 1) content (language, narrator voice, type, your own idea, profanity and speech-rate sliders), 2) visuals (profile + full overrides: background source/linkage/interval/Ken Burns, foreground inserts; target duration), 3) ads (a saved contract or fully manual fields), 4) publishing (account, count, subtitle style, clean-subtitles switch), 5) summary with the equivalent CLI command, the breakpoint switches and the GENERATE button. Drama adds a Story step (plot + a reorderable cast, edited on the right, with photo→appearance vision and AI cast-fill), puts clip length and visual constraints on Content and a parts field on Publishing, and turns the Visuals step into orchestration (an ordered list of AI generators; see below). Set everything up, press it, walk away.
- Review — where a run parked itself: the breakpoint screen (cards on the left, the open card's fields on the right, an AI edit line under them) or the manual-clip gather screen. Both resume the run when you are done;
slopgen review/slopgen gatheropen them directly. - Progress — while a run works, a bar tracks the stage it is inside: voiced fragments, generated video fragments, assembled scenes and rendered files, each as
done/total, over a per-video queue table and a live log. - Configuration — sections on the left: LLM profiles (profile tabs, per-provider model presets, API-key input auto-saved to
.env, ★ activation), footage/generator keys, the character library, ad contracts, accounts, presets. Entity sections have a tab per existing config file on top plus+ new; forms are prefilled, with 💾 save and 🗑 delete (confirmed). - The chosen color theme persists across runs (
[ui].theme).
A second mode: a narrated web drama — one voiceover narrator tells a story (and may quote characters' lines inline) over AI-generated shots featuring a recurring cast.
-
Cast (
configs/characters/*.toml):name,age,appearance. Before generation each character is compiled once into a token-dense Englishvisual_prompt, which is substituted in place of that character's name wherever the shot description mentions them — names never reach the generator (it cannot map a name to a face, and a foreign name gets rendered as literal text across the frame), and binding the description to the person doing the action keeps two characters in one shot from being blended or swapped (a text-only anchor — free generators won't lock a face perfectly). In the TUI you can build an ad-hoc cast, pull members from the library, upload a photo (vision → appearance), and let the AI fill the whole cast from the premise. -
Orchestration (
configs/orchestration/*.toml): an ordered list of AI generators, each amodel(wan2.1/ltx-video/animatediffvideo,flux/turboimage), akey_mode(rotatekeys on a limit /singlekey then skip), ametric+amount, and an optionalclip_seconds. The pipeline walks the stages in order and each makes its share of the clips:percent= a share of the length budget,seconds/clips= an absolute chunk, and the last stage fills the remainder. Multiple API keys (one per line in.env) are rotated across stages. A stage'sclip_secondsoverrides the run-level average — handy when one stage's clips are longer than the rest (hand-made Kling/Veo shots next to 5-second Space clips). -
Length, parts & sync: authored in minutes + a tolerance in seconds (the story may run a bit over/under). If parts >1, the writer labels scenes by part and places each non-final cut on a cliffhanger. Clip length is authored too (
--clip-s, or the field on the wizard's Content step; 0 = each generator's nominal ~3-5s). It decides how many clips the budget is cut into and how much narration each carries — a 7-minute drama is 84 clips at 5s but 28 at 15s. The length is fixed — the writer never changes it, it only writes to it. What varies is how much story a beat holds: a drawn-out moment is told to run across several consecutive beats rather than being crammed into one, and a fast turn to be compressed into a single beat. Padding a beat with three unrelated actions to fill the time is exactly what reads as monotonous. Whatever the length, a beat is ONE continuous take that moves, never a list of cuts: toldwide shot THEN close-up THEN reaction, real generators read that as a storyboard and open the clip with every shot on screen at once, as a split-screen grid. Every prompt also carries an explicit single-frame clause, because generators reach for that layout unprompted. One beat equals one clip, and the two are fitted to each other in stages, cheapest change first. The voice moves before the picture does, since nobody sees it happen: up to ±25% it absorbs the mismatch alone and the clip plays untouched. Past that the voice sits at its comfortable edge and the picture slows to cover the rest (down to 45% speed — that reads as deliberate slow motion); only when the picture is spent as well is the voice pushed to its hard limit. A 20s line over a 15s clip is voice-only; a 45s one becomes a 1.35× voice over a 0.45× clip, still matching exactly. The other direction is not symmetric: a voice shorter than its clip is left alone and the surplus picture is simply cut off, which costs nothing and shows nothing — retiming there would buy a sluggish voice or a comic clip and still trim afterwards. Loading it all onto the voice is what used to leave the clip short, and a short clip restarted from its beginning mid-scene. Subtitle timings are rescaled to match — audio and video stay locked. A native ad, when enabled, is woven into the plot at the script level rather than bolted on. -
Censorship & framing: two switches that keep a run publishable. Visual constraints (
--visual-notes) bind what the shots may SHOW and nothing else — the story is written as if they did not exist, so "all weapons are toy ones" leaves the gunfight a gunfight and only changes the props; they reach the writer and ride along on every generated prompt. Clean subtitles (--clean-subs) swaps profanity out of the burned-in text while the voiceover keeps every word — platforms moderate what they can read. Whole lines are rewritten, not single words — «Съебал нахуй с моей пары пидорас блять» becomes «Уйдите пожалуйста с моей пары молодой человек», where word-by-word swapping would leave a limping sentence. It catches words that merely look profane, such as the first part of the name «Хуй Сунь Вынь», and since a rewrite changes the word count, the line's span is re-divided among its new words so it still starts and ends with the speech. Cost is bounded: lines are screened by regex first, so a clean video makes no request at all, and only the flagged lines travel (each with its immediate neighbours for context) in a single request per video. Replies are keyed by line number, so a partial one still lands what it returned and only the rest fall back to masking.
Run it from the TUI (Generate → AI drama) or headless: slopgen drama ru --scenario "…" --cast example --duration-min 2 --tol 20 --parts 3 --orchestration my_chain.
The video track is a layered composition, configured per profile:
- Background:
stock_video/stock_photo/local_video/local_photo/ai_photo/ai_video(free keyless generation — Pollinations images, Wan video via HF Spaces). Linkagenarration= the LLM emits a photo/footage query for every ~N seconds of speech, tied to what is being said at that moment (Switzerland → the capital, a couple → a couple, a puppy → a puppy);neutral= random/looping content (e.g. gameplay). Photo backgrounds get Ken Burns motion (none/subtle/strong) and change everyinterval_s. - Foreground: optional framed picture/clip inserts that are event-driven, not on a timer — the LLM decides which spoken phrases deserve an illustration, and each insert appears exactly while that phrase is spoken (timed from edge-tts word timings) and disappears afterwards. You only pick the source, width and position.
Shipped profiles: classic (stock video b-roll, the default), slideshow (narration-synced Ken Burns photos), gameplay (drop your minecraft-parkour/subway-surfers clips into assets/footage/gameplay/, narration photo inserts pop in front). In the TUI wizard the Visuals step prefills from a profile and any edited field turns the run into a custom profile.
Named connections: provider (deepseek/gemini/openrouter/custom), model, base_url, temperature, web_search. The active one is chosen by [llm].profile in slopgen.toml. API keys never live in TOML — they are env variables in .env; the TUI Configuration → LLM section lets you pick model presets per provider, paste the key (saved to .env automatically), toggle web search, activate and delete profiles.
Web search (web_search = true): gives the model a real web_search tool via standard OpenAI function calling. Before writing the script the model calls it, slopgen runs a keyless DuckDuckGo search and feeds the results back, so the narration is grounded in real, verified facts instead of invented names/events. Works on any provider whose model supports tool use (OpenAI, DeepSeek, OpenRouter, Gemini's compat endpoint); a model without tool calling will simply not use it.
Stock-footage API keys (Pexels, Pixabay) can also be pasted in the TUI under Configuration → Footage API keys — they are saved to .env. They're only needed for stock_* visuals; local assets need none.
Everything is hand-editable TOML; a new file in the folder = a new entity, no code changes.
slopgen.toml— global: video size/fps, target duration, subtitle style/font/colors, music volume, active LLM profile, footage provider order, UI language/theme, defaults.content/*.toml— content types: per-language creative briefs (idea_brief,script_brief), edge-ttsvoices,fallback_keywordsfor stock search.ads/*.toml— ad contracts:url, overlay section (assets dir, captiontext,position,start_s,duration_s,width), native section (assets dir,talking_pointsthe LLM weaves into the script), descriptionsnippet({url}is substituted).accounts/*.toml— publishing targets:platform, YouTube OAuth paths/privacy/category, optionaldefaults(lang/type/ad).presets/*.toml— full parameter bundles for one-command runs.characters/*.toml— AI-drama cast members (name,age,appearance, compiledvisual_prompt).orchestration/*.toml— AI-drama generator chains (ordered[[stages]]withmodel/key_mode/key/metric/amount, plus an optional per-stageclip_seconds).visuals/*.toml— visuals profiles: background source/linkage/AI model/interval/motion/continuous, foreground inserts, described below.llm/*.toml— LLM connections (provider,model,key_env,temperature,web_search); the active one is named inslopgen.toml[llm].profile.
Drop files in, reference from configs:
assets/
ads/<contract>/overlay/ # corner animations: .webm (alpha), .gif, .png
ads/<contract>/native/ # pre-made ad video inserts
music/ # background tracks (one is picked at random, mixed at low volume)
fonts/ # extra subtitle fonts (passed to libass via fontsdir)
footage/ # local clips for the "local" footage provider
footage/gameplay/ # background loops for the "gameplay" visuals profile
images/ # local pictures for photo backgrounds / foreground inserts
Bring your own content. assets/music/, assets/footage/, assets/ads/ and the personal configs/ (characters/, ads/*.toml except the example, accounts/) are git-ignored on purpose — drop your own (copyright-cleared) tracks, clips and cast in. The repo ships only neutral templates: configs/characters/example.toml, configs/ads/example_vpn.toml, and a few demo images.
Subtitles default to the DejaVu Sans font. It's preinstalled on most Linux distros; on Windows/macOS either install it or drop any .ttf/.otf into assets/fonts/ and set [subtitles] font in configs/slopgen.toml to its family name.
- Google Cloud Console → create a project → enable YouTube Data API v3.
- OAuth consent screen → add yourself as a test user.
- Create OAuth client ID (Desktop) → download JSON → save as
secrets/client_secret.json. - First
--pushrun opens a browser consent window once; the token is cached per account.
Quota warning: one upload costs 1600 of the 10 000 daily units → ~6 uploads/day per Google Cloud project. Scale = more projects/accounts (that's what per-account configs are for).
- YouTube's inauthentic content policy (July 2025) demonetizes mass-produced templated content. This tool doesn't exempt you from it: invest in per-channel briefs, voices and assets variety.
- TikTok publishing is a stub (
publish/tiktok.py) — no official upload API for regular accounts. - edge-tts is an unofficial use of Microsoft's public endpoint; it can break or be rate-limited at any time.
100% vibe-coded via Claude Code. The author wrote zero lines of code — every function, stage, prompt, and config was generated through conversation with Claude Opus. The ideas, design decisions, and product vision are human; the implementation is AI.
Фабрика коротких видео промышленного масштаба: идея → сценарий → нейроозвучка → футаж → сборка ffmpeg с сабами → метадата → публикация. Полная автоматизация, всё управляется конфигами; TUI для человека, CLI для крона.
Нужны Python 3.12+ и ffmpeg в PATH. Работает на Linux, macOS и Windows.
ffmpeg: winget install Gyan.FFmpeg (Windows) · brew install ffmpeg (macOS) · sudo apt install ffmpeg / sudo pacman -S ffmpeg (Linux).
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\Activate.ps1
pip install -r requirements.txt
pip install -e .
cp .env.example .env # вписать ключи (Windows: copy .env.example .env)Nix / NixOS
В репозитории есть shell.nix (Python 3.12 + ffmpeg + шрифты DejaVu):
nix-shell # при первом входе создаст и активирует .venv
pip install -r requirements.txt && pip install -e .Личное и копирайтное вынесено в .gitignore: assets/music/, assets/footage/, assets/ads/, а также configs/characters/, configs/accounts/ и configs/ads/*.toml (кроме example_vpn.toml). Занеси свои (правомерные) треки, клипы и персонажей сам — в репозитории лежат только нейтральные шаблоны.
Ключи в .env: нейронка — один ключ выбранного провайдера (DEEPSEEK_API_KEY, GEMINI_API_KEY — есть бесплатный тариф, или OPENROUTER_API_KEY — есть :free-модели); сток-футаж — PEXELS_API_KEY / PIXABAY_API_KEY (оба бесплатные). Провайдер выбирается в configs/slopgen.toml [llm] или в TUI → Конфигурация → Нейронка. Больше ключей не нужно: edge-tts без ключа, YouTube — через OAuth. Футаж тоже можно без ключей — через провайдер local (assets/footage/).
slopgen # TUI: настроил → START → отошёл
# headless: сначала РЕЖИМ, потом его аргументы
slopgen info ru story # ролик «минута инфы»
slopgen info ru cyber --idea "Сайт, знавший даты катастроф" # своя тема вместо LLM
slopgen info en facts --visuals slideshow --duration 75 # фото-слайдшоу, ~75 секунд
slopgen info ru story --ad example_vpn --push yt_main -n 5
slopgen --preset daily_en # пресет — это info-прогон
# ИИ-дорама: озвученная история с постоянным кастом + ИИ-кадры
slopgen drama ru --scenario "Две подруги ссорятся из-за тайны" \
--cast example --duration-min 2 --tol 20 --parts 3
slopgen drama en --orchestration my_chain --ad example_vpn --dry-run
slopgen --resume output/<время>_<тип|режим>_<язык> # продолжить оборвавшийся прогонОдиночный результат: output/<время>_<тип|режим>_<язык>/<n>/final.mp4 + metadata.json.
Многочастные дорамы складываются рядом в той же папке <n>/ как part_01.mp4, part_02.mp4, ...
Первый позиционный аргумент — режим: info (ролик-минутка) или drama (ИИ-дорама); он меняет остальную часть команды. Флаги драмы: --scenario, --cast A,B (имена из configs/characters/), --orchestration, --duration-min (минуты), --tol (секунды допуска), --clip-s (СРЕДНЯЯ длина клипа в секундах, 0 = длина самого генератора), --visual-notes (ограничения картинки, не сюжета), --clean-subs (чистить мат в субтитрах), --parts (количество частей с клиффхэнгерами), --voice; плюс общие с info: --ad, --ad-mode, --profanity, --push, -n, --subs, --out, --dry-run, --keep-temp, -b/--break ЭТАП (остановка на разбор после этапа, флаг повторяемый). У info есть свои --tts-rate (скорость речи, ±50%) и --visuals. Глобальные (до режима): --resume, --list-types/-ads/-accounts/-presets/-visuals/-characters/-orchestrations. Подкоманды slopgen gather [папка] и slopgen review [папка] возвращают к застывшему прогону — к ручным клипам и к брейкпоинту соответственно; без папки берётся последний такой прогон.
Восстановление после сбоя. Каждый прогон пишет чекпойнт в output/<время>_<тип>_<язык>/checkpoint.json после каждого этапа конвейера. Если прогон оборвался на ошибке (обрыв сети, убитый процесс), пройденная часть (озвучка, скачанный футаж, состояние задачи) сохраняется, а этап и текст ошибки записываются. Команда slopgen --resume <эта папка> пропустит выполненные этапы и продолжит с места остановки: готовые видео не трогаются, недоделанные досчитываются. Если прогон завершился с ошибками, в итоговой сводке печатается готовая команда --resume.
Брейкпоинты. Отметь любой этап конвейера на шаге «Итог» в визарде (или передай --break ЭТАП, флаг повторяемый) — и прогон встанет сразу после этого этапа: чекпойнт переводится в состояние review, а экран разбора показывает результат этапа списком редактируемых строк:
| Брейкпоинт | Что показывает |
|---|---|
idea |
выбранную тему, ещё до единой написанной строчки |
script |
сценарий как он написан — по сцене: реплика, промпт кадра (или поисковые слова), кто в кадре, нейронка и длина клипа. Единственное место, где кадр правится до генерации |
tts |
каждый озвученный фрагмент с получившейся длительностью; правь строку и 🔊 переозвучивай прямо тут (▶ послушать), хоть до посинения — переозвучивается только она |
footage |
промпт кадра (дорама) или поисковые запросы (инфа) по сценам; изменённым сценам видеоряд соберут заново |
subtitles |
сгенерированные .ass как текст, правки пишутся прямо на диск |
assemble |
готовые файлы — только просмотр, посмотри перед публикацией |
metadata |
заголовок, описание и теги перед самой публикацией |
Экран устроен как мастер-детейл: слева карточки позиций этапа — + добавляет, ▲ ▼ двигают, ✖ удаляет, — справа поля открытой карточки. У сцены дорамы это реплика, промпт кадра, кто в кадре (добавляется и убирается поштучно из каста прогона), какая нейронка её генерирует и сколько длится клип. Поля правятся руками (кроме .ass — переписывание файла нейронкой снесёт тайминги), а под списком — ИИ-строка. На брейкпоинте script она работает со списком сцен целиком и умеет всё, о чём попросишь: переписать любое поле, переставить сцены, склеить, разбить, добавить, убрать, сменить каст и нейронки — сохраняя тождество сцен, так что нетронутая сцена оставляет при себе уже сделанные озвучку и клип. На остальных этапах переписывает текстовые строки: пишешь, что поменять («короче», «третью сцену злее», «разбей этот бит на два»), и модель переписывает весь набор; для сценария и озвучки она может ещё и поменять количество фрагментов. Жмёшь Продолжить — конвейер идёт дальше. Брейкпоинт срабатывает один раз на видео, так что переделка только что отредактированного этапа снова не встанет. При -n >1 видео выстраиваются в очередь и разбираются по одному. Работает в обоих режимах. В headless-прогоне печатается команда slopgen review <папка>, чтобы вернуться к застывшему прогону (по аналогии с slopgen gather для ручных клипов).
Приоритет параметров (режим info): флаги CLI > пресет > дефолты аккаунта > глобальные дефолты. Аккаунт может нести свои дефолты — slopgen info --push yt_main уже валидная команда. Драма собирает параметры прямо из своих флагов (слияния с пресетом/аккаунтом пока нет).
slopgen без аргументов. Тема Minecraft, нижней панели нет — сверху панель с переключателем языка интерфейса RU/EN, кнопкой <- (назад) и Palette.
- Меню — по центру, выбор стрелочками + Enter.
- Генерация — сначала выбор режима (минута инфы или ИИ-дорама), затем пошаговый визард со списком шагов слева. Info: 1) контент (язык, голос диктора, тип, идея, ползунки мата и скорости речи), 2) видеоряд (профиль + переопределения: фон, привязка, интервал, Ken Burns, вставки; длительность), 3) реклама (контракт или вручную), 4) публикация (аккаунт, количество, стиль сабов, переключатель чистых субтитров), 5) итог с CLI-командой, тумблерами брейкпоинтов и кнопкой СГЕНЕРИРОВАТЬ. Дорама добавляет шаг Сюжет (замысел + переставляемый каст, редактирование справа, фото→внешность через vision, ИИ-заполнение каста), кладёт длину клипа и ограничения картинки на Контент, количество частей — в Публикацию, и превращает шаг «Видеоряд» в оркестрацию (упорядоченный список ИИ-генераторов; см. ниже).
- Прогресс — пока идёт прогон, полоса показывает, где он внутри этапа: фрагменты озвучки, сгенерированные видеофрагменты, смонтированные сцены и собранные файлы, каждое как
сделано/всего, над таблицей очереди по роликам и живым логом. - Разбор — туда, где прогон встал: экран брейкпоинта (слева карточки, справа поля открытой, под ними ИИ-строка) либо экран сбора ручных клипов. Оба по завершении продолжают прогон;
slopgen review/slopgen gatherоткрывают их напрямую. - Конфигурация — секции слева: профили нейронок (табы профилей, пресеты моделей, ввод API-ключа с автосохранением в
.env, активация ★), ключи стока и генераторов, библиотека персонажей, рекламные контракты, аккаунты, пресеты. В секциях сущностей сверху табы — по одному на конфиг-файл плюс+ новый; формы предзаполнены, есть 💾 сохранение и 🗑 удаление с подтверждением. - Выбранная тема оформления сохраняется между запусками (
[ui].theme).
Второй режим: озвученная веб-дорама — один закадровый рассказчик ведёт историю (и может цитировать реплики героев внутри повествования) поверх ИИ-кадров с постоянным кастом.
-
Каст (
configs/characters/*.toml):name,age,appearance. Перед генерацией каждый персонаж один раз компилируется в токен-плотный английскийvisual_prompt, который подставляется вместо имени персонажа там, где описание кадра его упоминает: имена до генератора не доходят (он не свяжет имя с лицом, а кириллицу отрисует текстом поперёк кадра), а привязка описания к тому, кто действует, не даёт смешать или перепутать двух персонажей в одном кадре — и внешность держится (это текстовый якорь; бесплатные генераторы не фиксируют лицо идеально). В TUI можно собрать каст ad-hoc, подтянуть из библиотеки, загрузить фото (vision → внешность) и дать ИИ заполнить весь каст по замыслу. -
Оркестрация (
configs/orchestration/*.toml): упорядоченный список ИИ-генераторов —model(wan2.1/ltx-video/animatediff— видео,flux/turbo— картинка),key_mode(rotate— ротация ключей на лимите /single— один ключ, потом пропуск),metric+amountи необязательныйclip_seconds. Конвейер идёт по этапам, каждый делает свою долю клипов:percent— доля бюджета длины,seconds/clips— абсолютный кусок, последний этап добирает остаток. Несколько API-ключей (по одному на строку в.env) ротируются между этапами.clip_secondsэтапа перебивает общее значение прогона — пригодится, когда клипы одного этапа длиннее остальных (ручные кадры из Kling/Veo рядом с пятисекундными клипами Spaces). -
Длина, части и синхрон: задаётся в минутах + допуск в секундах (история может немного выйти за рамки). Если частей больше одной, сценарист размечает сцены по частям и ставит обрывы на клиффхэнгерах. Длина клипа тоже задаётся (
--clip-sили поле на шаге «Контент» в визарде; 0 = номинал генератора, ~3-5с). От неё зависит, на сколько клипов режется бюджет и сколько озвучки достаётся каждому: семиминутная дорама — это 84 клипа по 5с, но всего 28 по 15с. Длина фиксирована — сценарист её не меняет, а только под неё пишет. Варьируется то, сколько сюжета влезает в бит: затяжной момент ему велено растягивать на несколько подряд идущих битов, а не запихивать в один, а быстрый поворот — сжимать в один. Набивать бит тремя несвязанными действиями ради заполнения времени — это и читается монотонно. При любой длине бит остаётся ОДНИМ непрерывным дублем, а не списком склеек: если написатьобщий план THEN крупный план THEN реакция, реальные генераторы читают это как раскадровку и открывают клип сеткой из всех кадров сразу. К каждому промпту дописывается явное «один кадр целиком» — генераторы тянутся к сетке и без просьбы. Один бит равен одному клипу, и подгоняются они ступенями, начиная с самого дешёвого. Голос двигается раньше картинки — его никто не видит: до ±25% он забирает рассогласование целиком, клип идёт нетронутым. Дальше голос встаёт на комфортной границе, а остаток берёт картинка, замедляясь вплоть до 45% скорости (читается как намеренное слоу-мо); и только когда исчерпана и она, голос дожимается до жёсткого предела. Реплика 20с на клипе 15с — только голос; 45с — голос 1.35× поверх клипа 0.45×, и они всё ещё сходятся ровно. Обратная сторона несимметрична: если голос короче клипа, не трогается ничего, а лишний хвост картинки просто обрезается — это не стоит ничего и не видно, а ретайм там купил бы вялый голос или комичный клип и всё равно обрезал бы следом. Раньше всё вешалось на голос, клипа не хватало, и он начинался сначала посреди сцены. Тайминги субтитров пересчитываются — звук и видео синхронны. Нативная реклама вплетается в сюжет на уровне сценария, а не вклеивается отдельно. -
Цензура и кадрирование: два переключателя, чтобы прогон дожил до публикации. Ограничения картинки (
--visual-notes) связывают только то, что показывают, и больше ничего — сюжет пишется так, будто их нет, поэтому «всё оружие игрушечное» оставляет перестрелку перестрелкой и меняет лишь реквизит; они уходят сценаристу и дописываются к каждому промпту. Чистые субтитры (--clean-subs) заменяют мат в вожжённом тексте, оставляя его в озвучке — платформы модерируют то, что могут прочитать. Переписываются целые реплики, а не отдельные слова: «Съебал нахуй с моей пары пидорас блять» → «Уйдите пожалуйста с моей пары молодой человек» — пословная замена оставила бы хромающее предложение. Ловит и слова, которые лишь похожи на мат, вроде первой части имени «Хуй Сунь Вынь», а поскольку переписывание меняет количество слов, интервал реплики заново делится между новыми словами, чтобы она по-прежнему начиналась и кончалась вместе с речью. Расход ограничен: сначала реплики просеиваются регуляркой, поэтому на чистом видео запроса не будет вовсе, а уходят только помеченные (каждая с ближайшими соседями для контекста) одним запросом на видео. Ответ размечен номерами строк, так что частичный ответ доносит то, что вернул, а маскируются лишь остальные.
Запуск из TUI (Генерация → ИИ-дорама) или headless: slopgen drama ru --scenario "…" --cast example --duration-min 2 --tol 20 --parts 3 --orchestration my_chain.
Видеоряд — слоёная композиция, настраивается профилями:
- Фон:
stock_video/stock_photo/local_video/local_photo/ai_photo/ai_video(бесплатная генерация без ключей — картинки Pollinations, видео Wan через HF Spaces). Привязкаnarration— нейронка выдаёт запрос картинки/футажа на каждые ~N секунд речи, привязанный к тому, что произносится в этот момент (Швейцария → столица, пара → пара, щенок → щенок);neutral— случайный/зацикленный контент (например геймплей). Фото-фон получает движение Ken Burns (none/subtle/strong) и меняется каждыеinterval_sсекунд. - Передний план: опциональные вставки-картинки/клипы в рамке — по событию, а не по таймеру: нейронка сама решает, какие произносимые фразы заслуживают иллюстрации, и каждая вставка показывается ровно пока звучит её фраза (тайминг из пословной разметки edge-tts) и исчезает после. Ты задаёшь только источник, ширину и позицию.
Готовые профили: classic (сток-видео, дефолт), slideshow (фото в такт тексту с Ken Burns), gameplay (кинь клипы майнкрафт-паркура/сабвей-сёрфа в assets/footage/gameplay/ — поверх будут выскакивать картинки по тексту). В TUI шаг «Видеоряд» предзаполняется профилем; любое изменённое поле превращает запуск в кастомный профиль.
Именованные подключения: provider (deepseek/gemini/openrouter/custom), model, base_url, temperature, web_search. Активный выбирается через [llm].profile в slopgen.toml. Ключи API никогда не лежат в TOML — только в .env; в TUI (Конфигурация → Профили нейронок) есть пресеты моделей по провайдеру, ввод ключа (сам сохранится в .env), тумблер веб-поиска, активация и удаление профилей.
Веб-поиск (web_search = true): даёт модели настоящий инструмент web_search через стандартный function calling. Перед написанием сценария модель сама его вызывает, слопген выполняет бесключевой поиск DuckDuckGo и возвращает результаты — так озвучка опирается на реальные проверенные факты, а не на выдуманные имена/события. Работает на любом провайдере, чья модель поддерживает tool-use (OpenAI, DeepSeek, OpenRouter, compat-эндпоинт Gemini); модель без tool-calling просто не станет его использовать.
Ключи стоков (Pexels, Pixabay) тоже можно вставить в TUI: Конфигурация → Ключи API футажа — они сохраняются в .env. Нужны только для stock_* видеоряда; локальным ассетам не требуются.
Всё — редактируемый руками TOML; новый файл в папке = новая сущность без кода:
slopgen.toml— глобальный (видео, целевая длительность, сабы, музыка, активный LLM-профиль, порядок провайдеров футажа, язык/тема интерфейса);content/*.toml— типы контента: брифы промптов по языкам, голоса edge-tts, fallback-ключевые слова;ads/*.toml— рекламные контракты: ссылка, секция overlay (ассеты, подпись, позиция, тайминг), секция native (ассеты, talking points для вплетения в озвучку), сниппет для описания;accounts/*.toml— площадки публикации + их дефолты;presets/*.toml— бандлы параметров для запуска одной командой.characters/*.toml— каст ИИ-дорамы (name,age,appearance, компилируемыйvisual_prompt).orchestration/*.toml— цепочки ИИ-генераторов для дорамы (упорядоченные[[stages]]сmodel/key_mode/key/metric/amountи необязательнымclip_secondsна этап).visuals/*.toml— профили видеоряда: источник фона, привязка, ИИ-модель, интервал, движение, непрерывный режим, передние вставки — описаны ниже.llm/*.toml— подключения к нейронкам (provider,model,key_env,temperature,web_search); активное называется вslopgen.toml[llm].profile.
ads/<контракт>/overlay/ — угловые анимации (.webm с альфой, .gif, .png); ads/<контракт>/native/ — готовые рекламные вставки; music/ — фоновые треки (берётся случайный, тихо подмешивается); fonts/ — шрифты сабов; footage/ — локальные клипы для провайдера local; footage/gameplay/ — фоновые лупы для профиля gameplay; images/ — локальные картинки для фото-фона и вставок. Текущие демо-файлы — заглушки для теста, замени их настоящими.
- Google Cloud Console → проект → включить YouTube Data API v3.
- OAuth consent screen → добавить себя в test users.
- Создать OAuth client ID (Desktop) → скачать JSON → положить в
secrets/client_secret.json. - Первый запуск с
--pushодин раз откроет браузер для согласия; токен закэшируется.
Квота: загрузка = 1600 из 10 000 юнитов/день → ~6 загрузок/день на один Google Cloud проект. Масштаб — через несколько проектов/аккаунтов (для этого и есть конфиги аккаунтов).
- Политика YouTube inauthentic content (июль 2025) демонетизирует шаблонный масс-контент. Инструмент от неё не спасает: вкладывайся в разнообразие брифов, голосов и ассетов по каналам.
- Публикация в TikTok — заглушка (официального API нет).
- edge-tts — неофициальное использование публичного эндпоинта Microsoft; может отвалиться в любой момент.
100% навайбкожено через Claude Code. Автор не написал ни одной строчки кода — каждая функция, стадия, промпт и конфиг сгенерированы в диалоге с Claude Opus. Идеи, дизайн-решения и продуктовое видение — человеческие; реализация — ИИ.