Skip to main content
skill CX Codex

founder-product-video — Claude Code skill: founder video from a URL

Produces a 65-second product video with a talking founder, then overlays the real product screens. Takes a product URL plus founder details and a photo.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add Pika-Labs/Pika-Plugins --skill founder-product-video -a claude-code
Open on GitHub

What founder-product-video does

The skill builds a 65-second clip: four 15-second SeeDance acts of a founder on camera, a 5-second branded end card, and background music. Input is a product URL plus imagery from the user. Product screenshots and brand wordmarks get composited onto reveal shots after generation, so the visible UI stays legible instead of being invented by the model.

Every step runs through Pika MCP — generation, render, captions, concat, audio mix. A brand kit folder is also required: either brand.json or an export from build-a-brand holding brand.md, tokens and logo files. If none exists, the skill calls build-a-brand first. Required inputs are the product URL, the founder's name and role, and a photo (a path, a link, or generate for an auto-made portrait).

Before the first paid call the skill checks the balance and shows an estimate: roughly 4 000 credits for a typical four-act run. Nothing is spent until the user answers proceed. In non-interactive runs the config must carry cost_ack=proceed, otherwise the skill stops at the estimate.

What it helps with

  • shoot a founder pitch video for a product page
  • put real interface screenshots into an AI-generated clip
  • render a vertical or square cut for social
  • burn in captions and add music to the result
  • batch-render videos from CI without prompts

Example prompts for the agent

  • Make a 60s founder video for https://example.com, photo at ~/Pictures/eli.jpg
  • Build a founder video: Eli Kim, CEO, use generate for the portrait, brand kit in ./brand
  • Render a 9:16 talking founder explainer with captions from brief.md

How to install founder-product-video

1Skills CLI (Vercel)

npx skills add Pika-Labs/Pika-Plugins --skill founder-product-video -a claude-code

2Manually: put the files in place

~/.claude/skills/founder-product-video/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/founder-product-video/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about founder-product-video

How to install founder-product-video in Claude Code?

Run npx skills add Pika-Labs/Pika-Plugins --skill founder-product-video -a claude-code. The skill lands at ~/.claude/skills/founder-product-video/SKILL.md.

What does founder-product-video do?

It makes a 65-second product video: four acts of a talking founder, a branded end card, background music. Your screenshots are composited after generation, so the UI on screen is the real one.

What do I need before running it?

A connected Pika MCP, a brand kit folder, the product URL and the founder's name, role and photo. With no kit, the skill runs build-a-brand first.

Source text

SKILL.md · Apache-2.0
---
name: founder-product-video
description: >-
  Use when the user asks for founder product video or a task matching the examples below.
  Generate a 65-second founder-style product video from a product URL + user-supplied imagery.
  Output is a 16:9 1080p MP4 — 4 × 15s SeeDance acts of a talking founder + 5s branded end card +
  background music. The user's actual product screenshots are composited onto product reveal shots
  after Seedance generation, so readable UI and brand text are real, not AI-imagined. Triggers — "founder video", "product video",
  "60s pitch video", "make a video of [founder] for [URL]", "talking founder explainer". Requires
  Pika MCP. Uses a supplied brand kit folder (`brand.json` or an exported build-a-brand kit with
  `brand.md`, tokens, logo assets); if no kit exists, run build-a-brand first.
argument-hint: <product-url> --founder "<name, role>" [--photo <path|url|generate>] [brand-kit=<path>] [aspect=16:9|9:16|1:1] [--quick] [--config <path>]
required-capabilities:
  - add_captions
  - analyze_brief
  - analyze_media
  - capture_website
  - edit_audio_mix
  - edit_concat
  - edit_video_compose
  - edit_text_overlay
  - extract_frame
  - generate_image
  - generate_music
  - generate_reference_video
  - generate_slide_animation
  - html_to_png
  - identity_balance
  - render_html_animation
  - task_status
  - task_cancel
  - upload_asset
---

# founder-product-video

You generate a 65-second founder-style product video from a product URL plus user-provided imagery: 60 seconds of talking-founder body video plus a 5-second branded end card. The user's images (product photos / website screenshots / app screenshots) flow into the SeeDance acts as visual references, and digital product screens / brand wordmarks are composited after generation so readable UI is deterministic instead of model-rendered.

