Youtube Video Generator
Generate a publish-ready YouTube video or short from a topic — script, voice, captions, visuals, thumbnail and SEO — in one headless command.
YouTube Video Generator — how to actually run it
A full AI video generator in Leumas. The fastest way for an agent to produce a video is the headless CLI (no dev server, no login). It picks up your env API keys automatically and always renders even with no keys (real free stock photos as the default background — topic-relevant CC0/Pexels/Pixabay media — falling back to procedural "aurora" gradients + offline voice + a calm heuristic script).
Run it (primary path)
node ops/tools/yt-generate/index.mjs --type fall-asleep --topic "a quiet walk through a snowfall at midnight"
Prints a JSON result to stdout: { ok, videoPath, thumbPath, srtPath, durationSec, aspect, visualMode, voiceProvider, seo, renderSeconds }. videoPath is the finished MP4. Progress prints to stderr.
| flag | meaning | |||
|---|---|---|---|---|
--type <id> | video type (default fall-asleep). See --list. | |||
--topic "<idea>" | required — the idea/description to generate from. | |||
--minutes <n> | target length (fractional ok, e.g. 0.5 = 30s). Per-type default otherwise. | |||
--voice <p> | openai \ | elevenlabs \ | say \ | auto. |
--background <b> | auto (AI stills if keyed → free stock photos → gradient) · stock (force real free photos) · a theme: aurora·vivid·ocean·ember·gold·slate. | |||
--captions <c> | calm·reddit-bold·boxed·auto. | |||
--images <list> | comma-separated local paths OR http(s) URLs → used as the video's visuals (see MCP below). | |||
--out <dir> | output directory (default a temp dir; the path is printed). | |||
--list | print the available generators, backgrounds, caption styles, and voices as JSON. |
node ops/tools/yt-generate/index.mjs --list first if you're unsure of the ids.
The 6 types
| id | aspect | what it is |
|---|---|---|
fall-asleep | 16:9 | calm slow narration over soothing visuals — a sleep video |
trending-shorts | 9:16 | punchy vertical Short, fast hook, bold centered captions |
listicle-top10 | 16:9 | narrated Top-10 countdown |
reddit-story | 9:16 | first-person "story time" narration |
quote-motivation | 9:16 | short motivational quote video |
news-explainer | 16:9 | clear, neutral topic explainer |
Premium AI visuals via a connected MCP (e.g. Higgsfield)
The generator handles script/voice/captions/compose; give it great b-roll. If a media MCP is connected in this session (Higgsfield exposes mcp__higgsfield__generate_image / generate_video / models_explore / reframe), do this:
- Decide 3–6 scene prompts from the topic (concrete, no on-screen text). Match the type's aspect
(16:9 or 9:16 — use reframe or the model's size params).
- Generate the images with the MCP (
generate_image;models_explore(action:'recommend')if unsure
which model). Collect the resulting image URLs (from the tool result / show_generations / reveal_generation).
- Pass them straight in — the CLI downloads URLs and uses them as the Ken-Burns slideshow:
node ops/tools/yt-generate/index.mjs --type listicle-top10 --topic "most beautiful islands" \
--images "https://…/img1.png,https://…/img2.png,https://…/img3.png"
visualMode in the result will be supplied. (Higgsfield's tools are agent-only — not callable from the server — so --images is the bridge that gets their output into the render.) For a fully Higgsfield-produced clip you could also just generate_video and skip this generator; use the generator when you want narration + captions + SEO wrapped around AI stills.
Keys (optional — better output)
Set in the API env (products/leumas-api/.env) or the shell:
OPENAI_API_KEY/ELEVENLABS_API_KEY→ LLM script + SEO + a natural voice (auto-selected).STABILITY_API_KEY/OPENAI_API_KEY→ AI still backgrounds when you don't pass--images.PEXELS_API_KEY/PIXABAY_API_KEY(both free) → higher-res stock photos; without them the generator
still pulls free CC0 photos from Openverse (no key), so real topic-relevant media is the baseline. Without any keys it still renders well (real free stock photos → gradient fallback, offline voice, heuristic script).
In the app (Studio) — when the server is running
- UI:
/admin/yt-studio— Generators · Jobs (durable; leave & come back) · Channels (connect
YouTube via OAuth) · Planner (calendar: daily/multi-daily schedules + approval gate).
- HTTP:
POST /api/yt-studio/generate { type, topic, minutes?, voice?, background?, captionStyle? }
→ a durable job; poll GET /api/yt-studio/jobs/:id.
- MCP / functioncall: the
yt-generatoradapter auto-exposesgenerate/status/list/listGenerators
on the Leumas MCP gateway (/mcp) and as chatbot functioncalls — for agents talking to the running Leumas API rather than the repo.
- Schedule: `POST /api/planner/plans { kind:'yt-render', cadence:{ cron:'0 21 *' }, spec:{ type,
topics:[…], channelId }, autoApprove }` — the calendar Planner tab is the UI for this.
Publish / upload
The CLI produces the file; it doesn't upload (no auth). To publish: connect a channel in the Studio Channels tab (needs a Google Cloud OAuth client → MUSIC_YT_CLIENT_ID/SECRET/REDIRECT_URI), then upload from the Jobs tab or POST /api/yt-studio/jobs/:id/upload { channelId }.
Pair with leumas-capabilities (what exists / how it's wired) and expose-as-mcp (distribute + price).