skillZs
LIVE SKILL TAGS
>>> LIVE SKILLS INDEX <<<
* OPEN SOURCE *
NO LOGIN, NO TRACKING
REAL INSTALL DATA
← back to all skills
pika-labs/pika-plugins1.2k installs

app-sizzle

Generate cinematic 1080p iOS app teaser videos from real App Store screenshots, with a GPT-image-2 enhancement pass on each selected screen before generation. Output is a beat-driven cinematic teaser built from GPT-enhanced screenshots, ending with the brand logo/icon plus a deterministic `COMING SOON` overlay. Screens sourced from Pika MCP App Store fetch, a live website (auto-captured), user-supplied files, or URLs. Starts by sourcing real screens and brand assets before any generation. Triggers on: app sizzle, app teaser, app promo, iOS app promo video, app video, app product video, coming soon, seedance, motion graphics, make a promo for my app, make a video for [app], gpt enhance promo. NOT for: short-form consumer content like GRWM, vlogs, UGC, or non-app product ads (use content-video); app-sizzle is specifically for iOS app teaser videos sourced from App Store screens or real app UI.

How do I install this agent skill?

npx skills add https://github.com/pika-labs/pika-plugins --skill app-sizzle
view source ↗

Is this agent skill safe to install?

  • Gen Agent Trust Hubpass

    The skill is a well-structured tool for generating cinematic iOS app teaser videos. It follows security best practices by implementing cost transparency gates, user confirmation requirements, and quality verification steps. No malicious patterns, unauthorized data access, or obfuscation were detected.

  • Socketpass

    No alerts

  • Snykwarn

    Risk: MEDIUM · 1 issue

What does this agent skill do?

App Sizzle — GPT-Image-2 Enhanced iOS App Teaser

Generate a polished 15-second app teaser from real app screens. Each selected screen is passed through GPT-image-2 before Seedance so compressed captures become cleaner references without inventing UI.

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 3,000-4,000 credits (~$30-$40) for a typical run with screenshot enhancement plus Seedance video. 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.

Generation contract: use resolution="1080p", duration=15, and sound=True. Skip fast=true because it caps Seedance at 720p. The skill owns duration and sound so the user only has to supply app identity, screens, logo, and aspect ratio.

The visual aesthetic is derived from the app's personality — not defaulted to liquid glass. The agent reads the app's soul from its icon, screenshots, and category, then chooses a treatment. The user provides the app identity and assets; the agent decides everything else (mode, prompt, camera, style).


Pre-generation wall-clock guard

Start a timer at skill start once the required app identity and screen/logo source are available and the cost gate has passed. Time spent waiting for the user's proceed reply, or for non-interactive cost_ack=proceed, is not prep time and must not trigger this guard. If required inputs or real assets are missing, stop at Stage 0 or Stage 0.5 and ask for them; do not bypass the asset gate. For runs with required inputs in hand, the first paid generation call is the GPT-image-2 generate_image_edit enhancement pass, and it must be invoked within 5 minutes of skill start. If you have not invoked the first generate_image_edit enhancement 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 assets, selected screens, feature map, arc, enhancement-prompt status, Seedance prompt draft if any, and the exact blocker. Do not keep refining analysis, enhancement wording, prompt wording, or camera language.

Print a single-line progress checkpoint after each prep stage and right before the paid generation call:

  • Stage 1/3 done — assets sourced and screened, analyzing screenshots.
  • Stage 2/3 done — feature map and arc written, locking enhancement prompts.
  • Stage 3/3 done — enhancement prompts locked, calling GPT-image-2 now.

Feature-map and enhancement-prompt writing is maximum 2 passes before the first generate_image_edit call. After the max 2 passes, ship what you have to generate_image_edit; do not continue polishing enhancement wording, screen analysis, or arc language. Seedance prompt writing is maximum 2 passes after enhancements complete; then ship what you have to generate_reference_video.

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, overlay, 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.

Mode: Reference-to-Video

Primary: generate_reference_video(provider="seedance", resolution="1080p") with 3–5 screenshots + the app icon/logo as the final reference.

