--- id: Pika-Labs/Pika-Plugins/ugc-ads version: "1dbd488c" license: Apache-2.0 install: manual updated: 2026-07-20 --- # ugc-ads — ugc-ads builds short-form product videos optimized for social platforms, combining jump-cut pacing with native lip-synced dialogue delivered as a first-person talking head. The skill auto-detects product category from your URL and structures the narrative across five beats—setup, name reveal, product reveal, twist, and punchline—then renders in your choice of vertical formats. Publisher: Pika-Labs · Stars: 37 · Updated: 2026-07-20 Install (manual): `git clone https://github.com/Pika-Labs/Pika-Plugins` ## SKILL.md # /pika:ugc-ads ## Parameters | Param | Default | Notes | |---|---|---| | `url` | required | product URL — drives category detection and beat substitution | | `avatar_url` | built-in fallback | persona portrait URL; fed as `@Image1` reference. When omitted, the skill uses a pre-generated Pixar-style female creator portrait | | `provider` | `seedance` | seedance: strong at UGC selfie / talking-head POV with native lip-sync, multi-segment in single prompt, supports 3:4. kling: explicit `shots[]`, 9:16/16:9 only | | `aspect_ratio` | `9:16` | `3:4` is seedance-only (kling rejects 3:4) | | `variants` | unset | Optional comma list for shared-generation exports. Supported: `9:16`, `16:9`, `1:1`. Keeps the expensive UGC render shared, then reframes the final stage. | | `category` | auto | `HAUL` / `APP` / `FOOD` / `BEAUTY` / `FITNESS` / `TECH`; auto-picked from URL | | `captions` | `true` | TikTok-style word-chunked captions burned on top of the final video | ## 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 Seedance UGC ad with fallback/retry budget. 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. The gate runs after the product URL is known and before avatar analysis, screenshot capture, video generation, captions, or paid retries. ## Runtime expectations Typical end-to-end run: **6–12 minutes**. Breakdown: - Step 1 (WebFetch) + Step 3 (capture_website screenshot): ~10–30s - Step 7 (`generate_reference_video`): ~3–5 min for seedance, ~5–7 min for kling - Step 7b/c (cartoonize + retry): adds ~1–2 min if seedance moderation rejects the avatar - Step 8 (deterministic brand/spec overlays): 1-2 `edit_text_overlay` calls, ~30s–5 min total - Step 9 (captions): single `add_captions` call, ~30s–5 min (transcribe + burn in one shot) If the run exceeds 15 min without progress, something is wrong — inspect the tool-reported generation status and error message. ## Pre-generation wall-clock guard Start a timer at skill start once the product URL is available and the cost gate has passed. Time spent waiting for the user's `proceed` reply is not prep time and must not trigger this guard. The first paid generation call is `generate_reference_video`, the long-pole paid stage, and it must be invoked within 5 minutes of skill start. If you have not invoked `generate_reference_video` within 5 minutes of skill start, stop before any paid generation call and report `failed_pre_generation_timeout` with what you have so far: fetched product facts, chosen category, avatar source, screenshot status, draft dialogue, and the exact blocker. Do not keep refining script wording, prompt grounding, or shot order. Print a single-line progress checkpoint after each prep stage and right before the paid generation call: - `Stage 1/3 done — product fetched and categorized.` - `Stage 2/3 done — avatar and screenshot ready, composing dialogue.` - `Stage 3/3 done — prompt locked, calling Seedance now.` Script and prompt iteration is maximum 2 passes. After the max 2 passes, ship what you have to `generate_reference_video`; do not continue polishing the hook, punchline, or screen-close-up wording. ## 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. - 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 Kling, GPT-image-2, caption, or edit tasks. - On `completed`, unwrap the returned result URL and continue. - 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`. - Async polling budget: one active task with one 15 min polling window. After the polling cap is exhausted, cancel the task and surface failure instead of submitting another paid render unless a later step explicitly allows a separate capped retry after the original task is terminal. ## Engine choice: Seedance default, Kling fallback Default to Seedance for UGC selfie/talking-head ads because it handles native lip-sync, single-prompt multi-beat pacing, and optional 3:4 output well. Use Kling when the caller explicitly passes `provider=kling`, or after Seedance exhausts the capped cartoonized retry only if the user chooses Kling from the stop message. Kling's tradeoff is stricter aspect-ratio support but a separate moderation path and explicit shot segmentation. ## Steps ### 0. Resolve input (empty-args menu) Strip flags and `key=value` parameters from `$ARGUMENTS`. If no product URL remains and there is no usable product URL in prior context, print this menu and stop: > **Which product should the UGC ad promote?** Required: > > - **Product URL** — page to fetch for product name, category, visual references, and language > > Optional: `avatar_url=`, `provider=seedance|kling`, `aspect_ratio=9:16|3:4`, `variants=9:16,16:9,1:1`, `category=auto|HAUL|APP|FOOD|BEAUTY|FITNESS|TECH`, `captions=true|false`. If the product URL is present, skip this step silently. ### 1. Fetch + categorize `WebFetch` the URL: pull `product_name`, `brand_name`, value prop, brand color, product form, packaging, hero copy, target user, category, **and the primary language of the page**. Use `category=` if passed; else trust the WebFetch signal; fall back to HAUL for physical, APP for digital. Build two grounded fact lists from the fetched page: ```json { "grounded_specs": [ { "claim_text": "250W total output", "value": "250", "unit": "W", "source_quote": "visible source-page text containing the exact value", "source_url": "" } ], "claims_allowlist": ["250W total output"] } ``` Every numeric spec claim (`W`, `mAh`, `%`, minutes, ports, price, dimensions, counts, charging speeds, battery size, rankings) must come from visible source-page text and include a `source_quote`. If the source page does not visibly support a number, leave it out of `grounded_specs` and `claims_allowlist`. Do not infer specs from product category, model name, common knowledge, or competitor pages. ### 2. Resolve the avatar (fallback to built-in if missing) - If `avatar_url` was passed → use it as-is. - If NOT passed → use this built-in fallback: ``` https://cdn.pika.art/v2/files/agent/17d62bf9-0edb-49e4-9ba9-2c5419fa518f/seedream-1777624057811.jpeg ``` Pre-generated 3D animated Pixar-style portrait of a young female creator — pre-cartoonized so seedance moderation accepts it directly, neutral enough to fit any category. Note in the final summary that the fallback was used so the caller knows to supply their own portrait for persona consistency next time. ### 2.5 Avatar-type probe for creator portraits Run this probe before Step 7 and before any paid `generate_reference_video` call. It applies to caller-supplied `avatar_url`, the built-in fallback, or any creator portrait chosen as `@Image1`. The built-in fallback is already a non-IP stylized creator, but still document its source in the final summary. 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 accepted by Kling but can be inconsistent under Seedance moderation; continue only if the user supplied or accepted that avatar. - **trademarked / copyrighted** -> **STOP** before generation. Surface this message: `The avatar appears to be a trademarked character ([X]). Most video providers will moderate this and refuse to generate. Pass avatar_url= to override.` ### 3. Capture the product screenshot (best-effort) Call `capture_website` with `mode: "screenshot"`. Use `mobile=true` for handheld-product categories (APP / FITNESS / BEAUTY) so the captured page renders as a portrait phone screen; `mobile=false` for desktop-context categories (HAUL / TECH / FOOD). If the call fails (timeout, browser pool down), retry **once**. If still failing, proceed without the screenshot — the skill is degraded but functional. The close-up beat then describes the page from prose only and Beat 2's `reference_images` is just `[avatar_url]`. Capture URL → `screenshot_url` (or null). ### 4. Compose the prompt The full prompt is a single multi-beat string passed to **one** `generate_reference_video` call. Structural prose (not markdown bullets). Every beat has a `Says: "..."` line for lip-sync. Pacing target ~5.5–6 words per second across the whole 15-second ad (≈85–90 words total). `@Image1` is the avatar, `@Image2` is the screenshot when available. **Write all `Says: "..."` lines in the language detected from step 1's WebFetch.** Both seedance and kling lip-sync handle multilingual; if the product page is Chinese / Japanese / Spanish / etc., the dialogue should be in that language. Hook archetypes from step 5 are language-agnostic — adapt the rhetorical move to the language's natural register. **Spec-grounding rule:** forbid inventing numbers. Any spoken or visual number/unit claim must appear verbatim in `claims_allowlist`. If a number is not in `claims_allowlist`, rewrite the line qualitatively ("charges fast", "multiple ports", "big battery") or omit the claim. Do not say "50% in 28 minutes", "3 ports", "140W", prices, counts, or time windows unless that exact claim is source-backed. **Brand/spec text rendering rule:** Do not ask Seedance or the video model to render the brand wordmark, product wordmark, packaging label, or spec text from prose. Video-model text comes out garbled. The prompt may show `@Image2` as a reference, but any new brand name or spec copy that must be readable is added later by the deterministic Step 8 overlay. ``` HOOK (0–3 sec) . Says to camera, fast and energetic: "".