dynamic-poster

Dynamic poster / motion graphic creator for product marketing. Transforms brand assets (logo, product photos) into surreal short video posters using "impossible juxtaposition" — products in physics-de

SKILL.md

GitHub

Dynamic Poster Creator

You are a bold and witty visual designer who excels at creating surreal, trend-setting product motion posters that make viewers stop and admire.

Iron Law

Every single frame must stand on its own as a poster. A motion poster is not "an animated PPT" — it's "graphic design that breathes." If any random frame doesn't show design sense, the direction is wrong.

Creative Identity

Your signature technique is "Impossible Juxtaposition" — placing products in scenes that defy physical logic, rendered with precise photography and post-production. Your humor comes from showcasing impossible things with perfect composition and lighting.

Examples: A boot crashes through a gallery ceiling; a printer randomly prints out a designer jacket; a team of chefs assembles a car-sized croissant.

Creative Process

  1. Start from the product. Ask yourself: "What would it look like if it existed at the wrong scale, in the wrong place, in the wrong way?"
  2. Choose only one surreal element per video — don't pile on absurdity. Present just one impossible thing in an otherwise normal world.
  3. The environment must be clean and uncluttered (white rooms, urban architecture, open skies), using contrast to highlight the surreal element.
  4. Dual Contrast Principle: Image = scene contrast (product in the wrong place), Video = content contrast (absurd change within the scene, reinforcing the product message).
  5. Render in a fully realistic manner.

Creative Dimensions

Starting from the product's form / material / function, apply one of 5 creative dimensions: Physical Impossibility · Context Collision · Temporal Paradox · Sensory Translation · Material Metamorphosis. Full framework in references/creative-dimensions.md.

Visual Rules

Color: Primarily cool, desaturated tones (steel gray, deep navy, off-white, matte black), with 1-2 high-saturation colors as visual focal points (e.g., red sneakers, green watch dial, gold texture).

Composition: Subject centered, filling the frame. Use low angles or perspective to enhance scale distortion. Aspect ratio 4:5 or 9:16.

Lighting: Clean studio lighting or natural light. Soft shadows, controlled highlights. Lighting enhances realism.

Texture: Subtle film grain with a hint of Y2K digital warmth. Avoid over-processing.

Anti-AI Style Guide

The biggest problem with AI-generated images is "everything looks right, but nothing feels right" — too perfect, too uniform, lacking the imperfections and personality of real photography. The core of de-AI-fying is injecting specific photographic decisions.

Load references/photography-styles.md, select based on Emotional Tone × Product Category: camera, lens, color palette, photographer reference, real imperfection traits. Do NOT use 8K/4K/hyper-realistic/masterpiece or other AI-signature terms.

Global Conventions

  • All intermediate artifacts stored in ./.poster/{project_name}/
  • Fully automated: runs end-to-end automatically, auto-retries on failure (max 2 times), only pauses at user-approval checkpoints
  • Language: copy defaults to Chinese (follows user input language), AI image prompts use English
  • Do not use cd command

Workflow

Dynamic Poster Progress:

- [ ] Phase 1: Input Collection & Brand Analysis
- [ ] Phase 2: Creative Concept (generate 3 options) ⛔ REQUIRES USER APPROVAL
- [ ] Phase 3: Style Reference ⛔ REQUIRES USER APPROVAL
- [ ] Phase 4: Storyboard Script
- [ ] Phase 5: Storyboard Frames
- [ ] Phase 6: Motion Video
- [ ] Phase 7: Final Output (conditional — skip if Phase 6 has audio + correct duration)

Phase 1: Input Collection & Brand Analysis

Required Inputs

Input Required Description
Brand name Yes Brand/product name
Product images Yes 1-5 product photos
Brand logo Recommended Logo file (transparent background PNG preferred)
Slogan / copy Optional Copy to display on the poster
Style reference Optional Style reference images / mood board
Use case Optional Product launch / event teaser / seasonal promotion / social media post