Fallback to provider="kling", quality_mode="pro" (= 1080p) when:

  • Seedance returns non-audio partner_validation_failed (celebrity faces, screen-recording UI)
  • Seedance returns insufficient_balance
  • Seedance stays queued/running until it returns a timeout such as seedance timed out after ...

Do not treat generated-audio moderation as an immediate Kling fallback. See the Seedance generated-audio moderation recovery runbook in Generate Video first.

Kling prompt uses <<<image_1>>><<<image_5>>> tokens instead of @Image1@Image5. Drop the resolution param (Kling uses quality_mode instead). See Gotchas.


Stage 0 — Asset Sourcing

If invoked with empty args and no relevant prior context, print this menu verbatim and stop. Do not call tools until the user supplies the app identity and screen source.

To make your app promo, I need:

1. App name + one-line description of what it does
   (e.g. "Nova — an AI journaling app for iOS")

2. Where should I pull the app screens from?
   — iOS App Store: give me the App Store URL or app name → I'll use
     `fetch_appstore_screens` to fetch screenshots, metadata, and icon
   — Web app / website: give me the URL → I'll capture it with Pika MCP
   — Local files / URLs: drop the paths and I'll upload them

3. Brand logo — path or URL (preferred) or skip to use the App Store icon
   The logo anchors the end card and prevents Seedance from hallucinating brand text.
   If you don't have a logo file, use the fetched App Store icon as the fallback.

4. Aspect ratio: 16:9 (landscape/YouTube) / 9:16 (Reels/TikTok) / 1:1. Optional: `variants=16:9,9:16,1:1` to export multiple deliverables from one render.

If the trigger message or prior context already supplies part of this, ask only for the missing required fields before touching any tool. These are the only questions the user needs to answer; the agent decides mode, prompt, camera, and style.

Once answered, the agent:

  1. Sources the screens (MCP App Store fetch / website capture / upload local files)
  2. Analyzes each screen (Stage 1) — reads every screenshot, maps UI → feature
  3. Designs the narrative arc (Stage 2) — builds a 15s story structure before touching the prompt
  4. Selects the 3–5 best screens for the promo (ordered by narrative role)
  5. Uploads logo + screens to get public URLs
  6. Writes the screen-specific prompt (Template A or B)
  7. Generates at 1080p

Stage 0.5 — Asset Gate

Before calling any generation tool, verify both assets are in hand:

AssetRequiredIf missing
Real app screenshots (≥1 actual sourced image)YesStop and ask for screenshots
Brand logo OR app iconYesUse the fetch_appstore_screens icon when App Store sourcing is used; otherwise stop and ask for a logo/icon

If either is missing, tell the user exactly what's needed and wait. Real assets are what keep the teaser grounded; text-to-video placeholders make Seedance invent UI.

Avoid:

  • Generate using text-to-video as a substitute when screens were expected
  • Describe imaginary UI in the prompt ("a dark dashboard with…") without a real reference image
  • Proceed with "I'll use a placeholder for now"
  • Make up what the app looks like from its name or description

The only acceptable path forward is real assets from the user. If MCP fetching or capturing failed (App Store returned nothing, website screenshot errored), report what happened and ask the user to provide the screens manually. Never invent them.

Avatar-type probe for human or character assets

App screenshots and app icons are the only default visual anchors. App-sizzle is not a founder/creator-face skill, so a missing screen or logo is never filled with a user avatar.

Before any paid generate_image_edit or generate_reference_video call, run this Avatar-type probe only when a user-supplied screen, logo, promo image, mascot, founder photo, or character asset includes a prominent person or character that would become an enhancement or video reference. For ordinary app screenshots with incidental faces, prefer a different screenshot or crop the face before upload.

Call analyze_media once on that asset:

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 only if this is a legitimate app screenshot or user-supplied promo asset; otherwise ask for app UI instead.
  • stylized / illustrated -> proceed with a visible warning that stylized characters may reduce Seedance reliability, but do not substitute them for missing screens.
  • trademarked / copyrighted -> STOP before generation. Surface this message: The supplied avatar appears to be a trademarked character ([X]). Most video providers will moderate this and refuse to generate. Pass --avatar <real-looking-photo-url> to override. For app-sizzle, ask for non-IP app screenshots/logo instead of using the avatar override as a screen substitute.

Screen Sourcing

iOS App Store

