SuperAPI AI Directory

create-split-screen-creator-ad

General & other

View repository

Updated 10-15 21:54

About this skill

create-split-screen-creator-ad

Purpose

The production line for the 9:16 split-screen creator-ad format: an AI creator narrates while product/demo footage plays above them. Codifies the build proven by perplexity/ads/concept-10-bloomberg-terminal and its sibling concepts (03, 07, 11).

Every scene is the same two-zone vertical split:

9:16 frame · 1080 × 1920
┌──────────────────────────────────┐
│                                   │
│   TOP ZONE  (1080 × 998)          │ ← the scene's product/demo clip
│   product / demo clip             │   CONTAIN-fit; letterbox margins
│   or the hook graphic             │   filled with a darkened blurred
│   (blurred-fill, never bars)      │   cover-scale of the same visual
│                                   │
├───────────────────────────────────┤ ← 3px brand-color divider
│                                   │
│   BOTTOM ZONE  (1080 × 919)       │ ← the AI creator, lip-synced to
│   AI creator talking head         │   the VO, COVER-fit (crop biased
│   (lip-synced to the VO)          │   to top so the face stays framed)
│                                   │
│      [ KINETIC CAPTIONS ]         │ ← burn-in-captions, kinetic-pop
└──────────────────────────────────┘
   → then a full-frame end card

Use it for: creator demos, "I tried X" reaction ads, feature walkthroughs, side-by-side proof ads — anywhere a talking creator should narrate over live product footage.

NOT the right molecule for:

  • A felt-puppet / mascot explainer with text cards on top — use molecules/talking-goose-creator-video.
  • A full-bleed single-shot UGC diary ad (no split, no top clip) — use molecules/ugc-ad/create-ugc-diary-ad.
  • A voiceless full-frame motion ad — use molecules/ugc-ad/create-programmatic-motion-video-ad.

Inputs

  • <brief> — required. What the ad sells, the audience, the platform, the approved claims/CTA. If a script already exists, pass it.
  • <scenes> — required if <brief> doesn't already enumerate. An ordered list of {vo_line, top_visual, top_start?, top_end?}. One scene = one VO sentence/idea + one top-zone visual. Practical range: 5-7 scenes — fewer and it's thin, more and a <45s ad crowds.
  • <creator> — required. The bottom-zone talking head. Either:
    • {anchor_reference} — a path to one high-quality AI-creator portrait still (drives the anchor → lip-sync path), or
    • {ugc_avatar} — a turnkey UGC avatar id (HeyGen / Creatify / Arcads).
  • <voice> — required. {voice_id, model?, settings?}. Voice ID must be in VOICES.md or explicitly approved. Default model eleven_v3.
  • <top_clips> — required. Brand-owned product/demo clips for the top zone. If the brand has its own footage, build the library first with molecules/brand-research/build-brand-clip-library and pass the indexed clips here. The hook scene is usually a designed graphic, not a clip.
  • <end_card> — required. A logo end-card clip or a static brand image.
  • <brand> — {accent_color, divider_color}. accent_color drives the caption punch words; divider_color is the 3px zone divider.
  • <output_dir> — destination project folder.
  • <auto> — bool, default false. If true, passes human gates with prior operator preferences.

Composed Atoms

  • atoms/voiceover/create-voiceover-elevenlabs — the VO, with the with-timestamps endpoint so per-scene timing can be computed.
  • atoms/image-generation/create-image-gpt-image-fal — generate/lock the AI-creator anchor portrait (anchor → lip-sync path).
  • atoms/lipsync/create-lipsync-veed-fal — veed/fabric-1.0, lip-sync the creator to the full VO. (Alternative talking-head source: atoms/ugc-generation/create-ugc-heygen / create-ugc-creatify / create-ugc-arcads — a turnkey avatar that speaks the script directly.)
  • atoms/captions/burn-in-captions — the kinetic-pop style: kinetic creator-native captions, word-for-word with the VO, accent color on the punch word.
  • atoms/end-cards/create-end-card-ffmpeg — build the end card if one was not supplied.
  • atoms/review/watch — frame-grounded QC review of the assembled cut.