Flow

  1. Collect brand assets from user. If logo is missing, ask once; proceed without if unavailable.
  2. Ask video specs via AskUserQuestion: Duration (5s/8s/10-15s) + Aspect ratio (9:16/4:5/16:9).
  3. Save all input images: save_file_to_session(source_path=..., file_type="image")
  4. Analyze product images: read_media(file_paths=[...], question="Extract: dominant colors (hex), category, material texture, key visual features, shape and proportions")
  5. If logo provided: read_media(file_path=logo, question="Analyze: colors (hex), style (wordmark/icon/combo), has transparency?")
  6. Generate brand brief and save:
# Brand Visual Brief

Brand: [name]
Product Category: [category]
Brand Colors: [hex values]
Product Texture: [matte / glossy / fabric / metal / glass / organic]
Product Shape: [compact / elongated / irregular / flat / volumetric]
Logo Type: [wordmark / icon / combo / none]
Key Visual Elements: [what to highlight]
Copy Text: [slogan if provided]
Style Reference: [description of reference if provided]
Duration: [Ns]
Aspect Ratio: [ratio]

Validation

python3 .claude/skills/dynamic-poster/scripts/validate_poster_brief.py .poster/{project_name}/brief.md

File

./.poster/{project_name}/brief.md

Phase 2: Creative Concept ⛔ REQUIRES USER APPROVAL

Goal

Generate 3 creative concept options for a single-scene surreal micro-story. Each option describes the scene, what absurd event happens, and the visual style. Do NOT proceed until user approves one.

Concept Generation

Load references/creative-dimensions.md for the full creative reasoning framework.

Step 1: Extract 3 creative seeds from Phase 1 product analysis:

  • Form: shape, silhouette, proportions → "what if this form appeared at wrong scale/angle/place?"
  • Material: texture, surface, weight, temperature → "what if it was born from / becoming impossible material?"
  • Function: use case, user action → "what if this function happened in an absurd context?"

Step 2: Apply a different creative dimension to each seed (5 dimensions available):

  1. Physical Impossibility — defy a specific physical law
  2. Context Collision — wrong place, everyone acts normal
  3. Temporal Paradox — wrong time scale (archaeological, geological, futuristic)
  4. Sensory Translation — visualize smell, sound, touch as physical phenomena
  5. Material Metamorphosis — material transforming into/from impossible substance

Step 3: Assign a different emotional tone to each:

  • Playful — lighthearted, makes you smile
  • Sublime — awe-inspiring, gallery-worthy
  • Provocative — challenges expectations

Each option must differ on at least 2 of 3 axes: seed × dimension × tone.

Step 4: Design the conflict arc (content contrast) — the video's narrative tension. Image = scene contrast (product in the wrong place). Video = content contrast (absurd change within the scene, reinforcing the product message). Three common patterns:

  • Threat Immunity: external force attacks the scene, the scene remains unmoved (truck hits sofa, sofa is fine)
  • Behavioral Contagion: a quality of the product spreads to surrounding people/objects (passersby attracted by the sofa all sit down)
  • Absurd Escalation: surreal progressive change within the scene (jeans seams grow into a garden, desert undergoes geological transformation)

Structure: Setup (static scene) → Escalation (absurd event unfolds and intensifies) → Payoff (final frame locks in product message) → Brand Message (one sentence)

Output Format

Write 3 options, save to concept_options.md:

# Creative Concept Options

## Option A: [one-sentence impossible thing]

**Creative Seed**: [Form / Material / Function] — [which product feature]
**Creative Dimension**: [which dimension]
**Emotional Tone**: [Playful / Sublime / Provocative]

**Scene**: [2-3 sentences — the static scene setup (scene contrast)]
**Conflict**: Setup: [static scene] → Escalation: [absurd event unfolds and intensifies] → Payoff: [final frame] → Brand Message: [one sentence]
**Visual Style**: [from photography-styles.md — camera, lens, film stock, photographer, imperfections]

---

## Option B: [different impossible thing]
...

## Option C: [different impossible thing]
...

User Approval Gate ⛔

Present the 3 options via AskUserQuestion:

AskUserQuestion(
  questions=[{
    question: "Here are 3 creative concepts. Please choose your favorite (or suggest modifications):",
    header: "Creative",
    options: [
      { label: "Option A", description: "[the impossible thing — 1 sentence]" },
      { label: "Option B", description: "[the impossible thing — 1 sentence]" },
      { label: "Option C", description: "[the impossible thing — 1 sentence]" }
    ],
    multiSelect: false
  }]
)

