---
title: "E-commerce Lookbook — cinematic fashion b-roll + a pixel-perfect product-card overlay"
tier: hero
format: short-form-video
theme: commerce | fashion | ecommerce | product
persona: e-commerce brand, fashion creator, DTC marketer, social shopping
duration: "1 product → 30–45s vertical lookbook in ~6–12 min"
budget_usd: "$0.80–$4.00 per reel (5–7 beat keyframes + Ken-Burns/motion + TTS + music + hyperframes overlay)"
caps: ["generate_project", "ltx-q-i2v", "seedance-i2v", "chatterbox-tts", "music", "ffmpeg-concat", "ffmpeg-mux", "hyperframes-render"]
skills: ["short-form-video", "hyperframes-overlays"]
showcases: ["/chapters/ecommerce-lookbook-example.html"]
status: "live (2026-06-09) — rendered E2E. The example reel ('The Camel Trench') was produced exactly via this recipe (Ken-Burns base + a product-card hyperframes-render overlay)."
reliability: 4.4 # Ken-Burns default path: keyframes −0.3, tts+music −0.4, 7 stages −0.4, +0.5 proven E2E showcase; the i2v upgrade path swaps Ken-Burns for video (−0.6) ≈ 3.8
---

# E-commerce Lookbook — cinematic fashion b-roll + a pixel-perfect product card

Point this at a product — a garment, an accessory, a hero SKU — and it builds a **shoppable vertical lookbook**: cinematic AI fashion b-roll for the *feel*, and a single timed-HTML overlay that *is* a real product card. The b-roll carries the styling and the mood; the overlay carries the commerce UI — brand name, a free-shipping badge, the product name + **$189 price**, a ★★★★★ rating, a size selector, an "only 4 left" inventory bar, and a **BUY NOW** button. AI video can never render a legible price or a crisp size selector — and you must **never** trust a model to render a price — so this playbook keeps all of that in the HTML layer.

## What you'll get