Use Pika MCP fetch_appstore_screens; do not use a local scraper. It accepts a full App Store URL, numeric app ID, or app-name search term:

fetch_appstore_screens(
  query: <app_store_url | numeric_app_id | search_term>,
  country: "us",
  max_screens: 10,
  include_icon: true
)

Expected result shape:

{
  "app_url": "https://apps.apple.com/...",
  "metadata": { "name": "...", "subtitle": "...", "description": "...", "category": "...", "icon_url": "https://..." },
  "icon": { "url": "https://cdn.pika.art/...", "source_url": "https://is...mzstatic.com/...", "filename": "appstore-icon.png", "mime_type": "image/png", "width": 1024, "height": 1024 },
  "screenshots": [
    { "url": "https://cdn.pika.art/...", "source_url": "https://is...mzstatic.com/.../1290x2796bb.png", "filename": "appstore-screen-01.png", "mime_type": "image/png", "width": 1290, "height": 2796 }
  ],
  "count": 1
}

If fetch_appstore_screens returns no screenshots, report the error and ask the user for 3-5 real screenshots plus a logo/icon. Do not fall back to Playwright/headless App Store capture and do not invent UI.

After App Store assets are fetched, pick the 3–5 screens that show the core UI. Skip:

  • Pure text/splash screens (no UI)
  • Blank or loading states
  • Screens with faces (may trigger content policy)

Screen selection principle — maximize visual contrast. Each selected screen should look as different as possible from the others: dark vs. light background, UI-dense vs. photo-heavy, micro close-up vs. wide grid, minimal vs. busy. If all your screens look similar, Seedance blends them into a visual mush. What made Dazz Cam work: 3D camera grid + Polaroid output + VHS panels + fisheye orb — four completely distinct visual worlds. What makes teasers fail: four screens of the same UI at slightly different scroll positions.

Web App / Website (auto-capture)

Use Pika MCP's capture tool:

capture_website(url="https://example.com", mode="screenshot")
# Returns image_url — use directly as a reference

Call once per distinct page/view you want to include.

Local Files

User provides paths → upload each via Pika MCP (see Asset Upload section below).


Stage 1 — App Analysis

After sourcing screens, read every screenshot using Claude's vision before writing a single word of prompt. This is the most important step — skip it and you get a generic glass blob with no story.

For each screenshot, record:

  • What UI is shown — e.g. "chat input with suggested prompts", "video timeline with AI edit chips", "agent result card showing a generated clip"
  • What feature it represents — e.g. "creation entry", "agent at work", "output/share"
  • Emotional register — is this the power moment, the ease moment, the aha moment?

Also pull the app metadata from the fetch_appstore_screens result, or from the user-provided description:

  • App name, subtitle, one-line value prop
  • Category and target user

Output of Stage 1: A numbered feature map:

Screen 1 — [filename]: Shows [X UI]. Represents [Y feature]. Moment: [hook/build/reveal].
Screen 2 — [filename]: ...
...

After the map, score each screen for visual uniqueness: does it look completely different from the others you've mapped? Prefer screens with distinct color palettes, distinct layout density, and distinct subject matter. A great set has maximum visual spread — the hook should feel nothing like the build, which should feel nothing like the reveal.

Do NOT proceed to Stage 2 until this map is written out.


Stage 2 — Narrative Architecture

Every 15s promo needs a spine. Design the story arc before touching the prompt template.

The 4-beat structure

BeatSecondsJobWhich screen(s)
Hook0–3sGrab attention — show the most dramatic UI moment or the problem being solvedThe most visually striking screen
Build3–10sFeature walkthrough in logical user-journey order2–3 screens in sequence
Reveal10–13sPull-back or product overview — the "so that's what it does" momentWide shot or most complete screen
Logo13–15sBrand lock — wordmark materializes, accent color pulseLogo (@Image6 or last ref). COMING SOON is added later as a post-generation text overlay.

Story arc types — pick one based on the app

ArcWhen to useStructure
Problem → SolutionProductivity/tool appsHook = pain point UI → Build = app solves it → Reveal = result
Feature ParadeFeature-rich appsHook = most impressive feature → Build = 2 more features → Reveal = overview
JourneyConsumer/lifestyle appsHook = entry point → Build = the experience → Reveal = outcome
TransformationBefore/after type appsHook = the "before" → Build = the process → Reveal = the "after"

Output of Stage 2

Write out the arc explicitly before generating:

Arc type: [Problem→Solution / Feature Parade / Journey / Transformation]
Hook (0-3s): Screen [N] — [what happens] — camera: [extreme close-up on X]
Build (3-10s): Screen [N] → [N] → [N] — [what each reveals] — camera: [whip pan / orbital / etc.]
Reveal (10-13s): Screen [N] — [what it shows] — camera: [pull-back to show full product]
Logo (13-15s): @Image[N] — wordmark materializes whole in a burst of [accent color] light and holds. Do not ask the video model to render the `COMING SOON` copy; it is added later as a post-generation text overlay.

Do NOT write the Seedance prompt until this arc is defined.


Stage 2.5 — GPT-Image-2 Enhancement

After the arc is defined and the 3–5 screens are selected, enhance each one with GPT-image-2 before uploading to Seedance. This lifts compressed website captures and App Store thumbnails to a cleaner, higher-fidelity reference.

For each selected screen (including the logo/end card reference):

result = generate_image_edit(
    provider="gpt-image-2",
    prompt="High quality version, preserve all content exactly",
    images=["<original_cdn_url>"],
    aspect_ratio="16:9",   # match the capture — use 9:16 for portrait screens
    quality="medium",
)
# use result.image_url (or result.url) as the Seedance reference

Rules:

  • Keep the prompt exactly as shown — short, non-descriptive. Describing the image content makes GPT-image-2 hallucinate new details.
  • Match aspect_ratio to the original capture (desktop = 16:9, mobile = 9:16).
  • Run all enhancements in parallel (one call per screen).
  • Use the enhanced URLs as the reference_images array in the Seedance call — not the originals.
  • Keep your Stage 1 feature map descriptions unchanged — they describe the original content, which the enhanced image preserves.

Stage 3 — Prompt Writing

With the feature map (Stage 1) and arc (Stage 2) in hand, write the Seedance prompt. Every @Image description must reference the real UI content from the feature map — never write generic descriptions like "a mobile interface with controls."

Choose the template by reading the app's screenshots — don't default to liquid glass. Read exactly one of these based on the app's personality; the other never loads:

  • Template A — Cinematic Narrative (default; productivity, AI, creative, social, food, games): read references/template-a-cinematic.md. The proven BEAT-structure template plus validated examples.
  • Template B — Liquid Glass (photography, camera, filter apps only, where a lens/filter metaphor is apt): read references/liquid-glass.md. Template B skeleton plus glass transformation vocabulary.

The accent color is always from the brand — read the icon and primary UI color, never invent one.

Rules for both templates

  • Every @Image description comes directly from the Stage 1 feature map
  • Camera directions come directly from the Stage 2 arc
  • Never write "the app interface" or "a mobile screen" — be specific
  • Keep under 200 words
  • Why specificity matters: Seedance uses @ImageN description as its primary brief — "a dark chat interface" vs "a VHS three-panel grid of city streets, a skate park, and a coastal sunset with retro timestamp overlays" produce completely different results. Copy the most visually specific details from your Stage 1 feature map verbatim.

Generate Video

Primary — Seedance:

generate_reference_video(
    provider="seedance",
    reference_images=["<url1>", "<url2>", "<url3>", "<url4>", "<url5>"],  # 3–5 screens + icon
    prompt="<prompt using @Image1 … @Image5 tokens>",
    resolution="1080p",   # always
    duration=15,          # always
    sound=True,           # always
    aspect_ratio="16:9",  # or 9:16 / 1:1 per user request
    seed=<int>,           # set one; reuse it for content-policy recovery
)

Seedance generated-audio moderation recovery

If Seedance finishes generation and then returns a 422 whose body includes type: "content_policy_violation", reason: "partner_validation_failed", loc: ["body", "generated_video"], and msg: "Output audio has sensitive content.", treat it as a recoverable generated-audio moderation false positive.

Retry budget: generated-audio recovery gets at most 3 recovery renders after the original failed Seedance call: one sound=False probe, one sound=True replay, and one Kling fallback. After that cap is exhausted, stop or route the successful silent URL exactly as documented; do not keep probing Seedance.

  1. Retry the exact same prompt and reference_images with sound=False and the same seed.
  2. If the silent probe succeeds, retry the exact same prompt/reference set with sound=True and the same seed.
  3. If the sound=True replay succeeds, route the recovered sound-on URL into Stage 4 as generated_teaser_url. Keep the silent probe URL only as debugging context.
  4. If the silent probe fails, treat the failure as video/reference moderation and use the Kling fallback.
  5. If the silent probe succeeds but the sound=True replay fails again, run the Kling fallback once. If Kling is unavailable, route the silent URL into Stage 4 as generated_teaser_url and explicitly note that generated-audio moderation remained flaky.

Do not change the prompt, references, aspect ratio, duration, or seed during this recovery path. Changing any of them turns the silent probe into a new generation instead of testing whether only generated audio triggered moderation.

Seedance timeout recovery

If Seedance returns a terminal timeout before the 15 min total polling ceiling, treat it as provider queue saturation, not a prompt/content failure. Do not wait for provider timeout strings such as seedance timed out after 900s or seedance timed out after 1200s.

When this happens, run the Kling fallback with the same selected references, same beat structure, duration=15, sound=True, and quality_mode="pro". Convert @ImageN prompt tokens to <<<image_N>>> before calling Kling.

At 15 min total, follow the polling contract above: cancel the non-terminal task and surface failure instead of starting a fallback while the original may still be active.

Do not keep retrying Seedance after a timeout unless the user explicitly asks to wait for Seedance. The timeout path has already spent the launch-demo wall-clock budget; switching provider is the documented recovery.

Fallback — Kling (non-audio partner_validation_failed or insufficient_balance):

generate_reference_video(
    provider="kling",
    reference_images=["<url1>", "<url2>", "<url3>", "<url4>", "<url5>"],
    prompt="<prompt using <<<image_1>>> … <<<image_5>>> tokens>",
    quality_mode="pro",   # = 1080p on Kling (NOT resolution=)
    duration=15,
    sound=True,
    aspect_ratio="16:9",
)

Seedance tokens: @Image1@Image5 | Kling tokens: <<<image_1>>><<<image_5>>>

Seedance constraints: skip fast=True because it caps at 720p; skip negative_prompt because Seedance rejects it; skip auto_duration because this path is fixed at 15s.

Kling constraint: use quality_mode="pro" for 1080p; Kling rejects resolution=.

Kling queued/handoff recovery

Kling fallback is async. If generate_reference_video(provider="kling") returns a task_id, follow the task until terminal using the long-running polling contract above.

If task_status returns status: queued with statusMessage containing Worker handoff: task was requeued for retry on another worker., treat it as a worker restart handoff, not a failed render. Keep polling task_status(task_id); the next worker should reclaim the same task.

If statusMessage starts with Kling is at capacity, treat it as provider capacity wait. Keep polling the same task while lastUpdatedAt continues moving and the task is still under the 15 min total ceiling.

Do not submit a duplicate Kling request while the original task is still queued or running. Duplicates can burn provider quota and make artifact provenance unclear.

If status stays queued for more than 10 minutes with no lastUpdatedAt movement, capture the task_id, status, statusMessage, and lastUpdatedAt, then continue the same task until the 15 min total ceiling. At 15 min total, cancel the stalled original with task_cancel({task_id}) and surface failure. Do not retry a new Kling request from this path; changing providers or resubmitting after a paid call risks duplicate spend and unclear artifact provenance.


Asset Upload (local files → public URL)

If the user provides local file paths, convert them to public URLs before calling generate:

  1. Read the file size and MIME type.
  2. Call upload_asset(filename, mime_type, size_bytes).
  3. Upload the bytes to the returned presigned_url using the host client's file-upload capability.
  4. Use the returned public_url as the reference URL in generation calls.

Supported mime types: image/png, image/jpeg, image/webp, video/mp4, audio/mpeg, audio/wav


Stage 4 — Deterministic COMING SOON Overlay

Do not ask Seedance or Kling to render COMING SOON. Video models garble new typography, especially all-caps CTA text, so the final two seconds use a deterministic COMING SOON overlay as a post-generation text overlay.

After Seedance or Kling returns the 15s teaser URL, call:

edit_text_overlay(
    video_url=<generated_teaser_url>,
    text="COMING SOON",
    position="bottom_center",
    font_size=56,
    font_color="white",
    start_s=13,
    end_s=15,
)

If edit_text_overlay returns { task_id }, poll task_status until it reaches completed, failed, or cancelled, then unwrap the returned URL. Save the returned URL as final_url. If the overlay call fails, surface that failure and the unoverlaid teaser URL as a diagnostic preview; do not deliver a teaser whose only COMING SOON text was generated by the video model.


Aspect-ratio variants

Use optional variants=16:9,9:16,1:1 when the user wants the same app teaser for YouTube, Reels/TikTok, and square feed without paying for separate generations. Keep legacy aspect= as the single-output shorthand; when variants is present, use native 16:9 as the source aspect unless the user explicitly asks for one variant only.

Call generate_reference_video once for the native 16:9 teaser, then run Stage 4 once to produce final_url. Do not re-run screenshot sourcing, GPT-image-2 enhancement, Seedance/Kling generation, or any other expensive provider call for extra variants.

After final_url exists, build a flat variant_urls object:

{
  "16:9": "<final_url>",
  "9:16": "<edit_reframe url>",
  "1:1": "<edit_reframe url>"
}
  • For 16:9, set variant_urls["16:9"] = final_url.
  • For 9:16 and 1:1, call edit_reframe(video_url=final_url, target_aspect="<aspect>", fill_mode="blur") so the full teaser remains visible over a blurred background instead of being center-cropped.
  • Treat edit_reframe as the cheap final composite / reframe stage. If a reframe fails, return the successful variant URLs plus the failed aspect and tool error; do not resubmit the expensive generation.

Heads up — variants use blur fill. 9:16 and 1:1 keep the full native 16:9 teaser visible over a blurred background. Keep key subjects (product, logo, headline) centered for readability, but do not describe these outputs as cropped variants.

Post-flight quality gate

Before declaring success, call analyze_media on final_url and ask for a structured verdict. If variants was requested, run the same gate on each variant_urls value and key any warning by aspect ratio.

Return JSON only: {
  "verdict": "clean" | "degraded" | "catastrophic",
  "observations": string[],
  "quality_warning": string | null,
  "re_roll_suggestion": string | null
}
Check that COMING SOON is visible and spelled correctly in the final overlay, the brand color is present, the app screen / product screen remains readable, and there are no black frames or wrong-product shots.
  • If verdict is clean, return the final URL normally.
  • If verdict is degraded, return the final URL plus the quality_warning so the user can review before publishing.
  • If verdict is catastrophic, do not call the run complete; surface the verdict and re_roll_suggestion instead of declaring success.

Result Delivery

Return the final Pika CDN URL as the primary deliverable. If variants was requested, return the flat variant_urls object in the same response. If the host client requires local media markers, create that local preview outside this skill flow after confirming the CDN URL is reachable.

If generation completes asynchronously: follow the MCP tool's returned status handle until the video reaches a terminal state, then deliver the final URL.


Prompting Guide

The prompt is the output of Stages 1 + 2, not a starting point. Never fill in the template from imagination — fill it from the feature map and arc you built. A prompt written without Stage 1 analysis will produce a generic glass blob.

Camera Vocabulary

Use specific camera language — Seedance responds to it:

TermEffect
extreme macro close-up on [specific element]Tight detail shot — glass edge, button, icon
crash zoom into [element]Fast push-in, creates energy
whip pan toHard lateral cut with motion blur
orbital sweep around360° arc around the floating panel
push-in driftSlow, cinematic dolly
pull-back to revealClassic product reveal — shows full form
hard cut to blackClean beat before logo

Alternate fast cuts with slower drifts — pure rapid cuts feel chaotic, pure slow drifts feel boring.

(Glass transformation vocabulary lives in references/liquid-glass.md — only relevant on the Template B path.)

Device Framing

For product shots, lock the device to a black void — never place in environments:

# Floating desktop screens (SaaS / desktop apps)
Show the desktop screens floating in 3D space on a pure black background, tilted at
slight angles like a MacBook product shot. The UI elements on screen become translucent
glass with reflections and refractions. No text, no logos, no words.

# iPad reveal
An iPad Pro floating in empty black space, tilted at a cinematic angle like an Apple
product shot. The iPad is a real solid device with visible bezels — only the screen
content has the glass effect. The device slowly rotates. No text, no logos.

# MacBook
A MacBook Pro floating in empty black space, open at a cinematic angle. The screen
displays [content]. Light catches the aluminium edges. No text, no logos.

Reference Count Guide

All runs are 15s, 1080p. Select 3–5 screens based on the narrative arc.

RefsUse case
3Standard — one screen per beat (hook / build / reveal) + icon as @Image4
4Two build beats + hook + icon
5Feature-rich — hook + 3 build beats + icon. Don't exceed 5.

The golden rule: 1 reference per ~3 seconds of video.


Load-bearing phrases

These phrases are empirical prompt/flow anchors. Keep them when simplifying the skill:

PhraseWhereWhy load-bearing
High quality version, preserve all content exactlyGPT-image-2 enhancement passKeeps the enhancement pass from inventing UI while cleaning compression artifacts.
Do NOT write the Seedance prompt until this arc is definedStage 2.5 gatePrevents generic motion prompts that are not grounded in the selected screens.
The prompt is the output of Stages 1 + 2, not a starting pointPrompting guideForces the agent to use the screen feature map and story arc instead of template-filling from imagination.
pure black background / floating in empty black spaceDevice framing promptsKeeps product shots focused on the app UI rather than hallucinated environments.
materializes whole / crystallizes as a single form / fades in as a complete elementLogo reveal wordingAvoids per-letter logo construction, which causes garbled brand text.

Runtime Expectations

Typical run time is 4-8 minutes. All pre-generation stages before the first paid generate_image_edit enhancement call must fit inside the 5-minute guard above. If they do not, stop and report partial prep instead of continuing.

StepWall clockNotes
Asset sourcing10-60sApp Store via fetch_appstore_screens; website capture depends on page load
Screen analysis + arc<=2 minKeep this bounded by the max 2 prompt/analysis passes
GPT-image-2 enhancement30-90sRun selected screens in parallel only while still inside the 5-minute pre-generation guard
Seedance generation3-5 minGenerated-audio moderation recovery adds one silent probe plus one same-seed sound replay
Kling fallback5-15 minCapacity wait or worker handoff may temporarily show queued; follow the Kling queued/handoff recovery runbook
Download verification<30sLocal sanity check before delivery

Engine Choice: Seedance Primary, Kling Fallback

Seedance is the default because it handles polished motion-graphics references and 1080p app teasers well. Kling is the fallback for moderation, balance, or Seedance timeout failures because it is more permissive on some screen content and uses quality_mode="pro" for 1080p.

Failure Modes

Recovering from upstream 5xx on generate_image_edit / generate_reference_video / upload_asset

If any paid generation or asset MCP call returns:

  • code: "provider_5xx" AND retry_class: "retry_after_backoff"
  • Or HTTP 502 / 503 / 504 from any upstream provider (OpenAI, Seedance, Kling, storage)

Do this:

  1. Wait 5 seconds.
  2. Re-call the exact same MCP tool with the exact same arguments. Do not change selected screens, prompt text, seed, sound, provider, image order, or upload payload.
  3. If the retry also fails with 5xx, abort and surface to the user: "Provider returned a transient upstream error twice. Try again in 1-2 minutes; this usually clears on its own."

Do not retry more than once. Do not treat a 5xx as a content or moderation issue; rewriting the app arc can spend credits without addressing the outage.

Recovering from upstream 4xx / moderation_blocked

If generate_image_edit with provider="gpt-image-2" returns an upstream 4xx or moderation_blocked while enhancing screenshots:

  1. Do NOT retry the same prompt; moderation and most 4xx validation failures are deterministic.
  2. If the reference still works without enhancement, skip the enhancement and use the original screen. If quality is too low, try a fallback provider once for enhancement only; do not alter the selected app screens or Seedance prompt.
  3. If the fallback provider also fails, surface to the user: "Image provider declined this screenshot-enhancement prompt. Provide cleaner screenshots, crop faces/recording UI, or continue with the original screens."

