Skip to content
Back to skills

Render 3d Character Explainer

ASecurity

Assemble an animated character-explainer video ad (any art style — Pixar-style 3D, claymation, anime, paper-cut, felt) (~77s, 9:16) built on an "N types of X" listicle spine — a recurring human protagonist plus a locked cast of N persona characters, one per list item. Given the per-scene i2v clips + a per-scene target-duration table + a narration track, it trims each clip to its scene window, re-encodes every segment to identical 1080x1920/30fps/libx264/yuv420p (decrease+pad, never crop) so t...

  • 1,232 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 4, 2026
ai-agentspythongobash

Works with

  • cli

Security analysis

A100/100

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

Scanned September 29, 2026

npx -y skills add gooseworks-ai/goose-skills --skill render-3d-character-explainer --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Render 3d Character Explainer?

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

Security grade badge for Render 3d Character Explainer
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/gooseworks-ai-render-3d-character-explainer/badge)](https://www.skillsdirectory.com/skills/gooseworks-ai-render-3d-character-explainer)

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: render-3d-character-explainer
description: Assemble an animated character-explainer video ad (any art style — Pixar-style 3D, claymation, anime, paper-cut, felt) (~77s, 9:16) built on an "N types of X" listicle spine — a recurring human protagonist plus a locked cast of N persona characters, one per list item. Given the per-scene i2v clips + a per-scene target-duration table + a narration track, it trims each clip to its scene window, re-encodes every segment to identical 1080x1920/30fps/libx264/yuv420p (decrease+pad, never crop) so the concat demuxer never drops frames, concats, and muxes audio — in RESTYLE mode the source ad's VO+music mix is reused verbatim, in ORIGINAL mode fresh per-scene VO (loudnorm I=-14) is mixed under an optional music bed (loudnorm I=-26). A static-still fallback loops a scene's keyframe when its clip is missing/failed, so the master always assembles; libass captions are burned last. FREE deterministic assembly (Python + ffmpeg, no bash, no paid calls); the recipe supplies the clips, keyframes, VO or source audio, and caption table and gates the paid cast-anchor/keyframe/Kling-i2v/VO/music calls to their own capabilities. Use for the 3d-character-explainer listicle format.
status: active
---

# render-3d-character-explainer

The free, deterministic renderer for the **3d-character-explainer** video ad format — an
animated character spot (art style is the user's choice; the demo was glossy Pixar-style 3D) built on an **"N types of X" listicle** spine, where a recurring
human protagonist plus a locked cast of **N persona characters (one per list item)** carry a
hook → "deeper story" → cast-reveal → one beat per list item → kicker → product test →
relieved payoff. This capability is the **FREE assembly stage only**. All generative work
(Nano-Banana cast anchors + per-scene keyframes, Kling-V3 i2v clips, ElevenLabs VO + music,
or a source ad's audio reused verbatim) happens upstream in the recipe and is handed to this
capability as files.

It ports the validated compose recipe from the worked example — a "six types" Pixar-style 3D
listicle restyle (`_render_full.sh` — per-scene trim → normalize 1080×1920/fps30 → concat -c copy → mux the
source audio, with a static-still fallback on any failed clip). The assembly is
deterministic — iterate the cut for free, re-roll only the offending paid beat.

## Choices

The recipe asks these of the user before any paid step; this capability assembles whatever
comes back. None of them is fixed by the format.

- `visual_style` — the art style of the anchors, keyframes and Kling motion prompts (Pixar-style
  3D, claymation, anime, paper-cut, felt). Asked of the user; the demo used glossy Pixar-style 3D.
- `narrator` — who tells the story and in whose POV the lines / captions are written. Asked of
  the user; the demo used an off-screen storyteller.
- `narrator_voice` — the VO voice (ORIGINAL mode only). Asked of the user; the demo used one
  ElevenLabs narrator.
- `tone` — cute/comedic, sincere, educational, dramatic, punchy; shapes the style prefix, the
  delivery and the script. Asked of the user; the demo was cute and comedic.
- `protagonist` — the human's age, gender, look and outfit (locked via the world lock). Asked of
  the user; the demo used a young protagonist in a single tee.
- `music` — the bed under the VO, or none (ORIGINAL mode → `music_bed`). Asked of the user; the
  demo used a light instrumental underscore.

## Two modes

- **Restyle mode** (`audio_mode: "restyle"`, the reference run) — re-tell a finished source
  ad, beat for beat, as an animated character story in the chosen style and tone. The source ad's **audio mix (VO + music bed) is
  reused VERBATIM** (`source_audio`), and the per-scene `target_sec` table is inherited from
  the source's scene timing. No new VO or music is rendered. The trims must sum to the source
  audio length.
- **Original mode** (`audio_mode: "original"`) — the ad authors its own narration. Each scene
  carries a measured VO cue (`scenes[].vo`, `target_sec` = the ffprobe'd VO duration) which is
  concatenated into a VO track (loudnorm I=-14) and optionally mixed under a `music_bed`
  (loudnorm I=-26 then `volume`, `amix normalize=0`).

## What it does (the deterministic recipe)

1. **Per-scene retime.** Each i2v clip is trimmed to its scene `target_sec` and normalized to
   identical dims/fps/SAR
   (`scale=W:H:force_original_aspect_ratio=decrease,pad=W:H:(ow-iw)/2:(oh-ih)/2:color=<pad>,fps=30,setsar=1`).
   A clip **shorter** than its window is extended with `tpad=stop_mode=clone`; a longer one is
   `-t` trimmed. Decrease+pad (never crop) preserves the full 9:16 keyframe framing.
2. **Static-still fallback.** For any scene whose `clip` is missing or failed to render, the
   scene's `keyframe` PNG is looped (`-loop 1`) for `target_sec`, so the master always
   assembles. Fallback scenes are printed at the end.
3. **Identical re-encode + concat.** Every segment is re-encoded `libx264 -crf 18 -pix_fmt
   yuv420p -r 30` even if already correct — a dims/framerate mismatch makes the concat demuxer
   silently drop frames — then concatenated via the concat demuxer (`-c copy`).
4. **Audio.** Restyle: `source_audio` muxed verbatim (`-map 0:v -map 1:a`), clamped to the
   video length. Original: per-scene VO track (optional `atempo`, `apad`, `-t` clamp) → loudnorm
   → optionally mixed under the music bed.
5. **Captions last.** `make_captions.py` emits a libass `.ass` (one cue per scene, `start =
   scene_start + 0.08s`, suppressed on any scene with no caption — e.g. a product/end-card beat
   carrying its own typeset copy). `compose.py` burns it as the final filter so captions sit on
   top. Word-level energy-pop captions (Whisper on the narration) are the recipe's upstream
   option — produce that `.ass` externally and point `captions_ass` at it; compose burns
   whatever `.ass` it's handed.

## Scripts (free — Python + ffmpeg, no bash, no paid calls)

- `scripts/make_captions.py` — emits the per-scene libass `.ass` from the SAME scene table
  compose reads, so caption windows stay in lockstep with the cut. Run before `compose.py`
  (or leave `captions_ass` unset / pointing at nothing to skip captions).
- `scripts/compose.py` — the assembler: per-scene trim + identical 1080×1920/30fps re-encode
  (static-still fallback on missing clips) → concat → audio (restyle verbatim / original
  mix) → burn captions → master mp4.
- `scripts/config.example.json` — the shape of the `config` the recipe binds (the
  brand-neutralised "six types" restyle values as a worked example; captions, audio and
  music are the demo's, never defaults).

## Inputs (all via `--config` + a runtime work dir — NO hardcoded paths)

`config.json` carries: `audio_mode` (`restyle` | `original`), `scenes[]` (each `{id, clip,
keyframe, target_sec, caption?, vo?, atempo?}` where `target_sec` is the source-inherited
window in restyle mode or the **measured** VO window in original mode, and `keyframe` is the
static-still fallback source), `source_audio` (restyle), `music_bed` + `music_volume` +
`atempo` (original), `width`/`height` (default 1080×1920), `pad_color` (letterbox colour),
`captions_ass`, and `caption_style`. See `config.example.json`. `pad_color` defaults to neutral
black; set it from the brand palette.

## Craft rules (load-bearing — faithful to the source molecule + reference run)

- **Restyle inherits the source timing.** A restyle reuses the source ad's exact audio, scene
  order, and per-beat durations verbatim; only an original-mode remix authors its own VO +
  timing table. Merge any sub-1.5s flash scene into a neighbour upstream to avoid a dead
  micro-cut (the reference folded scene 7 into scene 8).
- **Normalize decrease+pad, never crop** — the listicle's cast-reveal + per-persona framing
  must not lose edges; letterbox-pad to the canvas colour instead. Re-encode every segment to
  30fps before concat, even if already correct, or the concat demuxer silently drops frames.
- **Static-still fallback is mandatory** — Kling can 403 mid-run (a billing wall after a burst
  of successes, not a rate limit). Any failed clip loops its keyframe so the master still
  assembles; re-roll only the missing beat and recompose (free).
- **`generate_audio` was false upstream** — Kling would otherwise invent its own dialog track;
  the real narration is muxed here separately. (This is the recipe's upstream call, not this
  capability.)
- **No AI-rendered brand text** — the product-beat keyframe shows a BLANK-label box; the real
  wordmark/end-card copy is composited upstream, never AI-drawn. Suppress captions on any
  product/end-card beat (its typeset copy carries the message — two text layers at one spot are
  both unreadable).
- **Caption `start = scene_start + 0.08s`** (avoids the caption flashing a frame before a cut).

## Requires

`watch` (QC the final master — the human protagonist reads as the SAME person every scene
(wardrobe/hair/lighting held), each persona is on-model, the cast-reveal lineup matches the N
list items, the product beat shows the REAL box, narration lands beat-for-beat, and duration is
within ±0.1s of the summed windows). The recipe gates the paid `create-image-fal` (cast
anchors + keyframes), `create-video-fal` (Kling-V3 i2v), `create-vo-elevenlabs`, and
`create-music-elevenlabs` calls to their own capabilities — this capability itself makes NO
paid calls.

Files in this skill

  • SKILL.md7.9 KB
  • scripts/compose.py11.5 KB
  • scripts/config.example.json3.9 KB
  • scripts/make_captions.py3.2 KB
  • skill.meta.json335 B
  • tests/smoke-test.md4.2 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…