Fully automated YouTube Shorts pipeline that generates and uploads viral short-form content -- and learns from its own performance to get better over time.
Topic -> Script -> AI Images -> TTS -> Video -> Upload -> Learn -> Repeat
Zero manual steps. Set it on a cron and walk away.
Most "YouTube automation" tools generate a video and call it done. This pipeline closes the loop: it scrapes your channel's actual view counts, identifies what worked and what didn't, and feeds that data back into the next generation prompt. Over time, the content evolves toward what your audience actually watches.
It also fights content repetition with 5 independent diversity systems -- topic rotation, hook sampling, voice rotation, history exclusion, and performance-informed generation -- so your channel never feels like a bot even though it is one.
+------------------+
| cron (3x/day) |
+--------+---------+
|
+--------v---------+
| Scrape YouTube | yt-dlp grabs view counts
| metrics | for all your videos
+--------+---------+
|
+--------v---------+
| Generate topic | LLM picks topic informed by
| (self-improving) | top/bottom performers
+--------+---------+
|
+--------v---------+
| Write script | 3-4 sentences, scroll-stopping
| + hook sampling | hook, diverse patterns
+--------+---------+
|
+-------------+-------------+
| |
+---------v----------+ +----------v---------+
| Generate 7 images | | Text-to-speech |
| (Together.ai FLUX) | | (edge-tts, rotated |
| | | across 11 voices) |
+--------+-----------+ +----------+----------+
| |
+-------------+--------------+
|
+--------v---------+
| Render video | MoviePy: images + audio
| 1080x1920 | + subtitles + background music
+--------+---------+
|
+--------v---------+
| Upload to YouTube | Selenium drives Firefox
| via Studio | headless on server
+--------+---------+
|
+--------v---------+
| Save to history | Track topic/hook/voice
| + clean up files | for future diversity
+-------------------+
| Component | Tool |
|---|---|
| LLM | Ollama (any model -- qwen2.5:3b, llama3, etc.) |
| Image Gen | Together.ai FLUX |
| TTS | edge-tts (11 voices, auto-rotated) |
| Video Render | MoviePy + ImageMagick |
| Subtitles | faster-whisper |
| Upload | Selenium + Firefox (headless) |
| Metrics | yt-dlp |
| Scheduling | cron (or any scheduler) |
Runs on any Linux box. Tested on AWS EC2.
- Python 3.12
- Ollama installed with a model pulled:
curl -fsSL https://ollama.ai/install.sh | sh ollama pull qwen2.5:3b - ImageMagick:
sudo apt install imagemagick # Ubuntu/Debian brew install imagemagick # macOS
- Firefox (for headless upload):
sudo apt install firefox
- Together.ai API key -- sign up at together.ai for image generation
git clone https://github.com/CodeSarthak/autopilot-shorts.git
cd autopilot-shorts
python3.12 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp config.example.json config.jsonEdit config.json with your settings. The critical ones:
{
"firefox_profile": "/path/to/your/firefox/profile",
"headless": true,
"nanobanana2_api_key": "your-together-ai-api-key",
"imagemagick_path": "/usr/bin/convert"
}See docs/Configuration.md for all options.
The upload uses Selenium to drive Firefox, which needs to be logged into YouTube Studio:
- Create a dedicated Firefox profile:
firefox -P(create a new profile) - Open YouTube Studio in that profile and log in
- Copy the profile path (find it at
about:profilesin Firefox) - Set
firefox_profileinconfig.jsonto that path
Create .mp/youtube.json:
[
{
"id": "any-unique-uuid",
"nickname": "MyChannel",
"firefox_profile": "/path/to/firefox/profile",
"niche": "your channel niche (e.g. tech, fitness, finance, history)",
"language": "English"
}
]Drop .mp3 files into the Songs/ directory. One is randomly selected per video. Use royalty-free tracks.
# Single run
venv/bin/python3.12 src/cron.py youtube YOUR_ACCOUNT_UUID qwen2.5:3b
# Automate with cron (3x/day example)
crontab -e0 6 * * * cd /path/to/autopilot-shorts && venv/bin/python3.12 src/cron.py youtube YOUR_UUID qwen2.5:3b >> pipeline.log 2>&1
0 14 * * * cd /path/to/autopilot-shorts && venv/bin/python3.12 src/cron.py youtube YOUR_UUID qwen2.5:3b >> pipeline.log 2>&1
0 22 * * * cd /path/to/autopilot-shorts && venv/bin/python3.12 src/cron.py youtube YOUR_UUID qwen2.5:3b >> pipeline.log 2>&1This is what makes this project different. Before every run:
yt-dlpscrapes view counts for all videos on your channel- The top 3 and bottom 3 performers are identified
- This data is injected into the LLM topic generation prompt:
LEARN FROM PAST PERFORMANCE -- these titles got the MOST views on our channel:
- How One Decision Changed Everything (842 views)
- The Hidden Cost Nobody Talks About (717 views)
These titles got the FEWEST views:
- Topic That Was Too Broad (2 views)
- Generic Title Without a Hook (0 views)
Generate topics that lean toward what performed well.
The LLM learns to generate content similar to what actually gets views. The more videos you publish, the better the signal, the better the content.
Five independent systems prevent your channel from feeling robotic:
| System | How It Works |
|---|---|
| Topic categories | 8 default categories (customize in youtube.json) -- one randomly picked per run |
| Hook patterns | Pool of 15 templates -- 3-4 randomly sampled per prompt |
| Voice rotation | 11 edge-tts voices (male/female, US/UK/AU) -- last 3 excluded |
| History exclusion | Last 10 topics and hooks are excluded from generation |
| Performance feedback | Top/bottom performers steer future topics |
AGPL-3.0. See LICENSE.
Originally forked from MoneyPrinterV2.