Broll Guide

There are three ways to add broll in Puffin Ship:

  • One step that decides everything. auto_broll_placer places existing footage, generates new clips, pulls in web media, and adds overlays in a single pass. Use this when you want a good result without wiring up the individual pieces yourself.
  • The classic two-step chain. broll_place places existing clips from your project's media folder, then broll_veo_generate fills whatever gaps are left by generating new clips with Veo 3. This gives you the most control over each stage, and it's what the rest of this guide covers in detail.
  • The media processor with a preset. Point a media step at the veo or imagen preset with source: gaps, and it fills empty spans on a level with spec-driven generation. Use this when you want to configure the generation request yourself rather than let an agent write prompts. See Filling gaps and generating per segment and Media services.

The rest of this guide covers the classic chain: broll_place then broll_veo_generate. Run them in this order. The generate step reads the full timeline state and only targets positions that broll_place left empty.

In the editor

Both steps come from the Library, under B-Roll, and go after your transcript and your cut. Add broll_place first, then broll_veo_generate below it: the order in the step list is the order they run, and it is what gives footage you already have first pick of the gaps.

For broll_place, wire transcript and backbone as step inputs and clips as a file input naming your folder of footage. For broll_veo_generate, wire transcript and backbone the same way and set max_generate, which is a hard cap on how many clips it may generate and therefore on what the step can cost. Generation also needs your own Google key, added under Variables & Service API Keys; a run that needs a key you have not set stops before it starts rather than partway through.

Tick Review gate on both. B-roll is the part of a video people notice when it is wrong, and the gate lets you look before captions and titles are built on top of it.

What you get in the run timeline is a b-roll level filled with clips over the moments you are not the focus. Preview it, retime or delete anything that does not work, and re-run just that step with the control rather than starting over.

If you would rather have one step decide everything, auto_broll_placer does the job of both plus web media and overlays in a single pass.


broll_place: Placing Existing Clips

Point this at a folder of .mp4 clips. Claude vision analyzes each one (cached), then an AI agent decides where to place them based on what the speaker is saying.

- id: broll
  processor: broll_place
  input:
    - id: transcript
      step: transcribe_main      # word-level timestamps
    - id: clips
      file: broll-clips          # project input ID pointing to your clips folder
    - id: backbone
      step: ai_cut               # cache dep: re-run when the cut changes
  params:
    min_gap_sec: 8               # minimum spacing between placed clips (default 5)
    max_gap_sec: 20              # gaps longer than this need coverage (default 0 = AI decides)
    max_duration_sec: 8          # max seconds to use from any single clip (default 8)
    backbone_step: ai_cut        # step to read backbone timeline from
    eval_prompt: >
      Accept: direct visual match to spoken content.
      Reject: vague topic overlap, people facing away, blurry footage.
  output:
    timeline: broll
  prompt: |
    Analyze every unanalyzed clip first (free, mandatory).
    Then fill backbone timeline gaps using approved clips where the content
    directly matches what the speaker is saying; vague topic overlap is not enough.
    Each clip should be placed at most once.
    Leave unfilled gaps blank; a broll_veo_generate step will handle those.
  review: true
  cache: true

Clip Manifest

Analysis results are remembered between runs, so a clip that has already been analyzed is never analyzed or generated a second time.

Each entry records:

  • verdict: approve or reject
  • trim_in / trim_out: clean usable range in seconds
  • notes: what the clip actually shows

To force re-analysis, ask the AI Assistant to clear the step's saved work.

Clip Placement Logic

The AI agent follows this workflow:

  1. Get transcript and backbone timeline positions
  2. Check get_timeline_state() for what's already placed (including any previous broll steps)
  3. List all available clips and analyze any that aren't yet in the manifest
  4. For each backbone gap longer than max_gap_sec: find an approved clip whose notes directly illustrates the spoken content at that moment
  5. Place the clip; each clip is used at most once

Matching is strict by design. "Approved" clips that don't match the content are left unused for a different gap or skipped entirely. This prevents random B-roll that doesn't relate to what's being said.


broll_veo_generate: Generating with Veo 3

Fills gaps that broll_place didn't cover. Requires a GOOGLE_API_KEY set in your workspace's Service API Keys.

Veo 3 always generates 8-second clips. The analysis step aggressively trims each clip to its most impactful moment, by default targeting ~4s cuts with a 2s minimum. This creates faster visual rhythm. Use the full 8s only when the entire clip is uniformly excellent.

