Turn any YouTube channel into a personalised AI-written news feed.
TubeNews monitors YouTube channels, transcribes new videos via Supadata, and uses Google Gemini AI to write AP-style news stories from the content. Each user gets a personalised feed filtered to the topics they care about, served through a web UI with subscriptions, an inbox, and shareable feed pages.
- Subscribes to YouTube push notifications (WebSub) for configured channels
- Fetches full transcripts (with timestamps) via the Supadata API
- Sends transcripts to Gemini AI with a journalistic prompt focused on your configured topics
- Saves AI-generated news stories as Markdown files
- Serves stories through a web UI; also publishes per-user and per-channel RSS feeds
# Install dependencies (global install — no venv needed)
pip install -r requirements.txt
# Configure
cp TubeNews.json.sample TubeNews.json
# Edit TubeNews.json: add gemini_api_key, supadata_api_key, base_url
# Start the daemon (subscribes to YouTube push, processes new videos continuously)
python3 TubeNews.py
# Start the web UI (in a separate terminal)
./serve.sh
# Open http://your-server:8000First time on a channel with existing videos? Run python3 helpers/catchup.py before starting the daemon to avoid reprocessing the entire backlog.
See SERVING.md for production deployment (gunicorn, HTTPS, reverse proxy).
- Python 3.10+
- Supadata API key — for transcript extraction
- Google Gemini API key — for AI story generation
- A public HTTPS URL (for WebSub push notifications from YouTube)
cp TubeNews.json.sample TubeNews.jsonKey fields in TubeNews.json:
{
"gemini_api_key": "YOUR_GEMINI_KEY",
"gemini_model": "gemini-2.5-flash",
"supadata_api_key": "YOUR_SUPADATA_KEY",
"base_url": "https://yourdomain.com",
"websub_callback_url": "https://yourdomain.com/youtube/push",
"websub_secret": "generate-with-python3-secrets-token-hex-32",
"tubenews_key": "generate-with-python3-secrets-token-hex-32"
}Channel configuration lives in state/channels.json and is managed via the web UI admin panel. See TubeNews.json.sample for all available options including ntfy notifications, email digests (via Resend), and daemon tuning.
# Daemon mode (default): subscribes to YouTube WebSub, processes pushes continuously
python3 TubeNews.py
# Single-run mode: process all channels once and exit (good for cron)
python3 TubeNews.py --single-run
# Add --debug for verbose logging
python3 TubeNews.py --debug
# Web UI (always use serve.sh, never python3 web/app.py)
./serve.shMost TubeNews.json settings are hot-reloaded each processor cycle — no restart needed for API key or tuning changes.
content/
├── <channel_slug>/
│ ├── <video_id>/
│ │ ├── transcript.txt # Supadata transcript
│ │ ├── metadata.json # Processing status + focus history
│ │ ├── 01_Story_Title.md
│ │ └── 02_Another_Story.md
│ └── rss.xml # Per-channel RSS feed
└── rss.xml # Aggregate feed (all channels)
state/
├── channels.json # Channel list
├── queue/push_queue.json # WebSub incoming video queue
├── run_logs/ # Daemon log + per-run summaries
└── users/
├── index.json # email→UUID index
└── <uuid>/
└── user.json # Account, subscriptions, prefs, digest state
- User accounts — register, log in, manage subscriptions and display preferences
- Personal feed — inbox (unread), read, starred, and all-stories tabs
- Per-channel topic focus — up to 3 focus lines per subscription filter AI output
- Shareable feed page — public
/feed/<token>.htmland RSS at/feed/<token>.xml - Daily email digest — opt-in morning digest via Resend (requires
resend_api_keyin config) - Admin panel — manage channels, users, view run history, trigger manual runs
| File | Contents |
|---|---|
CLAUDE.md |
Developer quick reference (architecture, conventions, testing policy) |
DEVREF.md |
Full developer reference (function signatures, schemas, route map) |
SERVING.md |
Production deployment guide |
TODO.md |
Known issues and completed work |
helpers/ |
Utility scripts: catchup.py, reset_password.py, check_quota.py |
BSD 2-Clause. See LICENSE.