broll_veo_generate

AI agent that fills remaining broll gaps by generating 8-second clips with Google Veo 3, then aggressively trimming each clip to its most impactful moment.

Tip: The media processor's veo preset generates the same clips from a spec, and with source: gaps fills empty spans. This processor remains the transcript-driven agent that writes its own prompts. See media and Filling gaps and generating per segment.

When to use

Run after broll_place to cover gaps that existing clips couldn't fill. See the Broll guide.

In the editor

Add it from the Library (B-Roll group), or with + add step and a search for broll_veo_generate, below your broll_place step so that footage you already have gets first pick of the gaps.

Under Inputs, add transcript as a step input and backbone as a step input pointing at your cut. The step's Prompt describes the kind of shot you want, and it is worth being concrete and physical: animals, food, streets, objects. max_generate is a hard budget for the run and the single most useful setting here, because each clip costs money. min_gap_sec decides which gaps are worth filling, target_clip_sec how long the trimmed result should be, and eval_prompt is the standard each generated clip must meet before it is used.

This step needs your own Google key. Add it in the workspace's Variables & Service API Keys, from the editor's Settings. A run that needs a key you have not set is refused before it starts, so nothing is generated or charged.

Tick Review gate and look at what came back before continuing.

Generated clips appear on the b-roll level in the run timeline. Every prompt is checked before anything is generated, and prompts featuring people, faces, screens or objects passing through each other are rejected: those are what generated video gets visibly wrong. Clips already generated in a run group are reused rather than paid for twice.

YAML Example

- 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
    min_clip_sec: 2.0
    target_clip_sec: 4.0
    trim_style: aggressive
    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.
    Feature animals, nature, food, architecture, objects. NO people or faces.
    Simple, literal, physical scene. 1–3 sentences max.
  review: true
  cache: true

Required secrets

GOOGLE_API_KEY: set in workspace or template secrets. A run whose pipeline includes this processor is refused before it starts if the key is missing; the web UI prompts for it.

Inputs

ID Source Description
transcript step Word-level timestamps
backbone step (optional) Cache dep: re-run when cut changes
segment_plan step (optional) A SegmentPlan (e.g. from video_director) constraining which gaps to fill.

Params

Param Type Default Description
eval_prompt text none Accept/reject criteria for generated clip analysis
context text none Background context injected into the system prompt. Supports text:, file:, dir:, files:.
min_gap_sec duration (s) 5 Minimum gap size to fill
max_gap_sec duration (s) 0 Gaps longer than this need coverage (0 = AI decides)
max_duration_sec duration (s) 8 Max seconds to use from any single generated clip
min_clip_sec duration (s) 2 Minimum clip duration after trimming
min_use_sec duration (s) 0 Minimum clip use duration in seconds
target_clip_sec duration (s) 4 Target clip duration to aim for
trim_style select: conservative, balanced, aggressive "aggressive" "aggressive" (trim to best moment) or "conservative" (preserve more)
full_coverage bool false Require every second of the backbone to be covered: no gaps allowed
max_generate number 0 Veo 3 budget per run. 0 = unlimited. Existing cached clips don't count.
no_clip_reuse bool false Reject placements that reuse overlapping in/out ranges
required_clips list none Previously generated clip filenames that must be placed. The AI force-places these before filling remaining gaps.
backbone_step string none Step ID to read backbone timeline from (optional)

Output

EditDecisions on the broll level.

Notes

  • Uses Puffin Ship's built-in AI for the prompt judge; requires a GOOGLE_API_KEY (set in your workspace's Service API Keys) for Veo 3 generation.
  • Veo 3 always generates 8-second clips. The trim step finds the most impactful moment.
  • A prompt judge (Claude) validates every prompt before generation. It rejects: people/faces/humanoids, screens/keyboards, objects passing through each other, intricate mechanical parts, abstract concepts, prompts over 3 sentences.
  • Generated clips are kept separately from the material you uploaded, and each one records what it was generated for, so re-running the step reuses clips it already has.
  • What works: animals, nature, food, architecture, city streets (no people), animation style.