For Seedance non-audio content-policy failures, use the documented Kling fallback below; that is the video fallback provider path for this skill.

Recovering from upstream 429 (rate limit)

If any upstream returns HTTP 429 with a backoff hint:

  1. Wait the hinted backoff, or 30 seconds if no hint is provided.
  2. Re-call the exact same MCP tool with the exact same arguments.
  3. Do not retry more than once. If it still returns 429, abort and surface the rate-limit message instead of submitting duplicate paid renders.

capture_website returning empty / page-not-loaded

If website mode calls capture_website and it returns 200 but action_bboxes is empty or recording_viewport is 0x0:

  1. Do NOT retry; the site failed to render in the capture environment.
  2. Surface: "Could not capture <url>. The page may be blocked / paywalled / require auth. Please provide 3-5 screenshots and a logo/icon instead."

upload_asset network / auth failure

If upload_asset fails while converting local screens, logos, or overlays to hosted URLs, do not continue with local paths in reference_images or HTML. Retry once only for the 5xx or 429 classes above. For auth_error, unsupported MIME, network failure, or repeated upload failure, stop and ask for hosted PNG/JPEG/WebP assets.

Long-running task_status exceeding ceiling

Each async MCP call returns either an inline result or {task_id, status} for polling. Use these ceilings before deciding a task is stuck:

  • Seedance i2v: 10 min per call
  • Kling fallback: 15 min per call
  • gpt-image-2 high quality: 3 min per call
  • Upload/edit/render helpers: 5 min per call

Use whichever is earlier: the provider's ceiling x 1.5 or any skill-specific hard polling cap, including the 15 min total cap in the Long-running task_status polling contract above. If task_status returns status: "processing" or status: "queued" past that earlier limit, call task_cancel({task_id}) and surface: "Provider taking unusually long; aborting. Try again."

SymptomCauseFix
fast=True with resolution="1080p"Seedance caps fast mode at 720pRemove fast; keep resolution="1080p"
negative_prompt rejectedSeedance does not accept this fieldUse positive framing such as "smooth motion, stable camera"
Seedance generated-audio moderation: content_policy_violation / partner_validation_failed, generated_video, "Output audio has sensitive content."Often a false positive on non-sensitive app-sizzle referencesFollow the capped generated-audio recovery runbook: same-seed sound=False probe, same-seed sound=True replay, then at most one Kling fallback
Seedance timeout such as seedance timed out after ...Provider queue saturation or tail latency exceeded the tool budgetRun the Kling fallback; do not keep retrying Seedance unless the user explicitly asks to wait
Seedance partner_validation_failed on videoScreen content includes recording UI, celebrity faces, or similar moderation triggersSwitch to provider="kling" and convert tokens to <<<image_N>>>
Faces in screenshots trigger content policyScreenshot includes real peopleCrop faces out before upload, or use Kling
6+ reference images reduce qualityThe model blends too many refsKeep to 3-5 references, roughly one per 3 seconds
Prompt tail ignoredPrompt exceeds about 200 wordsTrim to the beat structure and the concrete UI details
Text in output is garbledVideo model is asked to render new textKeep text as existing reference-image content; overlay any new branding in post
Logo reveal hallucinates letterforms"assemble/build/construct" language triggers per-glyph renderingUse "materializes whole", "crystallizes as a single form", or "fades in as a complete element"
Task returns { task_id } instead of inlineLong-running generation exceeded inline budgetFollow the long-running polling contract: poll task_status({task_id}), emit 60s progress lines, cancel/surface at 15 min total, and unwrap result.structuredContent on completion
Kling task returns status: queued after previously runningWorker handoff or provider capacity waitFollow the Kling queued/handoff recovery runbook and the long-running polling contract. Do not submit a duplicate; keep polling until terminal or cancel/surface at 15 min total
Kling rejects resolution=Kling uses a different quality knobUse quality_mode="pro"
App Store icon URL points to promo artApp Store metadata fallback found feature artworkPrefer the icon.url returned by fetch_appstore_screens; if missing, ask for a logo/icon file

Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.

<a href="https://skillzs.dev/skills/pika-labs/pika-plugins/app-sizzle">View app-sizzle on skillZs</a>