---
title: "Faceless stock-footage short — topic to TikTok in seconds"
tier: standard
format: short-form-video
theme: faceless | informational | listicle | social
persona: creator, marketer, educator, social-media
duration: a topic → a captioned vertical short with voiceover + music, in ~30–60s of wall-clock
budget_usd: ~$0.05–0.20 (TTS + music; stock fetch + ffmpeg are free)
caps: ["stock-footage-fetch", "gemini-text", "gemini-tts", "inworld-tts", "ffmpeg-burn-subtitles", "ffmpeg-concat", "music"]
skills: ["short-form-video", "finishing-quality", "playbook-runtime"]
reliability: 4.8 # 5 − tts .2 − music .2 + proven-pattern .2; NO i2v stage = no hang/drift; stock fetch + ffmpeg are deterministic
---

# Faceless stock-footage short

The fastest, most reliable short-form format on the network: a topic becomes a captioned vertical
reel built entirely from **real pre-shot stock footage** (Pexels/Pixabay) — no AI video generation,
so **nothing hangs and nothing drifts**. Perfect for "5 facts about…", money-tips, news explainers,
listicles, and any faceless b-roll-over-voiceover format.

Why this beats an AI-generated reel for this genre: the shots are generic by design ("city skyline",
"person counting money", "ocean waves"), so a real stock clip matches the script as well as an AI clip
would — but returns in ~1–2s instead of a 60–300s i2v job that might time out on fal. Five scenes that
would be five i2v gambles become five instant lookups.

## When to use — and when not to

| Use stock-footage shorts | Use AI generation instead |
|---|---|
| Generic, evocative b-roll ("rain on a window", "busy market", "stock charts") | A specific recognizable character / your product / your brand |
| Faceless informational / listicle / news / money / motivation | Story with a consistent protagonist across shots |
| You need it FAST and reliably, zero timeout risk | The exact composition matters and only generation can produce it |
| Cost-sensitive (stock fetch is free) | — |

For the best of both, see the **hybrid** variant below.

## How the agent should run this (interaction contract)

1. **CONFIRM (one message, ≤1 question):** restate in 1 line ("a ~40s faceless vertical short on
   <topic>, stock b-roll + voiceover + music, ~$0.10, ready in under a minute") + the choices that
   matter: length (30/45/60s → scene count), a theme-fit voice + tune (name the gemini-tts voice and
   tone you'll use — e.g. warm-mentor `Kore`, serene `Charon` — never the default), captions on/off. Assume
   9:16 + on-screen captions unless told otherwise; start.
2. **PREVIEW CHECKPOINT (cheap, shown first):** post the **script + the chosen stock clips** (the fetched
   URLs / thumbnails) BEFORE rendering voiceover + assembling — "here are the 5 clips + the VO script,
   reply 'go' or swap a clip / line." This is instant and free; never assemble before showing it.
3. **NARRATE:** one line per phase — "script ✓ → fetched 5/5 clips (Pexels) ✓ → voiceover ~8s →
   captions → stitching." Stock fetch + ffmpeg are seconds; only TTS/music are worth a wait note.
4. **FAIL GRACEFULLY:** a keyword returns no clip → broaden it once ("aerial city night" → "city at
   night"), then try Pixabay (automatic), then drop that beat or substitute an adjacent clip — never
   stall. TTS voice off → retry once with `inworld-tts`. Music fails → retry once, else ship without a
   bed and say so. ≤2 retries per step; partial (4/5 scenes) beats nothing.
5. **DELIVER:** the finished 9:16 MP4 + one honest line ("all footage is real licensed stock —
   attribution listed; generic b-roll, not bespoke") + ONE next step ("want a hybrid version with one
   AI hero shot, or a 16:9 cut?").

## The recipe

```
topic ─→ gemini-text (script + per-scene KEYWORDS) ─→ stock-footage-fetch ×N (real clips)
      ─→ gemini-tts (voiceover — pick voice + tune to fit the theme) ─→ ffmpeg-burn-subtitles ─→ ffmpeg-concat ─→ music (bed) ─→ 9:16 MP4
```

1. **Script + keywords (`gemini-text`).** Break the topic into 5–7 beats. For EACH beat write (a) one
   VO sentence and (b) 2–4 **visual search keywords** (concrete nouns a stock library has: "person
   counting cash", "city skyline dusk", "laptop typing close-up"). Keywords ≠ the VO line — they
   describe the footage.
2. **Fetch the b-roll (`stock-footage-fetch`).** One call per beat:
   `create_media({ model_override:"stock-footage-fetch", prompt:"<keywords>", aspect_ratio:"9:16" })`.
   Returns the top-ranked clip as `url` plus a ranked `clips[]` list — pick an alternate if the top one
   doesn't fit. Or, in `generate_project`, set the scene's `source:"stock"` and the prompt becomes the
   keywords automatically.
3. **Voiceover (`gemini-tts` — NEVER the default voice).** This is where most reels fall flat: the
   default TTS voice rarely fits the theme. Always set BOTH a named voice AND a tone directive.
   - `gemini-tts` takes `voice_name` (e.g. `Kore`, `Charon`, `Aoede`, `Puck`, `Fenrir`, `Zephyr`) AND
     honors a delivery instruction prefixed to the prompt — `"Read this in a <tone> tone: <line>"` —
     which it interprets as direction, NOT spoken text (verified live). So you control *who* speaks
     and *how*. `inworld-tts` is the alternative (named expressive voices: Celeste, Liam, Hank…).
   - **Match voice + tune to the theme**, e.g. money/wellness → a warm, calm, trustworthy mentor
     (`Kore`); premium/aspirational → a serene, unhurried voice (`Charon`); breaking-news → crisp and
     urgent; kids → bright and playful. State the chosen voice + tone in the CONFIRM step.
   - One track for the whole script, or per-beat for tight caption sync.
4. **Captions (`ffmpeg-burn-subtitles`).** Burn the VO as on-screen captions — faceless shorts live or
   die on captions (most viewers watch muted).
5. **Stitch + bed (`ffmpeg-concat` + `music`).** Trim each clip to its beat's VO length, concat in order,
   lay an instrumental `music` bed under the VO (duck the music ~-12dB). Loop/`-shortest` so audio
   covers the full video. Final ffprobe gate: video ≈ audio duration (±1.5s), 1080×1920.

## Cap quirks that bite (from live runs)

- **stock-footage-fetch** needs `prompt` = the search keywords (not the VO line). Broaden if a query
  returns nothing; it auto-falls-back Pexels→Pixabay. Requires `PEXELS_API_KEY` in server env.
- Stock clips vary in length — always trim to the beat. They're real footage, so **no motion gate
  needed** (it already moves).
- Attribution: every clip carries a provider attribution string — include it in the deliverable notes.

## What can disappoint (cap ceilings)

Stock footage is **generic**, not bespoke — it won't show your specific person/product, and the "match"
to the script is approximate. For brand/character work, use AI generation or the hybrid variant. Stock
libraries are thinner on niche/abstract topics — very specific keywords may return nothing.

## Cross-surface

MCP (`create_media` / `generate_project source:"stock"`), CLI, and webapp all reach the cap by name.
