Broll Guide
There are three ways to add broll in Puffin Ship:
- One step that decides everything.
auto_broll_placerplaces 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_placeplaces existing clips from your project's media folder, thenbroll_veo_generatefills 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
mediaprocessor with a preset. Point amediastep at theveoorimagenpreset withsource: 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:approveorrejecttrim_in/trim_out: clean usable range in secondsnotes: 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:
- Get transcript and backbone timeline positions
- Check
get_timeline_state()for what's already placed (including any previous broll steps) - List all available clips and analyze any that aren't yet in the manifest
- For each backbone gap longer than
max_gap_sec: find an approved clip whosenotesdirectly illustrates the spoken content at that moment - 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:
- Scans for glitches (morphing objects, uncanny valley, impossible physics)
- Identifies the single most visually dynamic/interesting moment in the clip
- Sets
trim_in/trim_outto isolate that moment, not just removing bad frames
With trim_style: aggressive (default):
- Target ~
target_clip_secseconds (default 4s): prefer a punchy cut over a long one - Minimum
min_clip_secseconds (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_placefirst and it places 5 clips,broll_veo_generatewill 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_placesteps 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.