AI agent skill · by @TokenRhythm
Meta Short Drama
Create a complete AI short-drama package from a topic: shot script, review/approval pause, consistent images and clips, titles, subtitles, and final delivery. Do not use for isolated script or image requests, slides, document analysis, or historical examples.
Archived 2026-10-23 · Source updated 2026-09-17 · License: Apache-2.0. Check the original repository for the latest version.
SKILL.md instructions
# meta-short-drama
End-to-end short-drama generator with an explicit-consent review flow before
any paid external-media step. **1-10 shots** (default 5), title card + ending
card, in-language burned subtitles, and the generated script is saved to disk
regardless of outcome. A direct approval continues immediately; an edit only
produces a revised preview and requires a second explicit approval.
## What it does
1. **`intake_extract`** scans the user message for RENDER_STYLE,
IDENTITY_ANCHOR, and N_SHOTS (1-10). Fills in defaults when missing.
2. **`script_draft`** calls `ai-video-script` with the inferred values
pasted verbatim into every shot prompt.
3. **`review_gate`** — free-form draft review. The user can approve,
request changes to render style / character / shot count / shot details,
or cancel in plain language.
4. **`review_intent`** is local and deterministic. Explicit approval may
proceed, while a recognizable adjustment emits `DECISION: revise`; the
adjustment never authorizes an external call.
5. **`script_revised`** (conditional) applies requested overrides, then
**`revision_confirm_gate`** shows the revised preview and requires a new
explicit approval. **`review_normalize`** is the final paid-media consent
authority; cancel, missing, ambiguous, off-topic, and further-edit replies
fail closed without provider calls.
6. **`final_script`** freezes the canonical scheduler snapshot in memory; it
never re-reads the user-editable artifact.
7. **`script_save`** writes that same canonical content to `script.txt` in the run folder
(always — even on cancel, so the user keeps the draft).
8. **`title_extract` / `subtitle_extract` / `ending_text_extract`**
pull cover/ending text in the script's language.
9. **`cover_image` + `cover_video`** — Pillow title card + 2s Ken-Burns
clip (`0_cover.mp4` — sorts first in merge).
10. **Per-shot extracts × 10** — all slots are declared, but an exact
`=== SHOT_N ===` header check deterministically skips absent script blocks
before calling the LLM. Active extracts still use `__SHOT_ABSENT__` as a
second fail-closed guard, and paid image/video steps repeat the exact-header
check so an LLM cannot activate an unused slot.
11. **Image generation per active shot** — `nano-banana-pro`, at most one paid
submit, followed by a local placeholder PNG on a verified policy refusal
(the image step never aborts the DAG). Provider responses and ambiguous
transport outcomes never trigger an automatic second paid request.
12. **`reference_prompt_extract` + `reference_image`** — one extra
`nano-banana-pro` call produces `reference.png`, a full-cast neutral
lineup of every named character on a neutral backdrop. Used as the
universal IDENTITY anchor for every shot's seedance call so the
character does not drift across cuts (nano-banana would otherwise
re-roll subtly different character designs per shot).
13. **Video generation per active shot** — `seedance-2.0`; paid submit
failures are never retried automatically because an ambiguous response may
already represent a billed job. After a job id is issued, transient polling
failures may retry that same job up to the configured limit. Any provider-policy
refusals stop immediately without another paid submission. The Ken-Burns
substitute then fires using the
shot's PNG. Each shot passes TWO reference images to seedance,
AND the per-shot prompt is wrapped with an explicit "Assets
Mapping" preamble in the upstream JiMeng convention so seedance
knows the role of each reference:
reference[1] = `reference.png` (full-cast fictional design anchor —
preserves silhouette / hairstyle / costumes /
accessories without reproducing real-person likeness)
reference[2] = `N_shot.png` (this shot's scene composition
reference — used for camera angle, framing,
blocking, prop placement, background layout)
The Assets Mapping preamble is in English even when the per-shot
directive is Chinese — seedance parses English instruction prefixes
reliably regardless of the user-content language. Empty / missing
references are still filtered before the API call (so direct CLI
callers using a single anchor remain backwards-compatible).
13. **`ending_image` + `ending_video`** — Pillow "完" / "THE END" card
+ 2s Ken-Burns clip (`99_ending.mp4` — sorts last).
14. **`merge`** — `video-merger` stitches `0_cover` + active shots
+ `99_ending` via numeric-prefix sort. ffmpeg cross-fade transitions.
15. **`subtitles_srt`** — SRT cues from VOICEOVER per shot, shifted by
the 2-second cover duration so cue timing matches the merged
timeline.
16. **`subtitled_final`** — `subtitle-burner` burns the SRT into
`final_subtitled.mp4`.
17. **`publish_final_video` + `publish_script`** — register the final
MP4 (`video/mp4`) and script (`text/plain`) with the active surface
so browser users receive artifact controls instead of only a local
path. The script is published even when the user cancels; the video
is published only after a successful proceed path.
18. **`delivery_audit`** — deterministic receipt/fallback/ffprobe gate.
It combines validated receipts with the scheduler's bounded, parent-owned
paid-submission dispositions (`safe_no_submit`, `maybe_accepted`, or
`receipt`; only a conclusive receipt becomes `confirmed`). It is the sole
authority for API provenance and reports both story content duration and
the probed final duration (content + 4s bookends). A fallback after a
proven pre-submit failure does not trigger a billing warning; ambiguous
submission outcomes still emit only a sanitized asset list and
check-history warning.
19. **`deliver`** — always runs, branches on DECISION, and waits for
the deterministic audit before composing delivery. It only restates
the machine-owned verdict and cannot promote fallback media to a
verified real-API result.
## Outputs
```
<workspace>/meta_short_drama/<meta_run_id>/
script.txt # full final script (always; published artifact)
reference.png # full-cast identity reference (used by every shot_video)
0_cover.png 0_cover.mp4
1_shot.png 1_shot.mp4 ┐
2_shot.png 2_shot.mp4 ├ only for active shots (1..N_SHOTS)
... ┘
*.png.receipt.json # image provider/request or placeholder status
*.mp4.receipt.json # video provider/model/job status
99_ending.png 99_ending.mp4
subs.srt
final.mp4 # merged, no subtitles
final_subtitled.mp4 # subtitled — published video deliverable
```
## Dependencies
| Skill | Purpose | Models / Tools |
|---|---|---|
| `ai-video-script` | Structured shot list (1-10 shots) | LLM |
| `short-drama-review-normalizer` | Local fail-closed review/consent decision | Python stdlib |
| `nano-banana-pro` | Per-shot first-frame PNG | OpenRouter Gemini 3.1 / 3 pro |
| `seedance-2-prompt` | Per-shot MP4 | OpenRouter Seedance 2.0 (or Volcengine ARK) |
| `video-still-animator` | Ken-Burns fallback / cover & ending clips | ffmpeg ≥ 5.0 |
| `video-merger` | Stitch cover + shots + ending | ffmpeg ≥ 5.0 |
| `srt-from-script` | VOICEOVER → SRT with cover offset | Python stdlib |
| `subtitle-burner` | Burn SRT into MP4 | ffmpeg + libass |
| `title-card-image` | Pillow cover + ending PNG cards | Pillow |
| (builtin) `write_file` | Save script.txt (no skill needed) | OpenSquilla builtin |
| `text-file-read` | Re-read script.txt after review pause | Python stdlib |
Environment:
- `OPENROUTER_API_KEY` must be set.
- `ffmpeg` and `ffprobe` on PATH.
- Pillow installed (already in opensquilla deps).
## Risk
`high` — writes files, spends real OpenRouter credits, runs ffmpeg
subprocesses. The review gate plus deterministic normalizer ensures explicit
approval or a meaningful requested adjustment before any external media step.
## Limits (v2)
- 1-10 shots; default 5. The DAG always declares 10 slots but
`__SHOT_ABSENT__` gating keeps unused slots dormant.
- Per-shot duration follows the script's DURATION_S (clamped 3-15s by
seedance API). OVERVIEW.DURATION_S means story-shot content duration;
the final MP4 adds a fixed 2s title + 2s ending (content + 4s).
- 9:16 portrait.
- Per-shot seedance failures fall back to Ken-Burns. Image step
has its own placeholder fallback. Both are explicitly reported as
degraded and cannot satisfy the verified-real-API E2E status.
Prompt-extract llm_chats still abort the run if they return malformed
output.
- Every run uses its runtime-owned `meta_run_id` subdirectory, so concurrent
runs and post-review `additional_notes` cannot redirect or collide outputs.
## When NOT to use
- Single image / single clip / script-only / stitch-only — use the
underlying skills directly.