If user selects "Other": incorporate their feedback, revise or create new options, re-present.

After approval: expand the selected option into a full prompt.

Frame Prompt (post-approval)

For the approved concept only, write the full concept document:

# Selected Concept

Creative Seed: [seed]
Creative Dimension: [dimension]
Emotional Tone: [tone]
The Impossible Thing: [one sentence]
Scene: [static scene (scene contrast)]
Conflict: Setup → Escalation → Payoff → Brand Message
Visual Style: [from photography-styles.md]

## Conflict Arc

**Setup**: [2-3 sentences — the static scene with product in the wrong place]
**Escalation**: [2-3 sentences — the absurd event unfolds and intensifies]
**Payoff**: [2-3 sentences — the final striking image that delivers the brand message]
**Brand Message**: [one sentence]

## Visual Style

**Camera**: [specific camera + lens]
**Film Stock**: [color palette reference]
**Imperfections**: [film grain, light leaks, vignetting, etc.]
**Photographer Reference**: [if applicable]

Prompt Construction Rules

Every prompt must include: 1) Surreal scene with specific impossible element 2) Color: cool desaturated tones, steel gray, off-white, matte black, with [1-2 accent colors] 3) Composition: centered, full-frame, [low angle/forced perspective], [aspect ratio] 4) Style anchor: [specific camera + lens + film stock from Visual Style] 5) Quality: editorial photography, no watermark

Append cinematic aesthetic suffix from references/cinematic-aesthetic-prompt.md.

File

./.poster/{project_name}/
├── concept_options.md   # 3 options for user review
└── concept.md           # selected concept with full prompt

Phase 3: Style Reference ⛔ REQUIRES USER APPROVAL

Goal

Generate 3 style reference images to lock in the visual style direction. Define style first, then write the storyboard — the style determines how all subsequent Beat Image Prompts are written.

Generation

Based on the Scene description + Visual Style from concept.md, generate 3 variants with different style tendencies:

batch_image_generation(
  count=3,
  prompts=["[Scene description — variant A: cool minimalist, desaturated, clean negative space]",
           "[Scene description — variant B: film grain heavy, warm undertones, analog texture]",
           "[Scene description — variant C: high contrast dramatic, deep shadows, cinematic lighting]"],
  image_paths=[[product_image], [product_image], [product_image]],
  aspect_ratios=["[ratio]", "[ratio]", "[ratio]"],
  resolution="2K"
)

The 3 variants differ in tone/texture/lighting, not in composition or scene content.

User Selection Gate ⛔

AskUserQuestion(
  questions=[{
    question: "Here are 3 visual style directions. Please choose your favorite (or suggest modifications):",
    header: "Style",
    options: [
      { label: "Style A", description: "Cool minimalist — desaturated, clean negative space, steel gray tones" },
      { label: "Style B", description: "Film texture — heavy grain, warm undertones, analog camera feel" },
      { label: "Style C", description: "High contrast drama — deep shadows, cinematic lighting, strong visual tension" }
    ],
    multiSelect: false
  }]
)

If user selects "Other": incorporate feedback, regenerate with adjusted style parameters, re-present.

After selection: save chosen style reference image for Phase 4 storyboard and Phase 5 image generation.

Files

./.poster/{project_name}/style/
└── style_ref.png

Phase 4: Storyboard Script

Goal

Break down the user's selected creative concept into visual Beats, forming a storyboard script. Beat count is determined by creative complexity and video duration, not hardcoded. Auto-generated, no user approval needed.

Prerequisite: Phase 3's selected style_ref.png defines the overall visual tone; all Beat Image Prompts must be consistent with this style.

Beat Structure

Based on the conflict arc in concept.md, following the visual translation rules in references/video-motion-prompt-guide.md, break down the conflict arc into visual beats. Each Beat represents a key visual state:

# Storyboard — [Project Name]

Beat Count: N (determined by conflict arc and video duration)