No cutaways. No website CSS extraction. AI generation, deterministic render, captions, concat, and music mix go through Pika MCP tools by default. Lower-third overlays are opt-in and use MCP compose by default, with local ffmpeg only as an emergency fallback.

## Cost transparency gate

Before any paid MCP call, call `identity_balance({verbose: true})` once. Surface the current balance, recent burn rate, and remaining runway, then gate the run with this exact message:

> Estimated cost: about 4,000 credits (~$40) for a typical four-act Seedance founder video plus supporting assets. This exceeds $5, so Reply `proceed` to continue or `cancel` to stop.

Do not call any paid MCP tool until the user replies `proceed`. If the user replies `cancel`, stop without generating. For non-interactive `--quick` or `--config` callers, require `cost_ack=proceed` in the config; if it is absent, stop with the estimate instead of spending credits.

## [0] Intake — run first, before any pipeline step

**If invoked with empty args**, print this menu verbatim and stop — wait for the user to paste inputs:

> **What founder video do you want to make?** Required:
> - **Product URL** — `https://...` (anything with a real homepage)
> - **Founder** — name + role, e.g. *"Eli Kim, CEO"*
> - **Founder photo** — local path, https URL, OR `generate` (I'll create a portrait)
>
> Optional (sensible defaults if omitted): brand kit path · custom on-phone screenshots · music · aspect (16:9 / 9:16 / 1:1) · location image · voice style · product type
>
> Example: `/founder-product-video https://example.com --founder "Eli Kim, CEO" --photo ~/Pictures/eli.jpg`

**If args carry partial input in interactive mode**, skip the menu and gather the missing required fields by asking one at a time — ask, wait, ask the next. Don't bundle questions into one block. If the user supplies a field unprompted (e.g. they pasted a URL in the trigger message), skip that question and confirm the value back to them once at the end. Don't start the pipeline until all required fields are answered. If the non-interactive fast lane applies, use step [0.5] instead.

### [0.5] Non-interactive fast lane

Use this path when the caller passes `--quick` or `--config <path>`, or when the
caller states they are running from CI, a subagent, a batch job, or any other
non-interactive harness.

This section has precedence over the interactive ask/wait instructions below.
When it applies, use this fast lane and do not fall through to the multi-turn
intake unless `url` or founder name/role is truly missing.

- `--config <path>` points to a JSON file with pre-baked values for the canonical
  input contract: `url`, `brand_kit_path` or `build_brand`, `founder_name`,
  `founder_role`, `founder_photo`, `assets`, `music_url`, `aspect_ratio`,
  `location_image_url`, `voice_style`, `product_type`, and `lower_third`.
- `--quick` means use defaults for optional extras, auto-build the brand kit with
  `build-a-brand --quick` if `brand-kit` is omitted, and use `founder_photo =
  "generate"` when no photo is supplied.
- For `--quick` or `--config`, do not stop for confirmation at the brand-kit
  branch, founder-photo generation prompt, optional-extras prompt, script
  choices, or end-card/caption defaults. Record assumptions inline and continue.
- If `url` or founder name/role cannot be found in args or config, stop once with
  a single compact missing-fields list instead of starting a multi-turn Q&A loop.

**1. Product URL** *(required)* — `https://...`. Used to (a) derive the brief in step [1] and (b) feed the brand-kit branch below.

**2. Brand kit** *(required)* — interactive mode: ask *"Do you already have a brand kit folder, or should I build one first?"*
- If a path -> use it (`state.brand_kit_path = <path>`). Accept either `brand.json` or an exported `build-a-brand` kit containing `brand.md`, `tokens/tokens.json`, and logo assets.
- If "build" -> invoke the `build-a-brand` skill on the URL/brief and wait for the exported brand kit. This is a full identity workflow and may pause for user choices; surface those prompts in interactive mode.
- Fast lane: if config provides `brand_kit_path`, use it. If config sets `build_brand` or `--quick` omits `brand-kit`, invoke `build-a-brand --quick` on the URL/brief and wait for the exported brand kit; do not surface build-a-brand prompts or stop for identity choices. After either branch, set `state.brand_kit_path`. Only stop with a single compact missing-fields list if there is no path and the brand kit cannot be built.

**3. Founder identity** *(required)* — interactive mode: ask all three together:
- `founder_name` — e.g. "Avery"
- `founder_role` — e.g. "CEO, ExampleCo"
- `founder_photo` — local path / https URL / OR the literal string `generate` to auto-create a portrait. If `generate`, prompt the user for a 1-line vibe ("warm, casual smart attire" / "Pixar-style 3D animation" / etc.) — this becomes the seed prompt for `generate_image` in step [4].
- Fast lane: use founder values from args/config. If `founder_photo` is omitted, set `founder_photo = "generate"` and use a neutral founder-portrait vibe derived from the product tone; do not stop for a separate photo-vibe prompt.

Default to no lower-third so the happy path stays lean. If the user explicitly asks for a lower-third, record `state.lower_third = true`; in interactive mode confirm that `edit_video_compose` will add the transparent overlay after rendering.

**4. Optional extras** — interactive mode: offer these once as a single message, then proceed without waiting if no answer comes back in the same turn. Fast lane: use the defaults below without asking.
- *Custom imagery* — list of `assets` (product photos / app screenshots) shown on the founder's phone. **Default if omitted:** use screenshots from `brand.json.screenshots` when present, otherwise look for obvious screenshots or product images inside the brand kit, otherwise capture the product URL with `capture_website(mode:"screenshot")` before step [2]. Do not proceed to script or SeeDance without real product UI / product imagery unless `product_type` is explicitly `service` and the user accepts an environment-only video. In the fast lane, if no supplied/brand-kit/captured asset exists, stop once with a compact missing-assets error instead of silently shipping a generic talking-head video.
- *Music* — local path / https URL / OR `generate` (instrumental, ~60s). Default: `generate` via Kling background mode.
- *Lower-third* — optional. Default: off. If enabled, render the transparent `.mov` through MCP and overlay it onto the body with `edit_video_compose`.
- *Aspect ratio* — `16:9` (default), `9:16`, `1:1`.
- *Location* — defaults to a flat seamless backdrop in `state.brand.colors.accent` (clean studio-shoot look, character against a single brand color, whatever the brand's accent is). Override with a path / URL / text description if the user wants office, outdoor, etc.
- *Voice style* — VO direction string for SeeDance, e.g. "warm authentic founder energy, conversational". Default: derived from `brief.tone`.
- *Product type* — `digital | physical_apparel | physical_object | consumable | service`. Default: auto-derived in step [2] from asset analyses.

After Stage 0 completes, store all gathered values in `state.inputs`. If you already created a local work directory for this run, optionally persist the same object as `<workdir>/inputs.json`; do not require a predefined work-directory environment variable. Then enter the pipeline at step [1].

### [0.6] Avatar-type probe for founder photos

Before any paid `generate_reference_video` call, run this Avatar-type probe on the resolved founder photo/avatar URL after local upload or user-supplied URL normalization. This applies to any founder photo used as the character reference — whether supplied via `--photo` or generated.

Call `analyze_media` once:

```
query: "Classify this image for paid video generation. Is it a photograph of a real human face, an AI-generated realistic portrait, a stylized / illustrated character, or a recognizable trademarked / copyrighted character such as Batman, Pikachu, or Mickey Mouse? Return strict JSON only: { \"avatar_type\": \"real_human\" | \"ai_realistic\" | \"stylized_illustrated\" | \"recognized_ip\", \"recognized_character\": string | null, \"moderation_risk\": \"low\" | \"medium\" | \"high\", \"recommendation\": \"proceed\" | \"warn\" | \"reject\" }. Use null for `recognized_character` when no specific character is recognized; never write \"none\", \"unknown\", or explanatory prose in that field."
```

Route from the result:
- **recognized IP / copyright risk** -> **STOP only when** `avatar_type` is `"recognized_ip"`, or `recognized_character` names a specific character (for example `"Batman"`), or when both `moderation_risk` is `"high"` and `recommendation` is `"reject"`. Treat `recognized_character: null`, empty string, `"none"`, `"unknown"`, `"n/a"`, and low/medium `moderation_risk` as not enough to stop by themselves. Run this check before the real/stylized routes. A chibi Batman is still Batman even when `avatar_type` is stylized / illustrated.
- **real human / AI-generated realistic** -> proceed normally.
- **stylized / illustrated** -> proceed with a visible warning that stylized avatars may be less reliable for Seedance likeness and moderation, then continue only if the user supplied or accepted that avatar.
- **trademarked / copyrighted** -> **STOP** before generation. Surface this message: `Your founder photo appears to be a trademarked character ([X]). Most video providers will moderate this and refuse to generate. Pass --photo <real-looking-photo-url> to override.` For this skill, `--photo <real-looking-photo-url>` is the accepted concrete flag; you may also mention the cross-skill `--avatar <real-looking-photo-url>` wording because users may know that convention.

## Required inputs (canonical contract)

After Stage 0, these are the fields downstream steps consume:

- `url` — the product website (https://). Drives step [1] brief.
- `brand_kit_path` — brand kit folder. Required. End card AND lower-third consume `brand.json` when present, otherwise `brand.md`, `tokens/tokens.json`, and logo assets from a `build-a-brand` export. See step [4.5].
- `founder_name` + `founder_role` + `founder_photo` — required from intake. Step [4] normalizes `founder_photo` into `founder_photo_url` and `character_url` before any SeeDance call.
- `assets` — optional array of `{ url, role?, caption? }`. Defaults to the screenshots captured by the brand kit; when the brand kit has no screenshots, capture the product URL before step [2] and store the returned `image_url` as a real product UI asset. `role` is a hint string mapping the asset to a script beat (`hero`, `feature_a`, `cta`, etc.).
- `location_image_url` — optional. Defaults to a generated solid-color backdrop in `state.brand.colors.accent`.
- `music_url` — optional. Defaults to `generate` (Kling 60s background bed in step [7]).
- `aspect_ratio` — default `16:9`.
- `voice_style` — optional, defaults to `brief.tone`.
- `product_type` — optional, auto-derived in step [2].

## State

Keep a simple `state` object as you work and save every CDN URL there so a partial run can be resumed. Treat `task_status` value `completed` as the successful terminal state (`failed` and `cancelled` are the failure terminals), then unwrap `result.structuredContent` when present. The final video lives on Pika's CDN; no local workspace is required unless MCP compose is unavailable and you explicitly trigger the local lower-third fallback in step [8b].

## Long-running task_status polling

When any long-running generation or edit call returns a `task_id` with or without an initial status, including `{task_id}`, `{task_id, status: "queued"}`, or an initial `queued`, `running`, or `processing` status, record the task id and start time immediately in `state`.

- Call `task_status({task_id})` in a tight loop until terminal (`completed | failed | cancelled`). No manual sleep and no Bash polling; the worker holds each status call open.
- Emit ONE visible progress line every 60s while status is `queued`, `running`, or `processing`: `Seedance i2v queued for {N}m {S}s... still processing`. Replace the provider/stage label when polling music, captions, render, concat, mix, or edit tasks.
- On `completed`, unwrap the returned result URL and save it into `state`.
- On `failed` or `cancelled`, surface failure to the user with `task_id`, status, and the last status message.
- After 15 min total from the original submit, call `task_cancel({task_id})` if the task is still non-terminal, then surface failure to the user. If cancel reports the task is already terminal, call status once more and report that terminal result.
- Do not submit a duplicate request while the original task is still `queued`, `running`, or `processing`.

## Pipeline overview

```
[Stage 0] intake          you (Claude): ask user for url + brand-kit (path or build) + founder (name/role/photo) + optional extras
  → [0.5] brand-kit auto-build (only if user said "build")
                          invoke `build-a-brand`; in non-interactive mode use `build-a-brand --quick`
  → [1] analyze_brief             pika MCP: product name + tagline + features + tone + CTA
  → [2] resolve product UI assets pika MCP: use supplied/brand-kit screenshots, or capture_website(product URL)
  → [2] analyze_media × N         pika MCP: understand what each real asset shows
  → [3] write script              you (Claude): 4 acts × 15s; map assets to acts
  → [4] founder/location refs     pika MCP: upload or generate founder ref; carry supplied custom location
  → [4.5] brand-kit ingestion     parse brand.json OR brand.md + tokens → state.brand; generate default brand-accent location if needed
  → [5] generate_reference_video × 4 IN PARALLEL  pika MCP: SeeDance acts, asset images as refs
  → [5.5] digital UI overlays     pika MCP: composite real product UI / wordmark onto digital reveal acts + OCR QA
  → [6] edit_concat acts          pika MCP: 60s stitched base (dialogue-only audio)
  → [7] generate_music            pika MCP: Kling 60s soft instrumental background bed
  → [8] captions / lower-third    pika MCP: add_captions for subtitles; render lower-third as transparent .mov, then overlay it with edit_video_compose when lower-third is enabled.
  → [9] render_html_animation     pika MCP: 5s end card — author inline HTML, brand-kit fonts inlined, aspect matches body, no corner clutter, CSS @keyframes (NOT GSAP)
  → [10] edit_concat + audio_mix  pika MCP: concat body + end card, then mix music over the full ~65s
  → [10.5] final duration probe   pika MCP: analyze final_url and enforce the 55s duration floor before delivery
  → [11] final_url                save the MCP returned final_url; upload only if a local fallback created the final MP4
  → [12] deliver
```

## Operational notes

Keep the main workflow focused on sequencing. Historical server validation details live in `references/ops-notes.md`; only the active constraints stay here:

- Use a unique `seed` per SeeDance act (101, 202, 303, 404). Identical generation params can replay cached failures.
- Kling music bed generation uses `provider: "kling-audio"`, `mode: "text_to_audio"`, `background: true`, and `duration_seconds: 60`; the MCP worker generates one 10s Kling seed and extends it locally.
- If SeeDance rejects a real-person founder photo, re-roll the founder ref with stronger stylization rather than retrying the same rejected reference.
- For local brand-kit logos, upload only logo-appropriate raster assets (`image/png`, `image/jpeg`, or `image/webp`). Do not send SVGs to `upload_asset`; choose the PNG export from `build-a-brand` or rasterize first.
- Use CSS `background-image: url(...)` for CDN-hosted logo/photo assets in end-card HTML; `<img crossorigin>` is blocked by CDN CORS.
- Use server-side deterministic tools for captions, lower-third compose, concat, and mix. Local ffmpeg is only the fallback if `edit_video_compose` is unavailable while `state.lower_third = true`.
- Decompose every 15s act into 3 time-coded sub-shots. Single-shot acts look static.
- Open each act with the style-match location framing and repeat the same `WARDROBE LOCK:` sentence across all 4 act prompts.

## [1] Analyze brief

```
analyze_brief(
  sources=[{ type: "url", url: <product_url> }],
  context: "Founder-style 60-second product video. Need: product name, one-line tagline, 3-5 key features, target audience, brand tone, and a call-to-action."
)
```
Save the result as `brief`. You'll reference `brief.product_name`, `brief.tagline`, `brief.key_features`, `brief.tone`, `brief.call_to_action` throughout.

## [2] Resolve product UI assets, then analyze each asset + derive `product_type`

Before analyzing assets, normalize `assets` so product reveal shots have a real visual reference:

1. Use any caller-provided `assets` first.
2. If none were supplied, read screenshots from `brand.json.screenshots` when present.
3. If `brand.json` has no screenshots, look for obvious raster screenshots or product images inside the brand kit (`screenshots/`, `assets/`, `product/`, or image files named like `hero`, `screen`, `app`, `dashboard`, `product`).
4. **When `assets` is empty after those checks, call `capture_website` on the product URL**:

```
capture_website(
  url: <product_url>,
  mode: "screenshot",
  mobile: false
)
# Save result.image_url as assets[0].url with role="website_capture".
```

If the product is likely mobile-first, also run a second capture with `mobile: true` and keep both URLs when available. Save these as real product UI assets before continuing.

Do not proceed to script writing, `generate_reference_video`, or any paid SeeDance call without at least one real product UI / product imagery asset, unless the caller explicitly set `product_type: "service"` and accepted an environment-only video. If capture fails or returns no `image_url`, surface: `Could not capture <url>. Please provide screenshots or hosted product assets; founder-product-video will not silently ship without real product UI.`

For each entry in `assets`, run `analyze_media` to extract content + visual style + **asset type**. Run all in parallel in one tool batch:

```
analyze_media(
  media: <asset.url>,
  query: 'Describe this product image briefly. Return STRICT JSON:
  {
    "content_description": "1-line summary of what is visible",
    "asset_type": "digital_screen | physical_apparel | physical_object | consumable | infographic | other",
    "key_elements": ["3-5 specific UI elements / features / objects in the image"],
    "visible_copy": "any text visible — heading, button label, tagline, t-shirt graphic text (or empty string)",
    "primary_colors": ["#hex", "#hex", "#hex"],
    "vibe": "1-line visual feeling",
    "best_for_act": "hook | problem | solution | proof"
  }
  Return ONLY the JSON.'
)
```

`asset_type` decoder:
- `digital_screen` — app UI / website screenshot / SaaS dashboard / mobile app capture
- `physical_apparel` — t-shirts, hoodies, hats, anything wearable (model + garment)
- `physical_object` — gadgets, accessories, packaged goods, anything held in hand
- `consumable` — food, beverages, supplements (something used/eaten/drunk)
- `infographic` — chart, diagram, data viz, illustration
- `other` — anything else; describe and pick best fit

Save as `asset_analyses[i]`.

After analysis, build:

```
usable_product_assets = asset_analyses
  .map((analysis, i) => ({
    asset_index: i,           # original assets[] index to use in script.shots[].asset_index
    asset_url: assets[i].url, # public URL passed to reference_images later
    asset_type: analysis.asset_type,
    analysis
  }))
  .filter(entry.asset_type in [
    "digital_screen",
    "physical_apparel",
    "physical_object",
    "consumable"
  ])
```

If `usable_product_assets` is empty and you have not already tried a URL capture, call `capture_website(mode:"screenshot")` on the product URL, append the returned `image_url` to `assets`, run `analyze_media` on that capture, save the analysis at the same new index, and rebuild `usable_product_assets`. The captured screenshot must therefore have its own `asset_index`; do not reuse a logo/hero/infographic index for a product reveal.

Do not auto-derive `product_type = "service"` from logo-only, hero-only, infographic, abstract brand, or `other` assets. Those are not real product reveal anchors. If `usable_product_assets` is empty after the capture attempt, stop unless the caller explicitly set `product_type: "service"` and accepted an environment-only video. Surface the missing-assets error instead of falling through to the service reveal pattern.

### Derive `product_type`

Look at the dominant `asset_type` across `usable_product_assets`:

```
product_type = mode(usable_product_assets[i].asset_type) → mapped to {
  digital_screen → "digital"
  physical_apparel → "physical_apparel"
  physical_object → "physical_object"
  consumable → "consumable"
}
```

If user passed `product_type` explicitly, use that and skip auto-derivation; `service` is valid only when explicitly chosen/accepted. The `product_type` value drives **which shots are picked in step [3] and how the founder reveals the product in step [5]**. Get this right or the video shows the wrong thing on screen.

## Product type → reveal pattern (the most important table in this skill)

`product_type` (set in step [2]) controls which shots to pick AND how the asset is revealed in each shot. **The reveal beat in the SeeDance prompt is product-specific; using the wrong one makes the founder hold a phone for a t-shirt brand.**

For `digital` products, the SeeDance prompt is only responsible for the founder, camera move, phone gesture, and a blank / neutral screen placeholder. **Do not ask Seedance or the video model to render readable brand wordmark or product UI text.** The real screenshot, product UI, and exact brand spelling are composited in step [5.5].

| product_type | Reveal shots | Reveal beat (used in SeeDance prompt) | Which acts get assets |
|---|---|---|---|
| `digital` | C-phone, E-phone | "founder lifts her phone toward camera; the phone has a blank neutral screen placeholder reserved for the real UI overlay; do not render readable UI text or brand wordmark" | shots C and E only |
| `physical_apparel` | G-hold, G-wear, E-detail | "founder lifts a charcoal-washed graphic tee toward camera; the shirt design exactly matches @ImageN — match the print/graphic exactly, do not invent" OR "founder is wearing the t-shirt from @ImageN — match the print exactly" | EVERY shot where a t-shirt is visible (C/E/F + the "wearing" variants) |
| `physical_object` | C-hold, E-detail, F-twoshot | "founder holds the [product name] up toward camera; the product exactly matches @ImageN — match shape, color, branding" | shots that show the product |
| `consumable` | C-hold, E-detail, H-using | "founder holds/uses the [product]; the packaging/product matches @ImageN exactly" | shots that show the product |
| `service` | A, B, D, F (environment) | no specific product reveal — focus on founder + environment | none of the shots reference assets |

For physical products, every shot where the product appears in frame should pass that asset as a reference image; otherwise SeeDance tends to invent a generic-looking product. For apparel, if the founder is wearing a t-shirt and the script says "we make t-shirts", the founder's t-shirt needs to reference one of the assets even in shots that are not reveal moments. Pass the asset URLs in `reference_images` for those acts and write prompt language like "the founder is wearing the t-shirt from @Image3 — print matches exactly".

## [3] Write script + character voice + per-shot asset + per-line beats (you do this — no model call)

Three sub-products, all written by you (Claude) in one inline JSON:

1. **`character_voice_profile`** — 3-4 lines describing the character's DEFAULT delivery (carries through every act for consistency)
2. **Per-shot `asset_index` + `reveal_beat`** — what asset is visible in this shot and how it's revealed
3. **Per-shot `beats[]`** — line-by-line acting direction with `emotion` + `physical` + silence beats between sentences

This is what separates a generic AI-talking-head from a character that actually feels intentional. Read all four sub-sections below ([3.0] founder voice, [3a] character voice profile, [3b] beats, [3c] transitions, [3c.1] acting energy, [3d] full JSON) before writing.

### [3.0] Founder voice — write a PITCH, not a feature list

The single most common failure mode in this skill is dialogue that reads like a marketing-page bullet list ("It can reason. Code. Even write your emails. No proxies. No selectors. No maintenance. Plug it into LangChain. LlamaIndex. MCP. Twenty-four thousand stars on GitHub. MIT licensed. Production-grade.") — clean copy, but it's not how a founder talks. Field feedback: *"the script sounds like a list of features, not like a founder would sell their product on camera."*

Real founders pitching their own product on camera use:
- **First-person ownership** — "I built", "we shipped", "we use it ourselves", "honestly we just want this everywhere"
- **A personal stake or origin moment** — Act 1 should reference a frustration the founder lived through, NOT the product abstractly. "Every time I tried building X, I hit the same wall" beats "X is hard."
- **Conversational connectives** — "look", "honestly", "the thing is", "so", "actually", trailing "..." for thinking. These are throwaway words in writing but the breath of natural speech.
- **A "bet" framing for the product** — "what if X just worked?", "we asked ourselves", "the whole idea was". Founders frame their product as an answer to a question they asked themselves, not as a list of capabilities.
- **One concrete anchor** — a specific number, a specific time, a specific scenario. "24 thousand devs starred it last year" beats "it's popular." "At 3 AM the layout breaks" beats "scrapers are unreliable."
- **Invitation-energy CTA** — "come try us", "go play with it", "we just want it everywhere". NOT "stop scraping. start extracting." (that's a Don Draper tagline, not a founder).

**Banned patterns** (each was empirically called out by the user, do not repeat):

| ❌ Banned pattern | Example | Why |
|---|---|---|
| Triple-negation chant | "No proxies. No selectors. No maintenance." | Feels like a marketing chant, not human speech |
| Capability staccato | "It can reason. Code. Even write your emails." | Reads as a feature checklist |
| Integration-list-as-pitch | "Plug it into LangChain. LlamaIndex. MCP." | Listing integrations is fine ONCE in passing — never as a 3-beat hook |
| Tagline closer | "Stop scraping. Start extracting." | Pure ad-copy. Founders close with invitation, not a slogan |
| Specs-as-pitch | "MIT licensed. Production-grade." | Specs go in the README, not the founder's mouth on camera |
| "Just" as filler in a list | "Just one API call. Just any URL. Just structured JSON." | "Just" repeated reads as marketing emphasis, not natural speech |

**Allowed patterns** (use these instead):

| ✅ Pattern | Example |
|---|---|
| Personal-stake hook | "Honestly — every time I tried building X, same thing happened. ..." |
| "What if" framing | "So we built Y. The whole idea was: what if Z just worked?" |
| One concrete claim | "Last year we hit 24 thousand stars. People are plugging us in everywhere." |
| Casual aside on pain | "Hand it a URL. Get clean structured data. The layout changes? Doesn't matter." |
| Invitation closer | "If your agent needs to actually see the live web — come try us." |

**Structure** (4 acts, ~30-40 words per act = 120-160 words total, ~50-60s spoken):

- **Act 1: Personal stake / pain.** First person. Reference a specific frustration the founder lived through. Land on the problem named cleanly.
- **Act 2: The bet.** "So we built X. The idea was — what if [pain] just worked?" One sentence on what it actually does (URL → data, prompt →...

© Pika-Labs · Apache-2.0 · Pika-Labs/Pika-Plugins

Similar skills

All skills for AI and ML →

From the same set18

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor