Produce a structured scene manifest (text-based, no images) for a multi-scene video ad. One row per scene with duration, script line, setting, wardrobe, framing, lighting, sub-beats, on-screen ratio, product refs, and continuity links. The pre-render approval artifact between script and prompt assembly. Required for any ad with ≥2 scenes (multi-product, multi-setting, or hook+body+endcard); optional for single-scene 15s ads.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Produce a structured scene manifest (text-based, no images) for a multi-scene video ad. One row per scene with duration, script line, setting, wardrobe, framing, lighting, sub-beats, on-screen ratio, product refs, and continuity links. The pre-render approval artifact between script and prompt assembly. Required for any ad with ≥2 scenes (multi-product, multi-setting, or hook+body+endcard); optional for single-scene 15s ads.
create-shot-list
Purpose
Author the scene manifest — the text-based shot list that drives downstream prompt assembly and per-scene rendering.
Replaces the role that visual storyboarding played in the older NB2 + i2v multi-keyframe architecture. With Seedance 2.0 reference-to-video, scene-by-scene image generation is no longer required — but a structured plan IS still required, because:
Multi-scene ads have global decisions that don't exist inside any single prompt (product ordering, setting variety, wardrobe rotation, lighting continuity).
Cost gating — at $5-10 per Seedance scene, a human needs to approve the plan before firing 4-6 scenes.
Global-rule enforcement — e.g. "wardrobe must vary across scenes" (per create-ugc-style-video Decision Rule 5). Each Seedance call has no memory of other calls; the author enforces variation in the manifest.
Use this atom when:
The video has ≥2 distinct scenes (hook + product scenes, multi-product review, multi-setting GRWM, before/after, etc.)
The architecture is Seedance 2.0 reference-to-video (one prompt per scene with internal sub-beats) — OR the legacy NB2 + i2v multi-keyframe flow (one keyframe per beat)
A pre-render human gate is needed
Skip the manifest (or collapse to one row) for single-scene 15s ads with one product and no setting change.
Inputs
Required:
script.md — the locked VO/dialogue script with per-scene lines
idea-brief.md or equivalent — angle, format archetype, funnel stage, target platform
Product reference image paths (source/products/*.png or similar)
Avatar persona spec (from upstream casting step) including locked portrait reference path
Optional:
targeting-spec.md — for tone/voice continuity
brand-voice.md — for wardrobe/aesthetic palette
Reference ads — for pacing benchmarks
Output
Primary artifact:scene-manifest.yml (or .json) at the project's working/ path.
Schema:
project:<slug># e.g. "video-01-three-product-grwm"brand:<brand-name>total_duration_seconds:<int># sum of all scene durationsarchitecture:seedance-ref# or "nb-i2v" for legacy multi-keyframeaspect_ratio:9:16target_platform:meta-paid# | tiktok-organic | both | youtube-shorts | pinterestfunnel_stage:TOF# | MOF | BOFavatar:persona_id:<slug># link to brands/<brand>/avatars/<persona>/portrait_ref:assets/avatar/portrait-hero.pngvoice_character:"warm conversational American female, early-20s creator"products:-id:<product-slug>label:"<exact brand name on package>"ref_image:source/products/<slug>.pngvisual_description:"powder-blue soft squeeze tube with white cap"common_confusions: ["NOT a moisturizer", "NOT a body wash", "NOT a serum dropper"]
scenes:-id:cold-open# ⭐ MANDATORY for UGC ads — 1s scroll-stopper teaser
{ }
{ }
[]
[]
[]
[, , , ]
[]
[, , ]
[]
[, , ]
{ , , , }
{ , , , }
{ , , , }
{ , , , }
[]
[]
[]
[, , ]
Decompose the script into scenes. For UGC review format: hook (8s) + N product scenes (15s each) + endcard (4s).
For each scene, populate:
Setting + lighting that varies from neighbors (per global rule)
Wardrobe with explicit negations of common drift
Framing strategy (wide/medium/close mix vs single focal length)
On-screen ratio (typically 100% for hook, 50-60% for product scenes, 0% for endcard)
For Seedance scenes: 4 sub-beats (WIDE_HOOK / PRODUCT_HERO / SIDESTEP / REACTION_CTA) inside the 15s window
Continuity links to prior and next scenes
Run the continuity audit (per memory feedback_continuity_audit_pass.md):
Walk through scenes[] in order
For each scene N+1, check that scenes[N].continuity.end_state is a reachable starting point for scenes[N+1].continuity.prev_state
Flag any time-jumps, setting jumps without explicit transition, wardrobe collisions
Compute cost estimate from scene durations × resolution-keyed per-second cost.
Write working/scene-manifest.yml to the project folder.
Surface to operator for approval — this is the cheap pre-render gate.
Decision Rules
Wardrobe must vary across consecutive scenes. Same identity portrait + different wardrobe per scene gives the ad visual rhythm. Avatar identity holds; wardrobe creates variety.
Setting SHOULD vary across consecutive scenes for multi-product reviews (bathroom → bedroom → kitchen → outdoor). For single-setting ads (e.g. mirror-only GRWM), state this explicitly in global_rules.
One product per scene (except the hook). Multi-product scenes inside a single Seedance call degrade label fidelity. The hook scene shows all products together but doesn't go macro on any single label.
NSFW sidestep for body-application products. Reframe scenes that involve water/lather/face/body-application as: pump-onto-fingertips, twist-up-and-smell-test, or hand-only POV placement. Encode the sidestep explicitly in the scene's action field.
On-screen ratio target. UGC review format aggregates ~50-60% creator on-screen. Hook = 100%, product macros (PRODUCT_HERO sub-beat) = 30%, B-roll = 0%. Sum across scenes shouldn't exceed 70% (over-talking-head reads as documentary, not UGC).
Continuity audit before approval. Sequential walk per memory feedback_continuity_audit_pass.md. Catches VO/visual timing inversions, off-screen transitions, time jumps.
Scene 0 (cold-open) MUST exist for UGC ads. A 0.8-1.2s scroll-stopper teasing the payoff state before the verbal hook. source_strategy=lift_from_scene is the default (free, identity/wardrobe lock for free); source_strategy=standalone_render only when the lifted slice spoils the body of the ad. The verbal hook in scene 1 (hook) is NOT a substitute — the cold open is visual scroll-stop, the verbal hook is intent framing. Memory: feedback_ugc_scroll_stopper_cold_open.md.
Quality Checks
For UGC ads: scenes[0].id == "cold-open" with duration in [0.8, 1.2] and a valid source_strategy. If lift_from_scene, lift_source.scene_id matches a later scene's id.
Every scene has a non-empty script, setting, wardrobe, framing, duration (except endcard which may have script: null, and cold-open which may inherit setting/wardrobe from its lift source).
Reference run: beauty-by-earth/video-01-three-product-grwm/working/ — see scene-{hook,facewash,deo,tanner}.json for per-scene specs
order:
0
duration:
1
# 0.8-1.2s; ffmpeg-trim to exact target in composite
script:
"Okay yeah, that's plumped."
# lifted VO OR 1-word interjection ("Wait —" / "Okay so —")
source_strategy:
lift_from_scene
# | standalone_render
lift_source:
# populated if source_strategy=lift_from_scene
scene_id:
product-1
start_time_sec:
12.4
# absolute timestamp in source scene
duration_sec:
1.0
setting:
description:
"inherits from lift source"
wardrobe:
description:
"inherits from lift source"
framing:
"extreme close-up of payoff state (e.g. post-application lips, surprised face, product mid-squeeze)"
on_screen_ratio:
0
# not counted toward face-share budget
sub_beats:
product_refs:
# the lift carries product context; no separate refs
continuity:
prev_state:
null
end_state:
"viewer registers a 'wait — what just happened?' moment, primed to keep watching"
next_compatible:
hook
notes:
|
Scroll-stopper cold open. Show the PAYOFF state before the SETUP state.
Default to lifting a 0.8-1.2s slice from a later scene (free, no drift).
Only set source_strategy=standalone_render if the lifted slice would spoil the body
(e.g. shows product name before the reveal). Memory: feedback_ugc_scroll_stopper_cold_open.md.
-
id:
hook
order:
1
duration:
8
# seconds
script:
"Okay so… top 3 products I'm honestly obsessed with."
setting:
description:
"casual bedroom corner with wooden dresser, cream wall, terracotta pot"