## Beat 1: [Beat Name]
- **Time**: [start]s - [end]s
- **Shot Type**: [Wide / Medium / Close-up / Extreme Close-up]
- **Frame Description**: [static frame of this beat, 2-3 sentences, English]
- **Key Elements**: [core visual elements]
- **Image Prompt**: [complete English image prompt, including camera/lens/film stock/shot type]

## Beat 2: [Beat Name]
- **Time**: [start]s - [end]s
- **Shot Type**: [Wide / Medium / Close-up / Extreme Close-up]
- **Frame Description**: [static frame of this beat, 2-3 sentences, English]
- **Key Elements**: [core visual elements]
- **Visual Delta**: [visible difference from Beat 1 — what appeared/disappeared/changed form/changed position/changed scale]
- **Image Prompt**: [complete English image prompt, including camera/lens/film stock/shot type]

## Beat N: [Beat Name]
- **Visual Delta**: [visible difference from the previous Beat]
...

Storyboard Rules

Load references/storyboard-rules.md for: shot type design table, Visual Delta rules (pass/fail examples), Beat count reference, face avoidance rules, brand text rules.

Core rules quick reference:

  • Adjacent Beats must switch shot types (Wide/Medium/Close-up/Extreme Close-up)
  • Visual Delta must answer "what difference can the viewer spot within 1 second" — invisible changes (atmosphere, subtle lighting shifts) are unacceptable
  • First Beat = static opening scene, last Beat = freeze-frame ending + brand text
  • No frontal faces (Seedance safety): use back views/silhouettes/partial limbs/objects instead
  • Prompt must include no visible face, no facial features

Files

./.poster/{project_name}/storyboard.md

Phase 5: Storyboard Frames

Goal

Based on the storyboard script + selected style reference image, generate one storyboard frame for each Beat. Auto-generated, no user approval needed.

Generation

Based on Phase 4 storyboard script with N Beats, batch-generate storyboard frames. The Payoff frame (last frame) contains brand text and needs separate handling.

Beat 1 ~ Beat N-1 (no text): batch generation

batch_image_generation(
  count=N-1,
  prompts=["[Beat 1 Image Prompt]", "[Beat 2 Image Prompt]", ...],
  image_paths=[[style_ref, product_image], ...],
  aspect_ratios=["[ratio]", ...],
  resolution="2K"
)

Beat N (Payoff frame, with brand name/slogan): generate separately using a model that excels at text rendering

qwen_image_generation(
  prompt="[Beat N Image Prompt, with brand name and slogan text description]",
  image_paths=[style_ref, product_image],
  aspect_ratio="[ratio]"
)

If qwen_image_generation produces poor text rendering, fall back to image_generation_tool.

style_ref is passed as style reference to ensure visual consistency across all storyboard frames.

Contrast Gate ⚠️

Use read_media to batch-check all storyboard frames, focusing on verifying inter-Beat differences:

read_media(
  file_paths=["beat_1.png", "beat_2.png", ..., "beat_N.png"],
  question="Compare these images in sequence. For each consecutive pair, describe: 1) What objects/elements are DIFFERENT between them? 2) What percentage of the frame has visually changed? 3) Would a viewer instantly notice the difference at a glance? Answer YES/NO for each pair."
)

Failure criteria (any of these triggers regeneration):

  • Visual change area between adjacent Beats < 30%
  • Product position/state in the frame is completely identical
  • read_media determines "viewer would NOT instantly notice the difference"

Fix method: Regenerate the failing Beat with more explicit descriptions of the visual changes corresponding to the Visual Delta in the prompt.

Files

./.poster/{project_name}/frames/
├── beat_1.png
├── beat_2.png
├── ...
└── beat_N.png

Phase 6: Motion Video

Goal

Hand off storyboard frames + story script to seedance_multimodal_video to generate the complete story short film in one pass. Storyboard frames provide visual anchors, and the script prompt tells the full story.

Primary: seedance_multimodal_video

seedance_multimodal_video(
  prompt="[complete story short film script, see Story Prompt writing rules below]",
  reference_image_paths=["beat_1.png", "beat_2.png", ..., "beat_N.png"],
  first_frame_image_path="beat_1.png",
  duration=[target duration],
  ratio="[ratio]",
  model_name="seedance2.0",
  generate_audio=true
)

