# 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)

```bash
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:

1. 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).
2. 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`).
3. Pass them straight in — the CLI downloads URLs and uses them as the Ken-Burns slideshow:

```bash
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-generator` adapter auto-exposes `generate/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).


---
Source: .claude/skills/youtube-video-generator/SKILL.md
Canonical: https://docs.leumas.tech/p/skills/youtube-video-generator
