AI-powered YouTube Shorts generator — script, TTS, visuals, assemble, upload
Project description
utube
AI-powered YouTube Shorts generator. Give it a topic — it writes the script, synthesizes narration, fetches stock visuals, assembles the video, and uploads it to YouTube. Supports Vietnamese-language content via VBee TTS.
How it works
topic → script (LLM) → assets (TTS + visuals) → assemble → upload
| Step | What happens | Providers |
|---|---|---|
| script | LLM generates title, scenes, narration, tags | Anthropic, OpenAI-compatible |
| assets | TTS audio + stock visual fetched per scene | OpenAI TTS, ElevenLabs, VBee |
| assemble | MoviePy builds the final MP4 + thumbnail | — |
| upload | Uploads to YouTube with title, description, tags | YouTube Data API v3 |
Each step is independently resumable — a failed or interrupted job can be continued from where it left off.
Examples
Videos generated with this tool:
Requirements
- Python 3.12+
- uv — dependency manager
- FFmpeg — required by MoviePy for video encoding
Installation
git clone https://github.com/your-org/utube.git
cd utube
uv sync
Configuration
cp .env.example .env
# Edit .env with your API keys
Minimum required keys
| Variable | Description |
|---|---|
LLM_PROVIDER |
anthropic or openai (default: openai) |
ANTHROPIC_API_KEY |
Required if LLM_PROVIDER=anthropic |
OPENAI_API_KEY |
Required if LLM_PROVIDER=openai |
TTS_PROVIDER |
openai, elevenlabs, or vbee |
PEXELS_API_KEY |
Stock video/photo visuals (free tier works) |
See .env.example for the full variable reference.
Usage
Run end-to-end
uv run utube run --niche "5 mind-blowing facts about black holes"
Runs all four steps and uploads as private by default.
Common flags
| Flag | Description |
|---|---|
--visibility |
private (default), unlisted, or public |
--public |
Shorthand for --visibility public |
--no-auto |
Stop after script — review before continuing |
--audio-speed X |
Narration speed multiplier (e.g. 1.2 for faster) |
--caption |
Overlay on-screen text captions on each scene |
Resume or restart a job
uv run utube continue <job_id> # advance one step
uv run utube continue <job_id> --from assets # restart from assets step
uv run utube status <job_id> # inspect current state
Restart targets: script, assets, assemble, upload.
YouTube auth (first time)
uv run utube auth # opens browser, caches token
uv run utube whoami # verify the connected channel
Place your Google OAuth client secret at secrets/client_secret.json before
running auth. See the YouTube Data API docs
for how to create OAuth credentials.
Job files
Each run creates a directory under ./jobs/<job_id>/ containing all
intermediate files: script JSON, per-scene MP3s, visuals, final MP4, and
thumbnail.
Vietnamese content with VBee
VBee is a Vietnamese AI TTS platform with high-quality voices. Set it as your TTS provider to generate Vietnamese-language Shorts.
TTS_PROVIDER=vbee
VBEE_API_TOKEN=your_token
VBEE_APP_ID=your_app_id
VBEE_VOICE_CODE=hn_female_ngochuyen_full_48k-fhg # default
VBEE_WEBHOOK_URL=https://your-server.com/vbee/callback
VBEE_SPEED=1.0
VBee uses an async batch API — the tool submits the synthesis job and polls
the webhook URL for the result. VBEE_WEBHOOK_URL must be a publicly
reachable HTTPS endpoint that VBee can POST the audio back to.
Extending
utube uses a provider registry pattern. Adding a new TTS, visuals, or LLM provider requires only a new file — no edits to existing pipeline code.
Example: add a TTS provider
# src/utube/providers/tts/mytts.py
from utube.providers.registry import register_tts
from utube.providers.base import TTSProvider
@register_tts("mytts")
class MyTTS:
async def synthesize(self, text: str, voice: str) -> bytes:
... # return raw audio bytes
Then set TTS_PROVIDER=mytts in .env. The same pattern applies to:
- LLM / script providers — implement
ScriptProvider, register with@register_script - Visuals providers — implement
VisualProvider, register with@register_visual
See src/utube/providers/base.py for the Protocol definitions.
Development
uv run pytest # run all tests
uv run ruff check src tests # lint
uv run mypy src # type-check
Tests never hit the network — all HTTP and external clients are mocked. New provider implementations should follow the same pattern.
Contributing
Pull requests are welcome. For significant changes, open an issue first to discuss the approach.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file utube_shorts-0.1.0.tar.gz.
File metadata
- Download URL: utube_shorts-0.1.0.tar.gz
- Upload date:
- Size: 111.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
75f0cbd2c5ca6c2348946ac52225eaaea5e6f5c7a626b2cbe957f190f029aaaf
|
|
| MD5 |
2547114c1058b53095c1c197bb655504
|
|
| BLAKE2b-256 |
9dd83f2de2b85778bdd1b840288360a530e00a55b961acaf07d8046834873d88
|
Provenance
The following attestation bundles were made for utube_shorts-0.1.0.tar.gz:
Publisher:
python-publish.yml on viet-dinh/utube
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
utube_shorts-0.1.0.tar.gz -
Subject digest:
75f0cbd2c5ca6c2348946ac52225eaaea5e6f5c7a626b2cbe957f190f029aaaf - Sigstore transparency entry: 1878311511
- Sigstore integration time:
-
Permalink:
viet-dinh/utube@09cde288f51c8ece3bf3271ebb4df401cb61212c -
Branch / Tag:
refs/tags/0.0.2 - Owner: https://github.com/viet-dinh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@09cde288f51c8ece3bf3271ebb4df401cb61212c -
Trigger Event:
release
-
Statement type:
File details
Details for the file utube_shorts-0.1.0-py3-none-any.whl.
File metadata
- Download URL: utube_shorts-0.1.0-py3-none-any.whl
- Upload date:
- Size: 29.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6b0ae4573b05a0965390c47da0b7b3c485052552a7dfeb884569d1a889c08323
|
|
| MD5 |
c90a3b7e911776fe36dfb99671174dc1
|
|
| BLAKE2b-256 |
91c079fd5c28254618adeb2fd1470f86d89ed3c9d9723c72a8f1d3155fef2c44
|
Provenance
The following attestation bundles were made for utube_shorts-0.1.0-py3-none-any.whl:
Publisher:
python-publish.yml on viet-dinh/utube
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
utube_shorts-0.1.0-py3-none-any.whl -
Subject digest:
6b0ae4573b05a0965390c47da0b7b3c485052552a7dfeb884569d1a889c08323 - Sigstore transparency entry: 1878311647
- Sigstore integration time:
-
Permalink:
viet-dinh/utube@09cde288f51c8ece3bf3271ebb4df401cb61212c -
Branch / Tag:
refs/tags/0.0.2 - Owner: https://github.com/viet-dinh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@09cde288f51c8ece3bf3271ebb4df401cb61212c -
Trigger Event:
release
-
Statement type: