| name | create-ugc-style-video |
| description | Produce a UGC-style talking-head ad with an AI avatar reviewing 1-N products. NB2 generates
the avatar portrait; Seedance 2.0 reference-to-video on FAL renders each per-product scene
with native lip-synced dialogue. Per-product scenes are stitched with a hook + HTML endcard
using an L-cut to land the closing CTA over the brand wordmark. Final master gets DIY karaoke
captions and an instrumental music bed. Designed for clean-girl skincare / beauty / wellness
briefs where a creator reviews products one by one on phone-front-camera selfie.
|
| status | ACTIVE — validated against Beauty by Earth Video 01 (May 2026) |
create-ugc-style-video
Validated end-to-end on beauty-by-earth/video-01-three-product-grwm. Final master:
finals/master-v12-captions-music.mp4 (~56s, 9:16 1080p, 3 product scenes + hook + endcard,
total spend ~$30 for hero-quality 1080p output).
Purpose
Produce a 15-60s vertical 9:16 UGC review ad where an AI avatar talks to camera about 1-N
products, using Seedance 2.0 reference-to-video on FAL. Avatar generation via NB2
(fal-ai/nano-banana-2/edit). Scenes are stitched with an L-cut HTML endcard, then sweetened
with DIY karaoke captions + ElevenLabs music bed.
The architectural win: Seedance 2.0 reference-to-video generates lip-synced dialogue
natively when generate_audio: true. No separate ElevenLabs VO + Whisper-locked beat
manifest + Soul ID needed. Multi-shot internal cuts (4 sub-scenes per 15s call) are handled by
the model in a single render.
Use when:
- 1-4 products per ad
- Creator talks directly to camera (review / GRWM / how-I-use-it format)
- Body application of the product is OK to SHOW HOLDING / smell-test, but actual on-body
rubbing is optional (often better to sidestep — see NSFW rules)
- 9:16 vertical, Meta/IG/TikTok delivery
- Avatar identity must hold across multiple scenes
- Per-product budget ~$5-10 per 15s scene
Do NOT use for:
- Real actor / real creator footage → recast in post or hire a creator
- Long-form explainer videos (>1min) → use
create-vo-anchored-beat-video
- Brands where MS Hyper Motion
product_showcase works (no creator on-screen) → use
create-product-stopmotion-video
Inputs
Required:
- One of:
- Company website URL (skill scrapes top-3 product candidates from site)
- Product URLs (1-N direct product page URLs)
- Pre-prepared product brief (markdown with company name, brand voice, product list +
images already downloaded)
- Brand voice notes OR explicit reference to
DELIVERY_STYLES.md voice (defaults to
UGC-Creator-Confiding: relaxed, first-person, em-dash hesitations, softeners like
"honestly" / "like" / "just")
Optional:
- Reference video URL of a real human creator (NOT AI-generated) — passed as
video_urls
to Seedance for style/voice anchoring. CRITICAL: must be footage of a real person; AI-gen
scenes will trigger FAL content_policy_violation.
- Avatar portrait (if user already has one they want to lock)
- Target duration (default: 15s per product scene + 8s hook + 4s endcard)
- Resolution (default:
1080p; budget mode: 720p)
- Number of products (default: 3; range 1-4)
Pre-requisites the USER must do before invoking this skill:
- Research the brand themselves (visit website, watch 2-3 brand reference ads on Meta/TikTok,
note tone)
- Have product hero images either downloaded or accessible via direct URLs
- Have a rough storyline preference in mind ("morning routine GRWM", "shower-to-bed
routine", "weekly favorites", etc.) — skill will propose options but user picks
If the user shows up with just a website URL and no prep, skill does light scrape only.
Heavier research belongs to the separate legacy/new-client-video-setup-research skill.
Composed Atoms
atoms/image-generation/create-image-nano-banana-2-fal — NB2 multi-image edit via FAL
(fal-ai/nano-banana-2/edit). Generates the hero avatar portrait + optional wardrobe
variations; also generates the endcard BG flatlay plate. Soul ID is NOT used in this
architecture — a single portrait reference carries identity across all Seedance scenes.
atoms/planning/create-shot-list — produces the structured scene-manifest.yml (text)
that drives prompt assembly. The pre-render approval gate. Encodes wardrobe variation,
NSFW sidestep, sub-beat structure, continuity links per scene.
atoms/voiceover/format-script-to-style — formats a draft script to a DELIVERY_STYLES.md
voice (default: UGC-Creator-Confiding) for use inside the Seedance prompt's audio-direction
block. Used for the textual VO direction only; Seedance itself synthesizes the audio.
atoms/video-generation/create-video-seedance-2-fal — fires
bytedance/seedance-2.0/reference-to-video via FAL with image_urls only (NEVER
video_urls of prior AI-gen scenes — content-policy hard fail), generate_audio: true
for native lip-sync, duration as string. The prompt template lives in this atom's docs.
atoms/end-cards/create-end-card-from-reference — reference + NB2 + HTML overlay endcard
pattern. NB2 generates a flatlay BG via create-image-nano-banana-2-fal; HTML hyperframe
overlays brand wordmark, tagline, CTA, cert footer (NB2 can't render brand text cleanly).
atoms/assembly/stitch-videos-ffmpeg — concat the rendered scenes. The L-cut endcard
(final scene's closing audio lands over the endcard visual) is implemented inline in this
molecule's Phase 8 — uses Whisper word-timestamps to find the natural sentence boundary
before the CTA, then maps audio + video separately in ffmpeg.
atoms/captions/add-captions-klap — DIY karaoke caption pipeline (Whisper word-timestamps
→ ASS → ffmpeg subtitles filter; visually matches Klap output).
atoms/music/create-music-elevenlabs — instrumental music bed via FAL ElevenLabs Music
endpoint (fal-ai/elevenlabs/music). force_instrumental: true because Seedance lip-synced
VO occupies the vocal space. Mix at ~22% / -13 dB with amix=normalize=0 (per memory
feedback_ffmpeg_amix_normalize.md).
Workflow
Phase 0 — Pre-flight checks
Skill should refuse and ask user to prepare first IF:
- User has no clear product list and no website URL
- User can't articulate which 1-4 products they want to feature
- User has zero reference ads watched and no sense of brand voice (skill will produce
generic UGC unless guided)
Skill should proceed IF:
- Website URL provided → skill will WebFetch the brand page and propose 3 hero products
- Product URLs provided → skill will WebFetch each and confirm images downloadable
- Brief markdown provided → skill verifies required fields present
Phase 1 — Intake & confirm
- Parse input (URL / brief / explicit product set)
- WebFetch the brand site briefly. Pull: company name, brand voice cues, palette,
top product candidates with hero images
- Confirm with user:
- Product list (default 3; user can adjust 1-4)
- Target duration per product scene (default 15s)
- Storyline theme (skill proposes 2-3 options; e.g. "morning skincare GRWM", "before-bed
wind-down routine", "products I'm obsessed with this month")
- Resolution mode (default 1080p std tier; 720p budget mode if user explicitly asks)
- Reference video URL of real creator? (optional — anchors style)
- Budget gate: show estimated total spend (Avatar NB2 + N×Seedance scenes + hook scene
- endcard NB2 BG + music + composite). Get user OK before any paid calls.
API limits to surface to user (per FAL docs):
- Image refs: max 9 per call
- Video refs: max 3 per call (combined ≤15s, total ≤50 MB)
- Audio refs: max 3 per call (combined ≤15s)
- Total files combined: max 12
- Duration per scene: 4-15s
- Resolutions: 480p / 720p / 1080p
Phase 2 — Avatar generation
- NB2 prompt for the avatar: describe age range (early-to-mid 20s creator typical),
hair (length, color, texture), eyes, light makeup, ethnicity if user specified, body
framing (head + shoulders + chest), wardrobe (loose neutral top — actual wardrobe will be
overridden per scene later).
1a. CRITICAL — Generate on a SEAMLESS NEUTRAL BACKDROP (cream/off-white), NOT in the
target environment. The background ref is generated separately in Phase 4.6 and passed
to Seedance as
image_urls[2]. Baking avatar + environment into one NB2 image produces:
(a) bokeh / shallow DOF on the background even with explicit "no bokeh" prompts;
(b) studio-portrait priors on the avatar → AI-glossy plastic skin;
(c) locked composition (creator distance to camera can't vary across sub-scenes).
Memory: feedback_avatar_background_separation.md. Validated Lineage Video 01 (2026-05-26).
- Apply the v8 soft-skin language (do NOT use "freckles prominent", "real-person
imperfections", "lived-in face"). Instead: "tiny natural imperfections", "subtle peach
fuzz", "faint fine lines", "healthy young-adult skin", "light golden tan".
- Generate 1 hero portrait. Show to user.
- If user wants 1-2 variations (different angles or wardrobe) → fire 1-2 more NB2 calls.
- User locks the hero portrait. Save as
assets/avatar/portrait-hero.png.
Save variations as assets/avatar/portrait-var{N}.png.
Cost: ~$0.08 per NB2 call. Total ≤$0.24 for 1 hero + 2 variations.
Note: Skip the 8-portrait contact-sheet pattern used by older Soul ID architectures.
Soul ID is not needed here — a single portrait reference image carries identity across all
Seedance scenes.
Phase 3 — Storyline + script
- Propose 2-3 storyline options. Examples:
- "A UGC creator showing 3 products as her one-by-one favorites in a morning routine"
- "A wind-down evening routine ending with a self-tanner application before bed"
- "Weekly favorites — what I keep restocking from [brand]"
- User picks one.
- Generate first-person UGC script using
DELIVERY_STYLES.md (default
UGC-Creator-Confiding voice). Script structure:
- Hook line (5-10 words, the opener — "Okay so… top 3 products I'm honestly obsessed
with")
- Per-product: 3-4 lines that fit a ~15s scene with 4 sub-scenes (hook/hero/sidestep/
reaction)
- Closer: "Highly recommend honestly" or equivalent CTA
- Naturalness QC (per memory
feedback_script_naturalness.md):
- Read aloud — must sound like a real creator, NOT ad copy
- Em-dashes, ellipses, "honestly", "like", "just" as softeners
- NO bulletpoint-y lists, NO superlatives stacked
- 1-2 phrases per sub-scene (Seedance dialogue feels natural at ~3-4s per phrase)
- User approves the script.
Phase 3.7 — Scroll-stopper cold open (1s teaser) — DEFAULT (skip in recreate-mode when the hook IS the reveal)
Default: every UGC ad opens with a 1-second teaser of the payoff state BEFORE the verbal intro. Without it, the verbal hook has no chance to land — Meta/IG/TikTok viewers swipe before "Today I'm trying…" finishes.
When to SKIP the teaser:
For single-creator recreate-mode briefs where the source ad opens directly on the visual reveal moment (e.g. ad-04-style: open-mouth excited "I have been looking for..." with the surprise expression at second 0), the verbal hook IS the visual scroll-stop. Adding a separate teaser creates audio repetition (the same phrase plays twice) and weakens the natural hook delivery.
Indicators that you should skip:
- Source/reference ad has no scroll-stopper teaser of its own
- The first 1-2 seconds of the hook scene already show the payoff expression (excited face, open-mouth reveal, satisfied reaction)
- The ad is a faithful single-creator recreate, not a slow-build GRWM or multi-product haul
Validated: Lineage Video 01 (2026-05-26) shipped without teaser after the first attempt felt awkward — "I finally found it" played twice (teaser + at 5.75s of Call 1). Final version (master-v3-captioned.mp4) opens directly on Call 1's open-mouth hook moment.
When the teaser still applies (Kosas-style): multi-product GRWM where the hook line is "Okay so… top 3 products I'm honestly obsessed with" (2-3s of setup before any reveal). Without the visual teaser the viewer has no payoff cue in the first second.
What it is: A 0.8-1.2s opening shot that shows the result before the setup. Examples (Kosas Lip Pulse ad-06 reference):
- Extreme CU of already-plumped glossy lips + VO
"Okay yeah, that's plumped" (lifted from the 0:31 callback)
- Creator's surprised face mid-reaction (lifted from a later tingle beat)
- Product mid-flick / mid-squeeze / mid-spray onto a finger
- Mouth slightly open + sharp inhale + freeze
- "Wait, look —" half-sentence over an off-center extreme close-up
Why this works (rubric): the viewer's brain registers "something already happened here" → curiosity gap → keeps watching to figure out what it was. The full ad then "resolves" the gap by showing the build-up.
How to source it (two options — pick ONE per ad):
| Option | When | Cost | Risk |
|---|
| A. Lift from a later scene | The payoff beat in Phase 4's product scenes already includes the reaction/result moment (post-application reveal, tingle face, satisfaction shot). Just ffmpeg-trim 0.8-1.2s out of that scene and prepend it. | $0 | None — same render, same identity, same wardrobe. Default choice. |
| B. Generate a standalone 1-2s Seedance call | The lifted slice would expose context that spoils the body (e.g. you'd see the product name before the reveal beat). Render a dedicated 1-2s Seedance scene matching wardrobe + setting + identity. Keep duration at the FAL minimum ("duration": "4", then ffmpeg-trim to 1s). | ~$1.20 at 720p / ~$2.72 at 1080p | Identity/wardrobe drift if you forget to seed-reuse from Call 1. |
Voice-over treatment:
- Lift the VO too if you're lifting visual (matched audio).
- If the lifted visual has no usable VO, drop in an interjection:
"Wait —", "Okay so —", "Hold on —", or a sharp inhale. Render via ElevenLabs v3 as a tiny separate clip.
- Never silent. The audio cue is half the scroll-stop.
Composite order: [1s scroll-stopper] → [hook scene] → [product scenes] → [endcard]
Continuity rule: the scroll-stopper should NOT show a state that contradicts the hook scene's opening state. If the hook starts with the creator holding all products on the dresser, the scroll-stopper showing applied-product lips is FINE (it's a flash-forward, viewer reads it as a tease). But the scroll-stopper showing the creator outdoors when the rest of the ad is indoors is a continuity break.
Memory: feedback_ugc_scroll_stopper_cold_open.md. Reference exemplar: kosas/existing-ads/ad-06.mp4 (0:00-0:02 extreme CU lips + "okay yeah, that's plumped" — verbatim callback of the 0:31 payoff).
Phase 4 — Scene breakdown
For each of: hook + per-product scenes:
- Wardrobe (STRICT, with negations — e.g. "cream linen tank, NOT white, NOT silk, NOT
patterned"). Must vary across scenes to provide visual rhythm. Identity holds via
portrait; wardrobe creates rhythm.
- Setting (specific environment — bathroom counter / bedroom dresser / edge of bed /
kitchen / etc.). Vary across scenes.
- Lighting (morning warm window light / amber bedside lamp / kitchen overhead daylight /
etc.)
- 4 sub-scenes within each 15s product scene:
- (0-3s) Wide hook — establishes setting + creator + product
- (3-7s) Product hero — rotates product, brand label readable, focus pull
- (7-11s) Sidestep "application" — pump/twist/squeeze onto fingertips OR smell test.
DOES NOT actually apply to body unless product is clearly safe (eye cream around
eye area = OK; face wash water+lather = NOT OK; leg tanner = NOT OK)
- (11-15s) Reaction + recommendation — pull back to medium, satisfied closing
For the hook (8s, all products visible):
- Single continuous shot
- All N products on a dresser/counter with creator behind/beside
- Hand sweep gesture to introduce
- Script: "Okay so… top [N] [brand] products I'm honestly obsessed with"
For the endcard (HTML, 3-4s):
- Brand wordmark + tagline + leaf/icon + "Shop Now" + brand URL + cert footer
- Optional NB2 lifestyle BG plate (warm flat-lay style, products on linen with shadow play)
- See
atoms/end-cards/create-end-card-from-reference for the proven recipe
User approves the full scene breakdown before any Seedance calls.
Phase 4.5 — Product image pre-clean check (NEW — validated 2026-05-23)
Before assembling Seedance prompts, inspect each product reference image:
- Does the image show ONLY the hero product? Or does it have accessories / secondary products / score badges / lifestyle elements / overlay graphics?
- If clean (product-only): proceed to Phase 5.
- If accessories present: Seedance will fuse them onto the hero product's face (validated Bristle 2026-05-23 — vials and funnel got composited onto the Bristle box's front face). Pre-process via
atoms/image-generation/create-image-nano-banana-2-fal:
- Endpoint:
fal-ai/nano-banana-2/edit
- Prompt: explicit "remove [accessories], keep ONLY the [hero product], fill with clean background"
- Cost: $0.08
- Output: cleaned product reference saved to
brands/<brand>/assets/product-refs/<product>-cleaned.png
- Pass the cleaned image as
image_urls[1] to Seedance instead of the original.
Surface to operator: if pre-clean is needed, flag the issue + cost + show the cleaned result before proceeding.
Memory: feedback_nb2_clean_product_refs.md.
Phase 4.6 — Background reference image (NEW — validated 2026-05-23)
For locked indoor settings, generate a background hero image BEFORE Phase 5:
- Use
fal-ai/nano-banana-pro (text-to-image, $0.15/1K, supports 9:16) for empty-room background generation.
- Prompt must include: "NO people, NO faces, NO body parts" + "Deep infinite focus — everything sharp, NO bokeh, NO shallow DOF" + composition details + aesthetic reference.
- Output:
<video-folder>/assets/setting/<setting-name>-hero.png
- Pass as
image_urls[2] to Seedance in Phase 5 (Image Refs block: "@Image3 = locked setting").
- Use the SAME background image across all calls of the same ad — different bg = "she moved rooms" continuity break.
Why: Text-only setting description yields generic-rental aesthetic. Background reference image LOCKS the aesthetic visually — far stronger than text. Validated 2026-05-23 (Bristle Video 02).
Memory: feedback_seedance_long_calls_not_short.md.
Phase 5 — Prompt assembly (per scene)
Use the proven template from content-goose/prompt-example.md (sunscreen + lipstick prompts
that produced high-quality output). Per-scene prompt must include:
📱 UGC INFLUENCER [PRODUCT] REVIEW REEL (SELFIE-STYLE, NOT A COMMERCIAL)
[BLOCK 0 — anti-pattern opener]
This is NOT a cinematic commercial, NOT a [product category] ad, NOT an editorial campaign.
This is a real Instagram Reel filmed by a 20-something [demographic] creator on her iPhone
front camera, talking directly to her followers in a relaxed, confiding, friendly tone...
[Image reference assignments]
Use @Image1 as the influencer's face/identity. Use @Image2 as the exact [product] she is
reviewing — it is a [VISUAL DESCRIPTION OF THE PRODUCT] (USE THE PRE-CLEANED IMAGE from
Phase 4.5 if the source had accessories). It is NOT a [common confusion], NOT a [common
confusion]. The product and label MUST be clearly identifiable.
Use @Image3 as the LOCKED [setting] — match @Image3 exactly: [list specific visible
elements from the background hero generated in Phase 4.6]. The setting NEVER changes across
sub-scenes.
[FORMAT block]
- Vertical 9:16 phone-shot selfie aesthetic, slight handheld micro-shake
- WARDROBE (STRICT, FULLY SPECIFIED — top + bottom + hair + accessories):
- Top: [top with negations — "NOT white-white, NOT silk, NOT patterned"]
- Bottom: [bottom with negations — "NOT jeans, NOT pajama shorts, NOT leggings"]
- Hair: [exact styling — "loose low ponytail at the nape with face-framing strands" works
better than vague "messy bun"]
- Accessories: [e.g. "thin gold hoop earrings, nothing else"]
- Setting: match @Image3 exactly
- Lighting: [lighting]
- Real, slightly imperfect skin (natural barely-any makeup), light golden tan, even skin tone
[IDENTITY block]
Same young woman as @Image1 — [age range, hair, eyes, skin tone]
[DYNAMIC FRAMING block]
The video must vary its framing across scenes like a real Reel — do NOT stay on one focal
length the whole time. Mix wide selfie / medium chest-up / close-ups.
[SCENE 1 (0-3s)] [WIDE HOOK] — [script line] + [emotion + action]
[SCENE 2 (3-7s)] [PRODUCT HERO with rotation] — [script line] + [emotion + action]
[SCENE 3 (7-11s)] [SIDESTEP application or smell test] — [script line] + [emotion + action]
[SCENE 4 (11-15s)] [REACTION + recommendation] — [script line] + [emotion + action]
[AUDIO DIRECTION]
[Voice character: tone, accent, pace. Match DELIVERY_STYLES.md voice.]
NO music in the audio (we add music in post).
[GLOBAL RULES]
- Wardrobe identical across the scene
- Product stays identical and clearly visible in her hand
- Settings consistent within this scene
- Lips remain CLOSED between dialogue beats
- [NSFW sidestep rules — see Decision Rule 2]
[STRICT REALISM RULES — Block F]
- Tiny natural imperfections, subtle peach fuzz, faint fine lines
- NOT plastic, NOT airbrushed, NOT doll-like, NOT porcelain
- NOT freckle-heavy, NOT blotchy, NOT mottled
- Lighting physics: realistic falloff, gentle shadow under jaw and nose, sun catch-light
- Skin highlights ONLY on nose tip / cheekbones / cupid's bow
- Hair: individual flyaway strands, slight frizz
- Image grain matches iPhone front camera, NOT cinema sensor
User reviews the full prompt for each scene before firing.
Phase 6 — Fire scenes (parallel where possible)
Per-product scenes (and the hook):
fal_client.subscribe(
"bytedance/seedance-2.0/reference-to-video",
arguments={
"prompt": prompt,
"image_urls": [portrait_url, product_url], # 2 refs for per-product
# "video_urls": ... ← DO NOT pass AI-gen scenes here. Will 422.
"resolution": "1080p", # or "720p" for budget mode
"duration": "15", # str, NOT int — FAL schema
"aspect_ratio": "9:16",
"generate_audio": True, # native lip-synced dialogue + ambient
},
)
Hook scene (multi-product):
arguments={
"prompt": hook_prompt,
"image_urls": [portrait_url, product_url_1, product_url_2, product_url_3], # up to 9
"resolution": "1080p",
"duration": "8",
"aspect_ratio": "9:16",
"generate_audio": True,
}
Cost per call (FAL pricing as of 2026-05):
- 720p std: $0.3024/sec → $4.54 per 15s scene
- 1080p std: token-formula → ~$10.20 per 15s scene
- Fast tier ~20% cheaper but caps at 720p
Time per call: 5-15 min depending on FAL queue. Fire in parallel where possible.
Phase 7 — Endcard hyperframe
- Optional: fire NB2 multi-image with product PNGs to generate a warm flat-lay BG plate
(~$0.08). Save as
assets/hyperframes/endcard-bg.png.
- Build
assets/hyperframes/endcard.html with:
- Brand wordmark (Cormorant Garamond or brand serif)
- Tagline (italic serif)
- Leaf or brand icon (inline SVG)
- CTA: "Shop Now"
- URL:
[brand].com
- Cert footer (USDA / Leaping Bunny / EWG / brand-specific)
- Subtle warm gradient overlays at top/bottom for text legibility against the NB2 BG
- Render via Playwright at design dimensions (1080×1920), output PNG.
See atoms/end-cards/create-end-card-from-reference for the proven recipe.
Phase 8 — Composite (L-cut endcard)
-
Trim alignment:
- Each per-product scene ends with her saying the closer at ~14-15s
- Use Whisper word-timestamps to find the natural sentence boundary just before the
final CTA word (e.g. "...beach trip." ends at 13.96s, then "Highly recommend." at
14.28-14.96s)
-
L-cut endcard on the LAST product scene:
- Tanner VISUAL cuts to endcard at the natural sentence boundary (~13-14s into scene)
- Tanner AUDIO continues full length (15s) — final words ("highly recommend") play OVER
the endcard wordmark
- Endcard holds silent for an additional 2-3s after audio finishes
-
Concat order: hook → product1 → product2 → ... → [last product with L-cut endcard]
-
Resolution match: if scenes are mixed resolution (e.g. one 720p budget scene mixed
with 1080p hero scenes), upscale 720p → 1080p with scale=1080:1920:flags=lanczos before
concat. Quality loss is invisible in motion.
-
ffmpeg concat: use concat=n=N:v=1:a=1 filter (re-encode-safe) rather than
demuxer-based concat (which fails if any input differs).
Phase 9 — Captions (DIY karaoke)
- Whisper-transcribe each scene mp4 with
word_timestamps=True and brand-name
initial_prompt bias.
- Offset each scene's word timestamps to its master timeline position.
- Build ASS with karaoke
\kf highlighting (yellow active word, white inactive).
- Style: SF Pro Display Bold, 60pt, ALL CAPS, white→yellow karaoke, MarginV=400
(bottom-third).
- Burn via
ffmpeg -vf "subtitles='X.ass'".
See atoms/captions/add-captions-klap for the proven recipe.
Phase 10 — Music bed
- Generate via FAL ElevenLabs Music endpoint (
fal-ai/elevenlabs/music):
arguments={
"prompt": "[genre + tempo + instrumentation + mood + NO vocals]",
"music_length_ms": master_duration_ms + 500, # 0.5s tail buffer
"force_instrumental": True, # critical — lip-sync VO needs vocal space
}
- Prompt guidance:
- Specify BPM (100-110 for energetic GRWM, 85-95 for chill evening)
- Specify instruments (warm guitar pluck + syncopated drums + dreamy synth pad is a
proven GRWM stack)
- Mandate
Strictly instrumental — NO vocals, NO singing, NO humming, NO ooh-ah
- Mix:
ffmpeg -i master.mp4 -i music.mp3 \
-filter_complex "
[1:a]volume=0.22,afade=t=in:st=0:d=1.0,afade=t=out:st=[END-1.3]:d=1.3[music];
[0:a][music]amix=inputs=2:duration=first:normalize=0[outa]
" -map 0:v -map "[outa]" -c:v copy -c:a aac -b:a 192k final.mp4
normalize=0 is critical — default normalize=1 silently eats the volume filter
(per memory feedback_ffmpeg_amix_normalize.md)
- 22% volume ≈ -13 dB — VO clearly audible, music adds vibe
Cost: ~$0.40 per music gen.
Phase 10.5 — De-AI grade pass (MANDATORY for NB2+Seedance plasticity)
NB2+Seedance pipelines bake plasticity into the output: AI-glossy specular highlights on cheekbones / forehead / nose, over-pushed peachy skin saturation, too-smooth skin micro-surface. A 3-filter ffmpeg pass partially fixes this (~50-60% plasticity perception reduction) at $0 cost. Apply as the default final composite pass on every UGC ad this molecule produces.
-vf "curves=all='0/0 0.25/0.27 0.5/0.5 0.75/0.73 0.85/0.82 1/0.93',eq=saturation=0.88,noise=alls=6:allf=t"
curves — slight shadow lift (0.25→0.27, gives soft shadow detail) + linear mids + highlight compression 0.85→0.82, 1.0→0.93 (the key plasticity fix — kills AI specular shine on skin)
eq=saturation=0.88 — −12% sat (de-pushes peachy AI skin tones toward neutral phone-camera)
noise=alls=6:allf=t — subtle luma grain, temporal (varies per frame, adds micro-texture variation)
How to apply:
- Apply UNIFORMLY across the whole master timeline (avatar clips + endcard) so transitions don't tonally jump
- Apply at the composite stage as part of the concat filter_complex, not as a separate post-pass (one fewer re-encode)
- Use CRF 22-23 on final output — temporal grain costs h264 efficiency. Validated Lineage Video 01: CRF 18 = 232 MB → CRF 23 = 24 MB at 30s 1080p with no visible quality loss
- Burn captions in the same pass — they draw viewer eye away from face (additional plasticity masking)
When NOT to use:
- Real human creator footage — don't degrade authentic footage
- Animated / motion-graphics ads — grain hurts vector aesthetics
- Tabletop product stop-motion — preserve sharp product details
Tunables:
- Stronger AI-tell removal:
noise=alls=10, saturation=0.82, top curve point 1/0.88
- Lighter touch:
noise=alls=3, saturation=0.94, top curve point 1/0.95
Memory: feedback_deai_grade_chain.md. Validated: Lineage Video 01 — recipe in lineage-hb/video-01-variety-pack-kitchen/working/build_master_v2.py.
Phase 11 — QC + delivery
- Run
/watch:watch (or equivalent frame extract + audio check) on the final master
- Verify:
- Lip-sync within ~100ms across all scenes
- Captions in sync with spoken word (within ~200ms)
- Music ducks under VO cleanly — VO intelligible
- No NSFW visual snuck in (body application, water, lather, etc.)
- L-cut endcard lands brand CTA audio over endcard wordmark visual
- Final 9:16 1080p @ 24fps, AAC 44.1kHz stereo
- Upload to gooseworks for share link
- Move to
finals/master-v[N]-captions-music.mp4
Output
finals/master-v[N]-captions-music.mp4 — shippable 9:16 1080p ad
assets/clips/scene-{hook,product1,product2,...}.mp4 — individual scenes
assets/hyperframes/endcard.png + endcard.html — reusable endcard
assets/avatar/portrait-hero.png — locked avatar
assets/music/grwm-bed-v1.mp3 — music bed
working/master-words.json — Whisper transcript with master-timeline word timestamps
- Optional:
storyboard.html with embedded scenes for review
Decision Rules
-
Identity continuity uses image_urls, NEVER video_urls with AI-gen scenes. Passing
a prior AI-generated Seedance scene as video_urls triggers FAL
content_policy_violation: partner_validation_failed. The 60% video-input discount is
real but only applies to REAL HUMAN reference video. For AI-avatar ads, always use
image_urls only. This is the single most important rule of this molecule.
-
NSFW sidestep for body-application products. Water + lather + face + female avatar =
Seedance NSFW reject (validated 6× on BBE early in this project). Reframe ANY scene with
body application as: pump-onto-fingertips, twist-up-and-smell-test, hand-only POV
placement. Avoid: actual face washing motion, leg/arm body application, underarm
application, water visible, lather visible. The prompt must explicitly state these as
negations in the Global Rules block.
-
Default 1080p std tier for hero quality. Skin texture and product label fidelity are
meaningfully better at 1080p vs 720p. Use 720p only if user explicitly requests budget
mode (saves ~55% per scene).
-
Single product per Seedance scene. Multi-product scenes within a single Seedance call
degrade label fidelity rapidly. The hook scene is the exception (it shows all products
together but doesn't go macro on any single label).
-
Vary wardrobe + setting between scenes; lock identity via portrait. Same portrait
reference image across all scenes keeps Clara as Clara. Different wardrobe + setting +
lighting per scene gives the ad visual rhythm. Skill must enforce this in the scene
breakdown phase.
-
End card via HTML hyperframe + L-cut. Don't generate the end card via Seedance —
typography drifts at the brand level. Use HTML+CSS for crisp wordmark. Then L-cut the
endcard 1-2s before the final word so closing CTA audio lands over the brand visual.
-
Music: force_instrumental=True. Seedance lip-synced VO occupies the vocal space.
Vocal music will compete and muddy the mix. Always instrumental for this architecture.
-
Soft skin language only. Block B language must use "tiny natural imperfections,
subtle peach fuzz, faint fine lines" — NOT "freckles prominent", "real-person
imperfections", "lived-in face". The aggressive language amplifies into heavy/blotchy
texture at NB2 + Seedance stages. Validated on BBE v7 → v8 prompt revision.
-
NSFW reject = STOP and surface, do not auto-retry. Per memory
feedback_hf_moderation_surface.md. If FAL returns content_policy_violation, surface to
user with 3 options: rewrite prompt to sidestep, reframe scene as POV (no face), or skip
this scene. Do not silently fall back to a different model or retry the same prompt.
Quality Checks
Before declaring done, verify:
Failure Modes
| Failure | Cause | Recovery |
|---|
FAL 422 content_policy_violation: partner_validation_failed on video_urls | Passed AI-generated scene as video reference | Remove video_urls from payload. Rely on image_urls (portrait) alone for identity continuity. |
FAL 422 nsfw on response (status field) | Body-application + female + water/lather hit classifier | Rewrite scene 3 (application) as smell-test or fingertips-show. Remove water/lather language. Re-fire. |
| FAL 404 on endpoint path | Wrong endpoint slug (e.g. fal-ai/bytedance/seedance-2.0/...) | Use bytedance/seedance-2.0/reference-to-video exactly. No fal-ai/ prefix. |
| Heavy freckles / blotchy skin texture | Block B language too aggressive | Use v8 soft skin language. Drop "freckles prominent", "real-person imperfections". Replace with "tiny natural imperfections, subtle peach fuzz, faint fine lines". |
| Product label garbled / wrong | NB2 multi-image drifted, or wrong resolution | Re-fire at 1080p (label fidelity scales with resolution). Add explicit "product label MUST be sharp and clearly readable" in the scene 2 hero prompt. |
| Mouth moving when not speaking | Default Seedance behavior for portrait + product + camera setup | Add to Global Rules: "Lips remain CLOSED between dialogue beats — no mouth movement when not speaking." |
| Music drowning out VO | Default normalize=1 in amix eats the volume filter | Use amix=...:normalize=0 (per memory feedback_ffmpeg_amix_normalize.md). Set music volume 0.18-0.22 (-15 to -13 dB). |
| Scene exceeds 15s requested | FAL duration param sent as int not string | Send as string: "duration": "15" not "duration": 15. |
| Cinematic slow pacing despite "real iPhone front camera" prompt | Seedance prior leans cinematic | Post-process with ffmpeg setpts=0.66*PTS (1.5x speed) on selected scenes for UGC pacing. OR strengthen prompt with "Casual real-time pace, NOT slow-motion, NOT dolly moves, NOT cinematic." |
| Scenes uniform 15s feel like documentary | 4 cuts in 56s is below Meta's 13-15 cuts in 30s benchmark |
Spend reference (validated on BBE Video 01, May 2026)
| Item | Count | Per-unit | Subtotal |
|---|
| NB2 portrait + 0 variations | 1 | $0.08 | $0.08 |
| Seedance hook scene (1080p, 8s) | 1 | $5.44 | $5.44 |
| Seedance product scenes (1080p, 15s) | 3 | $10.20 | $30.60 |
| Endcard BG via NB2 (optional) | 1 | $0.08 | $0.08 |
| ElevenLabs Music via FAL | 1 | $0.40 | $0.40 |
| DIY captions | — | $0 | $0 |
| Composite (ffmpeg local) | — | $0 | $0 |
| Total | | | ~$36.60 |
Budget mode (all 720p): ~$17-19. Quality drops noticeably on labels — only use if hard
ceiling.
Skill location & related
This molecule: skills/molecules/ugc-ad/create-ugc-style-video/
Related atoms used:
skills/atoms/image-generation/create-image-nano-banana-2-fal
skills/atoms/planning/create-shot-list
skills/atoms/voiceover/format-script-to-style
skills/atoms/video-generation/create-video-seedance-2-fal
skills/atoms/end-cards/create-end-card-from-reference
skills/atoms/assembly/stitch-videos-ffmpeg
skills/atoms/captions/add-captions-klap
skills/atoms/music/create-music-elevenlabs