Skip to content
Back to skills

Story Video

BSecurity

Create narrated faceless story videos (mystery, drama, true-crime style fiction) with characters that keep the same face in every scene. Writes the script, generates character/location/prop reference sheets and 40+ scene images, records the voiceover (Vbee or ElevenLabs), and renders a vertical video with Ken Burns motion, CapCut-style punch/shake/glitch, word-by-word captions, suspect/clue cards and a countdown — via Remotion. Use when the user asks for a story video, a narrated illustrated ...

  • 5 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 7, 2026
ai-agentspythonrustgobashnodegitapi

Works with

  • claude code
  • cli
  • api

Security analysis

B84/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 16 files and shows the line behind each finding

Scanned November 7, 2026

npx -y skills add Wanfeng1028/muse --skill story-video --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Story Video?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Story Video
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/wanfeng1028-story-video/badge)](https://www.skillsdirectory.com/skills/wanfeng1028-story-video)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: story-video
description: Create narrated faceless story videos (mystery, drama, true-crime style fiction) with characters that keep the same face in every scene. Writes the script, generates character/location/prop reference sheets and 40+ scene images, records the voiceover (Vbee or ElevenLabs), and renders a vertical video with Ken Burns motion, CapCut-style punch/shake/glitch, word-by-word captions, suspect/clue cards and a countdown — via Remotion. Use when the user asks for a story video, a narrated illustrated video, a mystery/detective episode or a series with recurring characters.
---

# Story video

Turns an idea into a 3–5 minute vertical (9:16) narrated video built from AI illustrations.
Everything lives in a **project folder** with one `story.json`; scripts read it and write next to it.

```
my-episode/
  story.json        ← you write this (script + cast + scenes)
  assets/           ← sheets + scene images (+ manifest.json)
  audio/            ← one voice clip per line (+ manifest.json)
  render/           ← timeline.json, audio.wav, resized frames
  out/my-episode.mp4
```

## 0. First run: set yourself up (once)

Users often just say *"clone https://github.com/huynhcongdac/story-video-skill and make me a video about …"*.
If you were cloned like that, do the whole setup yourself before writing anything:

1. **Install where your agent finds skills** (if you are not already there), so later sessions pick it up:
   Claude Code `~/.claude/skills/story-video` · Codex `~/.agents/skills/story-video` ·
   Antigravity `~/.gemini/antigravity/skills/story-video`. Any other agent: keep the clone and work from it.
2. **Check tools**: Python 3.10+ (`pip install numpy pillow`), Node.js 18+, `ffmpeg` on PATH (or set `FFMPEG_PATH`).
   Install what is missing if you can, otherwise tell the user the exact command.
3. **Create `.env`** from `.env.example`. Ask the user for **one image key and one voice key** — never require a
   specific provider:
   - Images: `IMAGE_PROVIDER=sangtao` + `SANGTAO_API_KEY`, **or** `IMAGE_PROVIDER=openai` + `OPENAI_API_KEY`.
   - Voice: `TTS_PROVIDER=vbee` + `VBEE_APP_ID` + `VBEE_TOKEN`, **or** `TTS_PROVIDER=elevenlabs` + `ELEVENLABS_API_KEY` + `ELEVENLABS_VOICE_ID`.
   Write the keys into `.env` yourself. Never print, echo or repeat keys back in chat.
4. Continue with step 1 below.

**Choosing the image provider:** both work. sangtao.ai is the cheapest option for this many images — one episode
needs ~60 images, each scene carries up to 6 reference sheets (sangtao accepts 20 per image), and plans start from
about 200k VND / 500 images (~7 episodes), pricing: https://sangtao.ai/vi/imagine?tab=pricing. API calls need a
plan or credit (no free tier on the API). Key: https://sangtao.ai · docs: https://sangtao.ai/vi/api-docs/chatgpt-image.
If the user already has an OpenAI key, that works too.

## 1. Write `story.json`

Ask the user for: topic/genre, language, length, and whether it is part of a series. Then write the file.
Start from `examples/locked-room/story.json` — copy its structure exactly. (It is a short ~3-minute
example with 41 lines; for a 4–5 minute episode write 45–55 lines.)

```jsonc
{
  "title": "CĂN PHÒNG KHOÁ TRÁI",        // shown on the title card
  "series": "HỒ SƠ THÁM TỬ MINH",        // optional red band above the title
  "episode": 1,
  "aspectRatio": "9:16",
  "visualStyle": "Cinematic semi-realistic digital painting, moody film-noir lighting, …",   // ONE style for every image
  "labels": {},                           // optional: override on-screen words (see "English videos" below)
  "keywords": "độc|manh|mối|hung|thủ",    // optional: words highlighted in captions (regex alternation)
  "characters": {
    "minh": {
      "name": "Thám tử Minh",
      "tag": "the detective in the beige trench coat",           // short English visual tag, used inside scene prompts
      "appearance": "Vietnamese man aged 40. BODY: 7.5-head proportion, … FACE: … HAIR: … OUTFIT: …",
      "sheet": "https://…/sheet.png"                               // optional: reuse a sheet from an earlier episode
    }
  },
  "locations": { "study": { "name": "…", "description": "English description of the place" } },
  "props":     { "watch": { "name": "…", "description": "English description of the object" } },
  "keyframes": {
    "k_watch": { "chars": [], "loc": ["study"], "props": ["watch"], "p": "English scene prompt …" }
  },
  "lines": [
    { "t": "Narration sentence in the video language.", "shots": [["k_clock", "shock"], ["k_body", "push"]], "sfx": ["chime"] },
    { "t": "Bạn đoán ai là hung thủ? …", "shots": [["k_lineup", "question"]], "countdown": 3 }
  ]
}
```

**Characters** — `appearance` always has four parts: `BODY` (with head-to-body proportion: 6 = short/stooped,
7 = average, 8 = tall), `FACE`, `HAIR`, `OUTFIT`, and starts with nationality + gender + age. Write it in English.

**Shots** — each line is split evenly across its shots. Aim for a new visual every **3–5 seconds**
(~1 shot per 8–12 words). Reusing a keyframe with a different effect is fine and saves images.

Effects (`fx`):
| fx | look | use for |
|---|---|---|
| `push` / `pan` / `slow` | Ken Burns zoom / lateral pan / gentle drift | normal narration |
| `punch` | zoom punch + white flash | a key detail |
| `shock` | punch + shake + RGB split | discoveries, doors bursting, screams |
| `glitch` | RGB split + slice jitter | "something is wrong" moments |
| `shake` | handheld tremble | fear, nervous characters |
| `flashback` / `flashpush` / `flashshock` | black & white + vignette | memories, the reveal reconstruction |
| `reveal` | slow push + shake + red pulse | the culprit's face |
| `title` | title card over the shot | right after the cold open |
| `suspect:N:NAME:role` | red suspect card | introducing each suspect |
| `clue:N:text` | yellow clue card | each clue (text may contain ":") |
| `question` | "who did it?" card (+ `"countdown": 3` on the line) | just before the reveal |
| `end` | follow / next episode card | last line |

`sfx` per line: `chime thunder hit boom lock knock crash siren tick riser scream rain shimmer click`.
Lines also accept `pauseBefore` / `pauseAfter` (seconds).

### Writing rules (these are what make it watchable)
1. **Cold open in the first 3 seconds** — start at the most shocking moment, then the title card. No intro.
2. **Open loop** — state the question early (who, how) and don't answer it until the end.
3. **Fair clues** — 3–4 clues, each shown on screen with a `clue` card and an image that clearly shows it.
4. **Red herrings** — 2–3 suspects with motive and a weakness; the culprit must have an alibi that the clues break.
5. **A hook every 45–60 s** ("Nhưng có một chi tiết không ai để ý…").
6. **Question + countdown before the reveal**, then a `reveal` shot and a fast black-and-white reconstruction.
7. **Length** — ~45–55 lines ≈ 4–5 minutes. Keep sentences short; one idea per line.
8. Fiction only, no gore: show consequences (a body slumped, a cold cup), never wounds or blood.
   Sensitive words are masked on screen automatically (`chết → ch*t`); the voice is unchanged.

### Image prompt rules
- Write `p` in English, describe composition, camera, light and mood. Name characters exactly as in `characters[].name`
  — the script appends their `tag` so the model links the name to the right sheet.
- List every character / location / prop that appears in the scene in `chars` / `loc` / `props`: those sheets become the references.
- Clue objects need **physical** descriptions, not facts: "the short hour hand just left of 12, the long minute hand
  slightly above the 9" works; "the watch shows 11:47" does not. Same for "cold porridge": describe the cracked skin, dry crust.
- No readable text in images; put words in cards instead.
- Flashbacks: start the prompt with "Black-and-white flashback:".

## 2. Generate images

```bash
python scripts/gen_assets.py my-episode sheets       # ~10–15 sheets
python scripts/gen_assets.py my-episode keyframes    # ~40–45 scene images
```
Then **look at the results** (open the PNGs, or build a contact sheet) and check: same face across scenes,
every clue clearly visible, no garbled text, flashbacks in black and white. Fix the prompt in `story.json` and
regenerate only the bad ones: `python scripts/gen_assets.py my-episode keyframes k_watch --force`.

## 3. Voiceover
```bash
python scripts/tts.py my-episode
```
Changing a line's text and re-running only redoes that line. ElevenLabs gives exact word timing; Vbee is estimated.

## 4. Build and render
```bash
python scripts/build_timeline.py my-episode
python scripts/render.py my-episode --still 30 900 3000    # check a few frames first
python scripts/render.py my-episode                         # → my-episode/out/my-episode.mp4
```
The first render runs `npm install` in `remotion/`. Look at the stills before the full render:
title fits on two lines, cards don't cover faces, captions readable.

## Series
For episode 2+, set `"sheet"` on returning characters to the URL (or local path) of their sheet from episode 1
— they will look identical. With sangtao the sheet URLs are in the previous episode's `assets/manifest.json`.

## English (or other language) videos
Write `lines[].t` in that language, pick a matching voice, and override labels:
`"labels": {"suspect": "SUSPECT", "clue": "CLUE", "episode": "CASE", "question1": "WHO", "question2": "DID IT?", "comment": "Comment before you keep watching 👇", "next": "Next case?", "follow": "Follow for more"}`.
Extend `CENSOR` in `scripts/build_timeline.py` if needed.

Files in this skill

  • LICENSE1.1 KB
  • README.md5.7 KB
  • SKILL.md9.5 KB
  • examples/locked-room/story.json24.3 KB
  • remotion/package.json305 B
  • remotion/src/index.ts92 B
  • remotion/src/timeline.json93 B
  • remotion/tsconfig.json210 B
  • scripts/build_timeline.py12.7 KB
  • scripts/common.py2.1 KB
  • scripts/gen_assets.py9.2 KB
  • scripts/providers/__init__.py965 B
  • scripts/providers/openai_images.py3.4 KB
  • scripts/providers/sangtao.py7.3 KB
  • scripts/render.py2.7 KB
  • scripts/tts.py4 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.