See also: molecules/brand-research/build-brand-clip-library (source the top-zone clips), atoms/editing/trim-video-clips (cut clips to length).

This molecule also ships references/assemble.py — the deterministic two-zone assembler (blurred-fill top, divider, cover-fit creator, per-scene clip windowing, end-card trim, optional ASS burn). It is driven by one ad-spec.json (schema in references/ad-spec.md).

Workflow

S0 — Intake

  1. Validate <creator.anchor_reference> (or <creator.ugc_avatar>) exists.
  2. Validate <voice.voice_id> against VOICES.md; if missing and not explicitly approved, STOP and ask.
  3. Validate every <top_clips> path and the <end_card> file.
  4. Create <output_dir> with voiceover/, avatar/, assets/, captions/ subfolders.

S1 — Script + scene plan lock (GATE 1)

  1. Write script/script-locked.md: the clean VO, and a per-scene mapping table — each row is scene # · VO line · top-zone visual · notes.
  2. Budget: ~6 scenes ≈ 35-45s. The hook scene (scene 1) is usually a designed stat/claim graphic; the rest are product/demo clips.
  3. For every scene, name the exact top visual and confirm it shows what the VO line says (this is the #1 quality lever — see Decision Rules).
  4. HUMAN GATE. Any change after this invalidates downstream artifacts.

S2 — Voiceover

  1. Run create-voiceover-elevenlabs with the with-timestamps endpoint and the chosen <voice>. Save voiceover/vo.mp3 + the timestamp JSON.
  2. Apply any speed adjustment (creator-native VO often reads ~1.15-1.2×).
  3. Slice into per-scene boundaries from the character timestamps; write voiceover/timing.json — {"scenes":[{"scene":N,"start":s,"end":e}]}.

S3 — Creator talking head

  1. Anchor path: generate 2-3 AI-creator portrait takes with create-image-gpt-image-fal, lock one, then run create-lipsync-veed-fal on the full VO → one creator video covering the whole ad.
  2. UGC-avatar path: drive create-ugc-* with the script + voice → the talking-head video directly.
  3. Lip-sync must cover the entire VO duration in one continuous take — the assembler slices it per scene by timing.json.

S4 — Top-zone visuals + end card

  1. Gather the product/demo clips for scenes 2..N (from the brand clip library). Each clip stays 16:9 — the assembler contain-fits it.
  2. Render the hook graphic for scene 1 (a designed stat/claim card).
  3. Confirm or build the end card (create-end-card-ffmpeg).

S5 — Assemble (GATE 2)

  1. Write ad-spec.json (schema: references/ad-spec.md): canvas, divider color, the creator lip-sync video, timing.json, the per-scene top visuals, and the endcard. Leave captions_ass unset for now.
  2. Run python3 references/assemble.py ad-spec.json → the precaption cut.
  3. Review the precaption cut with atoms/review/watch. Check, per scene: does the top clip show what the VO says? Are there black bars? Does the last frame end clean? Fix per the Decision Rules and re-assemble.
  4. HUMAN GATE. Operator approves the precaption cut.

S6 — Kinetic captions

  1. Run the burn-in-captions atom on the assembled precaption video: caption.py --video <precaption>.mp4 --style kinetic-pop --accent "<brand.accent_color>". It transcribes the cut's own audio (fal Whisper, word-level), builds kinetic chunks, and burns them.
  2. Transcribe the assembled video, not the raw VO file — concat drops the inter-scene silence, so the ad timeline differs from the VO timeline. Only the final cut's audio yields correctly-synced caption timing.
  3. Optionally pass --emphasis "<brand>,<product>,<numbers>" to force the punch words. For a hand-tuned caption track, build the ASS yourself and set captions_ass in ad-spec.json so assemble.py burns it directly.
  4. Promote the captioned render to <output_dir>/<name>-final-ad.mp4. Keep the -precaption.mp4 and the .captions/ sidecar for re-caption passes.

S7 — Review + deliver (GATE 3)

  1. Run atoms/review/watch on the final captioned ad. Verify the Quality Checks below.
  2. Write manifest.json (the Output Manifest Standard).
  3. HUMAN GATE. Operator confirms ship. This molecule stops before any publishing step.

Decision Rules

  • Top clip shorter than its scene → do NOT loop it (looping replays into sparse/black tails). Set top_start/top_end to the on-message window; assemble.py speed-fits that window to the scene length.
  • Top clip content drifts from the VO line → reseek with top_start so the relevant moment lands under the words, or swap the clip. The top visual must match what the creator is saying — flag every mismatch in S5 review.
  • Hook scene → use a designed graphic (stat/claim card), not raw footage.
  • End-card clip fades to black → set endcard.clip_end to the last sharp second; the assembler clone-holds that frame so the ad never ends on a black rectangle.
  • Captions cover the creator's face → kinetic-pop already sits low (margin_v_pct 0.12); if a specific creator is framed high, lower further.
  • Whisper mis-splits numbers/brand names (e.g. $25 + ,000) → merge in a caption patch pass or pass --emphasis and correct the .ass sidecar.
  • Prefer composed atoms over re-implementing provider calls in this molecule.
  • Keep all three human gates.

Output

<output_dir>/
├── script/
│   └── script-locked.md
├── voiceover/
│   ├── vo.mp3
│   ├── vo_timestamps.json        # char-level from ElevenLabs
│   └── timing.json               # per-scene start/end
├── avatar/
│   └── creator-lipsync.mp4       # full-VO lip-sync take
├── assets/
│   └── scene-01-graphic.png      # hook graphic
├── captions/
│   └── karaoke.ass               # kinetic-pop ASS (sidecar)
├── ad-spec.json                  # assembler input
├── <name>-final-ad.mp4-precaption.mp4   # before captions (re-burnable)
├── <name>-final-ad.mp4           # delivered ad
└── manifest.json

Quality Checks

  • Final video is <canvas> (default 1080×1920), h264 + AAC, 30fps; duration matches the VO + end card within ±0.5s.
  • Two-zone layout holds every scene; the divider is visible; the top zone has no black bars (blurred-fill present).
  • Every top clip plausibly matches its VO line (S5 review confirmed it).
  • Captions are word-for-word with the VO, kinetic, accent color on punch words, and do not cover the creator's face.
  • The final frame is a clean end card — no black rectangle, no fade-to-black artifact.
  • No clip loops into a sparse/black tail.
  • manifest.json exists and its output_files resolve.

Failure Modes

Symptom Likely cause Fix
Veed Fabric 403 on storage auth Too many parallel lip-sync calls Run lip-sync sequentially with sleep 3 between calls
FAL "User is locked / exhausted balance" FAL credits depleted Top up at fal.ai billing; the error body is explicit
Black bars around the top clip Assembler not used, or charcoal-pad fallback Use references/assemble.py; it blurred-fills the letterbox
Top clip goes black/sparse mid-scene Clip shorter than the scene, looped Set top_start/top_end; the assembler speed-fits the window
Last frame is a black rectangle End-card clip fades to black Set endcard.clip_end to the last sharp second
Captions out of sync with the VO Transcribed the raw VO file, not the cut Transcribe the assembled video — concat drops inter-scene silence
Caption text doesn't match the VO words Used an old/paraphrased script kinetic-pop transcribes the actual audio; never hand-type caption text
Numbers split mid-caption ($25 / ,000) Whisper word tokenization Patch the .ass sidecar; merge the tokens
Creator face cropped oddly in the bottom zone Lip-sync framing too tight Re-frame the anchor portrait (head-and-shoulders, centered)

Reference build

perplexity/ads/concept-10-bloomberg-terminal/ — the canonical build of this format: 6 scenes, AI creator (Arlo voice) over Perplexity product clips, kinetic captions, logo end card. Concepts 03/07/11 are sibling builds.