- id: broll_ai
  processor: broll_veo_generate
  input:
    - id: transcript
      step: transcribe_main
    - id: backbone
      step: ai_cut
  params:
    min_gap_sec: 8
    max_gap_sec: 20
    backbone_step: ai_cut
    max_generate: 5              # Veo 3 budget per run (0 = unlimited)
    min_clip_sec: 2.0            # minimum clip duration after trimming (default 2.0)
    target_clip_sec: 4.0         # preferred clip duration to aim for (default 4.0)
    trim_style: aggressive       # "aggressive" (default) or "conservative"
    eval_prompt: >
      Accept: clear, focused shot without glitches or uncanny elements.
      Reject: blurry, morphing objects, impossible physics.
  output:
    timeline: broll
  prompt: |
    Check get_timeline_state() first to see what's already placed.
    Only generate clips for unfilled gaps longer than max_gap_sec.
    Leave shorter gaps blank.

    When writing prompts for generate_broll_clip:
    - Feature animals, nature, food, architecture, vehicles, or objects. NO people
    - Simple, literal, physical scene. No abstract concepts
    - Cartoon/animated style works great for conceptual topics
    - 1–3 sentences max

    For longer gaps, consider placing multiple shorter clips rather than one long one.
  review: true
  cache: true

Trimming Behavior

After generation, Claude vision analyzes every frame and:

  1. Scans for glitches (morphing objects, uncanny valley, impossible physics)
  2. Identifies the single most visually dynamic/interesting moment in the clip
  3. Sets trim_in/trim_out to isolate that moment, not just removing bad frames

With trim_style: aggressive (default):

  • Target ~target_clip_sec seconds (default 4s): prefer a punchy cut over a long one
  • Minimum min_clip_sec seconds (default 2s)
  • Use the full 8s only when the entire clip is uniformly excellent

With trim_style: conservative:

  • Still finds the best portion but is less strict about cutting runtime

Prompt Judge

Before calling Veo 3, every prompt is sent to Claude for validation. The judge rejects prompts that describe:

  • People, faces, or humanoid figures: AI-generated humans trigger uncanny valley
  • Computer/phone/tablet screens, keyboards, or UI elements
  • Objects passing through each other or impossible physics
  • Intricate mechanical objects (gears, watch internals, engine parts)
  • Abstract concepts without a concrete visual scene
  • More than 3 sentences
  • Descriptor words like "dramatic," "cinematic," or "epic"

If approved with minor issues, the judge rewrites the prompt before generation.

What works well

✓ Animals doing things: a cat knocking things off a shelf, birds landing ✓ Food and cooking: coffee being poured, bread rising ✓ Nature: clouds moving, waves, fire, rain ✓ Architecture and spaces: empty offices, server rooms, city streets (no people) ✓ Cartoon/animation style: good for abstract topics ✓ Simple object interactions with clean physics

Generation Budget

max_generate limits Veo 3 calls per pipeline run. Existing generated clips (already in the manifest) don't count toward the budget. Set max_generate: 0 for unlimited.

Generated clips are cached like existing clips. Re-running with a higher budget fills additional gaps.

Reviewing generated b-roll

To approve or reject b-roll before it's finalized, add a review gate to the step (review: true). The run pauses at the gate and shows you the planned placements to approve, edit, reject, or regenerate. See Review Gates.


Full Timeline Awareness

Both broll_place and broll_veo_generate see all clips placed on the broll level across all previous pipeline steps, not just what the current step has placed. This means:

  • If you run broll_place first and it places 5 clips, broll_veo_generate will see those 5 clips when checking for gaps
  • Overlap detection also checks against all previous steps, so two steps can never place overlapping clips on the same level
  • You can run multiple broll_place steps with different clip sources, and each one sees what the others already placed

Ordering and Priority

The order of your broll steps controls placement priority. Earlier steps have first pick:

# Higher priority: these existing clips get placed first
- id: broll
  processor: broll_place
  ...

# Lower priority: only fills what broll_place left empty
- id: broll_ai
  processor: broll_veo_generate
  ...

You could flip the order to give AI-generated clips priority over existing ones, though this is rarely useful.


broll_imagen_generate: Generating with Imagen

An alternative to Veo 3 when you want generated still images with motion rather than full video. Faster and cheaper per clip. See broll_imagen_generate for full params.

- id: broll_img
  processor: broll_imagen_generate
  input:
    - id: transcript
      step: transcribe_main
    - id: backbone
      step: ai_cut
  params:
    backbone_step: ai_cut
    max_generate: 8
    target_dur_sec: 4.0
    motion_style: zoom_in
    eval_prompt: >
      Accept: clear, focused image without distortion or artifacts.
      Reject: blurry, faces, text artifacts, impossible geometry.
  output:
    timeline: broll
  cache: true

broll_screenshot_websource: Animated Web Screenshots

Generates animated background clips from web screenshots. By default (auto_find: true), it uses AI web search to find and screenshot relevant pages based on the transcript. You can also supply URLs directly. Motion effects (zoom, blur, pixelate) are applied to each screenshot. See broll_screenshot_websource for full params.


Ordering all four processors

Earlier steps have first pick of gaps:

# 1. Existing clips first: highest relevance
- id: broll
  processor: broll_place
  ...

# 2. Web screenshots: for specific topic coverage
- id: web_broll
  processor: broll_screenshot_websource
  ...

# 3. Imagen stills: fast generated imagery
- id: broll_img
  processor: broll_imagen_generate
  ...

# 4. Veo 3 video: fills remaining gaps with full video generation
- id: broll_ai
  processor: broll_veo_generate
  ...

Each step reads the full broll level state and only targets gaps left by earlier steps.