> **A finished reel = vertical 9:16 + voiceover + music bed + a pixel-perfect product-card HTML overlay + 30–45s.** Pass `aspect_ratio: "9:16"` to `generate_project` (it threads to every scene; keep the garment consistent across shots with `character_anchor:"always"` + a restated wardrobe — the model often returns 4:3, so the Ken-Burns step cover-crops to exactly 1080×1920, see the note below), animate in waves of ≤4–5 with `resolution:"auto"` (or use the Ken-Burns stills fallback when fal's video tier is flaky), stitch with `create_media model_override:"ffmpeg-concat"`, then lay `chatterbox-tts` narration over a ducked `music` bed with `create_media model_override:"ffmpeg-mux"` + `audio_fill:"loop"` (so audio covers the FULL reel — no silent tail), then composite a single `hyperframes-render` document — the product card — over the whole reel. A silent montage with the price melted into a blurry frame is a draft, not a deliverable — see the `short-form-video` skill's *definition of done* and the `hyperframes-overlays` skill for the overlay pattern.

A 30–45s **vertical (9:16, 1080×1920)** lookbook: a hook → styling beats → detail beat → call-to-action script, 5–7 cinematic beat keyframes of the *same garment*, slow motion (i2v or Ken-Burns), a warm brand VO over a chic bed, **and** a pixel-perfect HTML product card — brand, badge, name, price, rating, size selector, inventory bar, and BUY NOW — that animates in over the reel.

## How the agent should run this (interaction contract)

1. **CONFIRM** — one line: product + price/sizes/rating + the choices that matter (motion path: **Ken-Burns default** vs i2v upgrade; 5–7 beats; voice tone) + "~$0.80–$4.00, ~6–12 min". Commerce data (price, sizes, stock) MUST come from the user — never invent it; that's the one question worth asking.
2. **PREVIEW CHECKPOINT** — the **keyframe contact sheet** (5–7 stills, ~$0.40) **plus the product-card HTML shown as a static frame**. Both before any motion/TTS/music spend — garment drift or a wrong price gets fixed here for cents, not after the mux.
3. **NARRATE** — one line per stage with job_id + ETA ("animating beat 3/6, ~90s each"); poll `get_create_media` every 10–15s; i2v in waves of ≤4–5; flag the hyperframes render ("compositing overlay, ~1–2 min").
4. **FAIL GRACEFULLY** — keyframe 422/timeout: soften prompt → `flux-dev` / `krea-2-large`. i2v hang: `seedance-i2v` → `ltx-q-i2v resolution:"auto"` → **Ken-Burns** (the live showcase shipped on Ken-Burns — state the swap in one line, don't apologize). TTS or music fail → ship VO-only or bed-only and say so. ≤2 retries per clip; partial reel beats nothing.
5. **DELIVER** — final MP4 + one honest note ("commerce UI is pixel-perfect HTML; garment held on N/N beats") + ONE next step: swap the detail beat to a `kontext-edit` of the real product photo.

## The cap chain (the PROVEN recipe)

```
product (the garment / SKU — and its real price, sizes, rating)
  → agent writes the script: hook → styling beats → detail → call-to-action
       (this is BOTH the brand VO AND the on-screen card copy)
  → generate_project           # one cinematic 9:16 fashion keyframe per beat
       aspect_ratio: "9:16"
       character_anchor: "always"     # KEEP THE GARMENT CONSISTENT across shots
       restate the wardrobe in every scene prompt (the camel trench held this way)
       image: gpt-image | flux-dev | recraft-v4 | krea-2-large
  → motion (pick ONE — Ken-Burns is the DEFAULT, i2v is the upgrade):
       (a) Ken-Burns DEFAULT   # ffmpeg zoompan slow-zoom on each 9:16 still → ~7s clips
                               # deterministic, exactly 9:16, zero garment drift. The example reel used THIS.
       (b) i2v upgrade         # create_media action:"animate" — ltx-q-i2v / seedance-i2v, resolution:"auto",
                               # slow cinematic push / fabric drift — or kling-i2v / pixverse-i2v / cosmos-3-i2v.
                               # Worth it for fabric motion; costs reliability (fal video tier is flaky).
  → create_media action:"tts" model_override:"chatterbox-tts"   # warm brand-voice narrator
  → create_media action:"music" lyrics_prompt:"[Instrumental]"  # chic instrumental bed ("downtempo fashion-runway, no vocals")
  → create_media model_override:"ffmpeg-concat"   # stitch the clips → base reel
  → create_media model_override:"ffmpeg-mux" audio_fill:"loop"  # VO over a ducked music bed, covering the FULL reel
  → hyperframes-render         # THE PRODUCT-CARD LAYER — one timed HTML doc over the whole base reel
                               # ≤15s reel → create_media model_override:"hyperframes-render"
                               # >15s reel → call the cap directly (tool /run/hyperframes-render
                               #             or raw SDK /inference) with duration:N
```

## The differentiator — the product-card overlay HTML

`hyperframes-render` runs an agent-generated HTML document in Chromium and composites it over the base reel for `duration` seconds. The whole layer is **one** HTML file driven by CSS `@keyframes`. It doesn't just caption — it reconstructs a real e-commerce product card, with exactly the data a shopper acts on:

- the **brand** ("Maison Atelier") + a **"Free shipping"** badge,
- the **product name + price** ("The Camel Trench · **$189**") — the number that must be exact,
- a **★★★★★ 4.9 (320)** rating row,
- a **size selector** (XS S [M] L XL, M highlighted),
- an **"Only 4 left in size M"** inventory bar (scarcity),
- a **BUY NOW** button.

```html
<!-- product-card overlay: brand · price · rating · size selector · inventory · CTA -->
<style>
  body { margin:0; width:1080px; height:1920px; font-family:'Inter',sans-serif; color:#fff; }
  .badge { position:absolute; top:64px; left:48px; background:#1c1c1c; border:1px solid #c8a16b;
           color:#c8a16b; font-size:24px; letter-spacing:.08em; padding:8px 16px; border-radius:99px; }
  /* the card animates up from the bottom and holds */
  .card { position:absolute; bottom:90px; left:5%; width:90%; opacity:0; transform:translateY(40px);
          background:rgba(14,14,16,.86); border:1px solid rgba(200,161,107,.5); border-radius:22px;
          padding:34px 38px; backdrop-filter:blur(10px);
          animation:rise 6s 2s forwards; }
  @keyframes rise { to { opacity:1; transform:none; } }
  .brand { font-size:26px; letter-spacing:.22em; color:#c8a16b; text-transform:uppercase; }
  .name  { font-size:50px; font-weight:700; margin:6px 0 4px; }
  .price { font-size:50px; font-weight:800; color:#c8a16b; }
  .rating { font-size:30px; color:#ffce54; margin:10px 0 4px; }
  .rating span { color:#aaa; font-size:24px; }
  .sizes { display:flex; gap:12px; margin:18px 0 12px; }
  .sz { width:64px; height:64px; display:grid; place-items:center; border:1px solid #555;
        border-radius:10px; font-size:26px; color:#ddd; }
  .sz.on { border-color:#c8a16b; background:#c8a16b; color:#111; font-weight:700; }
  .inv { font-size:26px; color:#e0524b; margin-bottom:18px; }
  .buy { display:block; text-align:center; background:#c8a16b; color:#111; font-size:34px;
         font-weight:800; letter-spacing:.06em; padding:20px; border-radius:14px; }
</style>
<div class="badge">FREE SHIPPING</div>
<div class="card">
  <div class="brand">Maison Atelier</div>
  <div class="name">The Camel Trench</div>
  <div class="price">$189</div>
  <div class="rating">★★★★★ <span>4.9 (320)</span></div>
  <div class="sizes"><div class="sz">XS</div><div class="sz">S</div><div class="sz on">M</div><div class="sz">L</div><div class="sz">XL</div></div>
  <div class="inv">Only 4 left in size M</div>
  <div class="buy">BUY NOW</div>
</div>
```

**The 15s cap split:** a 35s reel exceeds `create_media`'s 15s `duration` cap. For long reels, call the capability directly — the tool endpoint `/run/hyperframes-render` or raw SDK `/inference` — with `duration: 35`. Reels ≤15s can go through `create_media model_override: "hyperframes-render"`.

## Script structure (beats)

1. **Hook (0–4s)** — the desire, stated cold. "The one coat that finishes every outfit."
2. **Styling beats (2–3, 1 beat each)** — the garment in context: street, café, evening. Same garment, different scene.
3. **Detail beat** — the close-up that sells the make: lapel, stitch, fabric drift.
4. **Call-to-action (last beat)** — the card fully revealed; "Tap to shop The Camel Trench."

## Quality bar

- **Native 9:16** — every keyframe and every clip is 1080×1920, NOT post-cropped from 16:9.
- **Garment consistency** — the *same* coat across every shot, held by `character_anchor:"always"` + a restated wardrobe in each prompt. The example reel's camel trench stayed consistent this way.
- **Deterministic commerce UI** — brand, price, rating, sizes, inventory, and CTA live in the `hyperframes-render` layer. **Never** trust the model to render a price.
- **VO + music** — `chatterbox-tts` brand voice over a ducked chic bed; silent is a draft.
- **30–45s** — long enough to style the look and land the CTA, short enough to finish.

## What can disappoint (cap ceilings)

i2v can shift the garment's cut, colour grade, or drape **mid-clip** even when the keyframe was perfect — i2v style stability is not a promise any cap makes; Ken-Burns is immune. And no image/video model ever renders a readable price — that lives in HTML, always.

## Watch-outs

- **Never put the price (or any commerce data) in the image.** This is the whole point of the playbook. AI text rendering is the hardest known failure mode — a melted "$189" or a garbled size chip destroys trust and conversion instantly. Render price, rating, sizes, and inventory in the HTML layer where they're pixel-perfect every time.

- **Garment drift is the real risk — anchor it.** Any text-to-image model has zero cross-shot consistency by default. Use `character_anchor:"always"`, restate the wardrobe ("a camel double-breasted trench, belted") in every scene prompt, and prefer a reference-image edit (`kontext-edit`) for the detail beat. The example reel's trench held because the wardrobe was restated and anchored.

- **fal video tier is flaky — mitigate, don't fight it.** The video tier has real latency. Mitigations, in order: (1) prompt **image-led** fashion subjects; (2) try alternate video caps (`kling-i2v`, `pixverse-i2v`, `cosmos-3-i2v`, `ltx-q-i2v`); (3) render in **waves of ≤4–5** and poll each to *done*; (4) fall back to the **Ken-Burns stills** path (ffmpeg `zoompan` slow-zoom on each 9:16 keyframe → ~7s clips). The example reel honestly used the Ken-Burns fallback — reliable and exactly 9:16.

- **4:3 keyframes → cover-crop to 1080×1920.** The image model often returns 4:3 even with `aspect_ratio:"9:16"`. The Ken-Burns step's `zoompan`/`scale`+`crop` cover-crops to exactly 1080×1920 — so the base reel is true vertical regardless of what the model returned.

- **`hyperframes-render` runs agent-generated HTML in Chromium with `file://` access.** Only ever feed it **agent-authored** HTML — never paste untrusted third-party markup. Treat the overlay document as code you wrote.

## Cross-surface (MCP / CLI / Webapp)

- **MCP:** `generate_project` (9:16 beats, `character_anchor:"always"`) → `create_media` (animate `resolution:"auto"`, TTS, music) → `ffmpeg-concat` → `ffmpeg-mux` (`audio_fill:"loop"`) → `hyperframes-render` overlay (≤15s via `create_media model_override`, >15s via the cap directly with `duration:N`).
- **CLI:** `livepeer story "<product> lookbook, 9:16, same garment across shots"` → TTS + music via `livepeer media create` → `livepeer media export` to stitch → call `hyperframes-render` for the product-card overlay (long reels via raw `/inference duration:N`). Ken-Burns fallback via `ffmpeg zoompan` if the video tier rejects.
- **Webapp chat:** `make an e-commerce lookbook for <product> with a product-card overlay (price, sizes, BUY NOW)` — the agent drafts the hook→styling→detail→CTA script, renders 9:16 b-roll with the garment anchored, and offers the product-card finishing as a follow-up.

## Execution mode (autopilot / director / auto)

This is a multi-scene project, so pass a `mode` to `generate_project` to control the **pre-finish gate** (after every scene renders, before delivery): `autopilot` (certain brief → ship in one call, no pause), `director` (always pause for a human pick/steer before delivery), or `auto` (recommended — ship UNLESS the auto-critic is unsure: score < `confidence_threshold` (default 0.8), verdict `iterate`, or a flagged shot). Setting `mode` runs the project async (returns a `job_id`); resume a director/auto pause with `review_checkpoint` + `resume_from_checkpoint` (decision `continue` to deliver / `abort` to discard). Omit `mode` for legacy straight-through behavior.