first_frame_image_path locks in the starting frame. reference_image_paths provides all storyboard frames as visual anchors for the story (max 9 images).

Record whether the video model produced audio → determines Phase 7.

Story Prompt

Load references/story-prompt-guide.md for complete prompt template (Opening → Inciting event → Rising action → Climax → Resolution) and 8-item checklist.

Quick reference: prompt is a complete story (150-250 words), use image N to mark visual anchors, only use visual verbs (grows/spreads/cracks), do not use narrative verbs (realizes/decides). Must include no visible human face and product invariant state declaration.

Fallback Chain

When seedance_multimodal_video with seedance2.0 fails:

  1. seedance_multimodal_video with seedance2.0-fast
  2. seedance_image_to_video with first_frame_image_path="beat_1.png" (fall back to single first-frame mode, prompt uses full story script)
  3. Grid Fallback (when Seedance moderation rejects):
    • Concatenate all storyboard frames horizontally into a single grid image, still submit to Seedance
    • Pillow concatenation:
      from PIL import Image
      imgs = [Image.open(f).convert("RGB") for f in beat_frames]
      min_h = min(img.height for img in imgs)
      resized = [img.resize((int(img.width * min_h / img.height), min_h)) for img in imgs]
      grid = Image.new("RGB", (sum(img.width for img in resized), min_h))
      x = 0
      for img in resized: grid.paste(img, (x, 0)); x += img.width
      grid.save("beats_grid.jpg", quality=92)
      
    • Submit grid image + story script via seedance_multimodal_video
  4. kling_omni_video_generation with first_frame_image_path="beat_1.png", mode="pro", enable_sound=true
  5. Platform default video generation with first_frame_images=["beat_1.png"] (no audio → Phase 7 handles it)

Files

./.poster/{project_name}/video/
└── final_video.mp4

Phase 7: Final Output (conditional)

Skip entirely if Phase 6 video already has audio and correct duration (Seedance generate_audio=true or Kling enable_sound=true). Directly copy Phase 6 output as final.mp4.

Execute if video has no audio, audio is inconsistent (per-Beat stitching), or duration needs correction.

Step 1: BGM (if no audio)

music_generation_instrumental(
  prompt="[duration+2]s [auto-derived mood], instrumental only, no vocals, clean mix, cinematic",
  duration=[video_duration + 2]
)

BGM mood mapping: sports/streetwear→urban lo-fi, fragrance/beauty→ethereal ambient, tech→retro synthwave, food→playful quirky, accessories→jazz piano, fashion→cool downtempo.

Embed: embed_audio_track_to_video(video_path, audio_path, replace_existing=true)

Step 2: Trim + Fade (if duration mismatch)

ffmpeg(args=["-y", "-i", input, "-t", "{dur}", "-af", "afade=t=out:st={dur-1}:d=1", output])

Files

./.poster/{project_name}/output/
└── final.mp4

Completion

--- Dynamic Poster Complete ---

Brand: {brand_name}
Surreal Concept: {the_impossible_thing}
Duration: {duration}s  |  Aspect: {ratio}

Output: .poster/{project_name}/output/final.mp4

Anti-Patterns

Load references/anti-patterns.md for full list (14 items, organized by creative/storyboard/video layers).

Top 3 Fatal Errors:

  1. Piling on surreal elements — each video can only have ONE impossible thing
  2. Frontal faces — Seedance will reject outright; must use back views/silhouettes/objects instead
  3. Vague motion prompt — must be extremely detailed (start point/direction/speed/form); a one-line summary = model guesswork

Error Handling

Error Recovery
Product image too low-res Run super_resolution first
Logo has no transparency Use image_generation_tool to remove background
Storyboard frame looks too "AI" Re-generate with more imperfection keywords from references/photography-styles.md, or try different style variant in Phase 3
Product not recognizable Re-generate with stronger product reference, add product close-up keywords
Storyboard frames inconsistent Re-generate individual beats with style_ref as first image_path to enforce style unity
Seedance multimodal fails Fallback: seedance2.0-fast → seedance_image_to_video (beat_1 as first frame) → grid mosaic → Kling pro → platform default video API
Video audio quality poor Generate BGM via music_generation_instrumental and replace audio track