SuperAPI AI Directory

generate-edit-decision-list

General & other

View repository

Updated 10-16 05:49

About this skill

generate-edit-decision-list

Purpose

This is the editorial brain of the creator-grammar pipeline. It transforms:

  • a chosen archetype (from references/archetypes.json)
  • a script or transcript with word-timestamps
  • an optional storyboard scene table or shot-list JSON
  • an optional beat-grid JSON

into a concrete, validated edl.json — the Edit Decision List defined in references/edl-schema.md. The EDL encodes every cut point, role, transition, caption cue, audio beat, and pacing-curve metric for the video. Downstream steps (render-edl, add-zoom-cuts, synthesize-sfx-ffmpeg, add-captions-burn) consume it without further planning decisions.

Two source modes:

  • generative — timeline clips are scenes still to be created. The EDL records a generation spec per clip that the orchestrator passes to image/video gen atoms.
  • conform — timeline clips are time-ranges of existing video files. The EDL records source.file, source.in, source.out per clip. Used to recut an existing video to creator grammar.

Both modes produce the same schema; render-edl executes either.

Inputs

Input Required Notes
archetype yes one of the 8 IDs in references/archetypes.json
script_source one of the two path to a script-locked.md markdown file + word_timestamps_path JSON, OR
words_json one of the two path to a [{text, start, end}] word-timestamps JSON (from transcribe-audio or similar)
scene_table no path to a storyboard scene table JSON or shot-list JSON ([{scene_id, description, duration_s, ...}]). If omitted, clips are derived from VO segments.
beat_grid no path to a beat-grid.json (from extract-beat-grid). Required only if archetype has beat_sync: true.
target_duration yes target video runtime in seconds
source_mode yes "generative" or "conform"
source_files conform mode only list of source video file paths the conform clips are drawn from
output_path yes where to write edl.json

Workflow

This is an LLM-executed planning workflow. Follow these steps in order.

Step 1 — Load archetype parameters

Read references/archetypes.json and extract the record for archetype. Note audio_mode, caption_family, caption_preset, cuts_per_10s, payoff_hold, transition_default, and beat_sync.

Step 2 — Compute the pacing curve

Run scripts/edl_pacing.py to derive the segment boundaries and target cut counts:

python3 skills/atoms/planning/generate-edit-decision-list/scripts/edl_pacing.py \
  --archetype <archetype> \
  --target-duration <target_duration>

Record hook_end_s, payoff_start_s, payoff_end_s, tail_start_s, target_cuts, mean_shot_len_s, and payoff_hold_dur_s — you will use these in every subsequent step.

Step 3 — Lay out the timeline clips

Build the ordered timeline[] array honoring the pacing targets:

Generative mode:

  • Use the scene table as the primary source of clips (one clip per scene or sub-scene). If no scene table is provided, derive clips from VO phrase boundaries in the word-timestamps.
  • Assign role to each clip:
    • The first clip is always "hook".
    • Clips in the hook segment (before hook_end_s) use "hook".
    • Clips covering feature narration use "feature".
    • B-roll cuts away from main VO use "b-roll".
    • Mark exactly one clip "payoff-hold" (see Step 4).
    • The final clip(s) after tail_start_s use "feature" or "establishing".
  • Set transition_in per clip using the archetype's transition_default as the base, then upgrade specific boundaries per the creator grammar:
    • silence-masked-cut on the biggest edit (ideally the cut into the payoff).
    • jump-cut on breath/pause removal (gaps > 0.35s in the word-timestamps).
    • beat-synced-cut if beat_sync: true and a beat-grid is provided.
    • b-roll-insert when cutting away from VO.
  • Fill in source.spec.description per clip from the scene table or from the VO phrase that clip covers. Write in camera-language format: "<shot-size>, <subject>, <action>" (e.g. "ECU, spray nozzle, liquid emerging").
  • Set shot.size and shot.movement per clip following the WS→MS→CU/ECU cycling pattern from CREATOR_GRAMMAR.md §5.
  • Set target_in and target_out so clips are contiguous (no gaps, no overlaps) and the final clip's target_out is within ±0.5s of target_duration.

Conform mode:

  • Load each source file's word-timestamps to map speech to time.
  • Identify the strongest claim (the most direct, benefit-forward sentence) in the transcript and move it to position 0.0–hook_end_s as the hook clip, even if it appeared later in the original recording.
  • Remove inter-word and inter-sentence gaps > 0.35s by splitting at those boundaries: each contiguous speech run becomes a clip with transition_in: "jump-cut".
  • Record source.mode: "file", source.file, source.in, source.out for each clip.
  • Keep the same role, target_in/target_out, and pacing rules as generative mode.

Step 4 — Mark the payoff-hold clip

Identify the clip that represents the hero moment: the product working, the key reveal, the strongest visual proof of the claim. This clip should fall in the payoff window (payoff_start_s to payoff_end_s).

  • Set its role to "payoff-hold".
  • Set its duration to approximately payoff_hold_dur_s (from Step 2), which is mean_shot_len_s × payoff_hold.multiplier from the archetype. Acceptable range is 2.0×–4.0× the mean shot length.
  • Record its id in grammar.payoff_hold_id.
  • Set transition_in: "silence-masked-cut" on this clip (the biggest cut is hidden in the music gap).

Step 5 — Place caption cues

Use the archetype's caption_family to decide caption style:

karaoke-pop family (speech-only or vo+music archetypes):

  • Generate one caption cue per word or word-group from the word-timestamps.
  • Each cue: { "text": "<word(s)>", "start": <master_s>, "end": <master_s>, "preset": "<caption_preset>" }.
  • For conform mode, map source-file word timestamps to master-timeline positions.
  • Suppress captions on clips that have their own on-screen text (e.g. hyperframes, end cards, title cards). Add a notes comment on those clips.

static-title-card family (music-only archetypes):

  • Place one caption cue on the hook clip (or a dedicated title-card clip) that holds for the clip's full duration. This is the single on-screen claim.
  • Do not place per-word cues.

Set grammar.caption_family and grammar.caption_preset from the archetype.

Step 6 — Snap cut points to beat grid (when applicable)

If beat_sync: true for the archetype AND a beat-grid file is provided:

  • For each clip boundary in the body and tail segments, find the nearest bar boundary in the beat-grid.
  • Snap target_in to that bar boundary if within ±150ms (a deliberate half-beat tolerance — do not force snapping that would break a narration phrase).
  • Set transition_in: "beat-synced-cut" on those clips.
  • The hook clip's first cut should land on a downbeat.

Step 7 — Place silence beats and SFX

Silence beats (audio_beats[]):

  • Place one silence beat immediately before the payoff-hold clip (the at time is payoff_hold.target_in - 0.10s, duration 0.25–0.6s from the archetype's characteristic gap).
  • For broll-narrative-essay: place one additional silence beat at the structural pivot between acts (~50% of the video).

SFX on cuts (clip.sfx[]):

  • Add { "type": "whoosh", "at": <target_in> } on feature-flash cuts in the hook and body segments.
  • Add { "type": "tap", "at": <target_in> } on match-cuts or zoom-punch cuts.
  • Do not add SFX to the payoff-hold clip or tail clips.

Step 8 — Assemble the EDL object

Write the complete edl.json per references/edl-schema.md:

  • meta — archetype, target_duration, aspect, fps, audio_mode, source_mode, project_dir
  • grammar — hook_type, caption_family, caption_preset, pacing_profile, payoff_hold_id, loop
  • audio — music, beat_grid, vo, ducking, music_drop_s (set to payoff_hold.target_in)
  • timeline — all clips from Step 3 + Step 4
  • audio_beats — from Step 7
  • pacing_curve — fill from pacing script output and actual clip durations:
    • cuts_per_10s: array of cut density per 10s window
    • mean_shot_len: total_duration / number_of_clips
    • payoff_hold_ratio: payoff_hold_duration / mean_shot_len
    • segments: hook_end_s, payoff_start_s, tail_start_s

Step 9 — Validate

Run the validator before reporting done:

python3 skills/atoms/planning/generate-edit-decision-list/scripts/edl_validate.py <output_path>

If the validator reports errors, fix each one and re-run. Do not deliver an invalid EDL. All nine rules in references/edl-schema.md §"Validation rules" must pass.

Output

  • edl.json at output_path — validated, conforming to references/edl-schema.md.
  • Optionally a brief planning-notes.md in the same folder with the key editorial decisions (archetype rationale, payoff clip choice, beat-sync adjustments).

The EDL schema is fully documented in references/edl-schema.md. The pacing_curve section is derived from the pacing script and actual clip durations.

Quality Checks

  • scripts/edl_validate.py exits 0 (all nine rules pass).
  • Exactly one clip has role: "payoff-hold" and its duration is 2–4× mean_shot_len.
  • All clips are contiguous: timeline[N].target_out == timeline[N+1].target_in within ±1 frame (33ms at 30fps).
  • Last clip target_out is within ±0.5s of meta.target_duration.
  • For conform mode: every source.file path exists on disk.
  • For beat-synced archetypes with a beat-grid: every beat-synced-cut clip's target_in is within ±50ms of a grid boundary.
  • No karaoke-pop captions in a music-only EDL.
  • grammar.caption_preset is a known preset in caption-style-presets.json.
  • meta.archetype is one of the 8 IDs in archetypes.json.

Failure Modes

  • No word-timestamps provided for a karaoke-pop archetype — cannot place per-word caption cues. Request the word-timestamps JSON from transcribe-audio or similar before running.
  • Scene table missing for generative mode — fall back to VO phrase boundaries to derive clips, but flag in planning-notes.md that visual descriptions are placeholder-level and need review before generation.
  • No strongest claim identifiable in conform mode — log a warning in planning-notes.md and keep the original order; do not silently reorder.
  • Beat-grid missing for a beat_sync: true archetype — proceed without beat snapping and add a warning. Record audio.beat_grid: null.
  • Payoff window is too short for the archetype's payoff multiplier — log the shortfall in planning-notes.md and use the longest available shot in the window.
  • Validator exits non-zero — do not deliver the EDL. Fix each reported error and re-validate. Common fixes: reorder clips by target_in; adjust the last clip's target_out to match meta.target_duration; confirm exactly one payoff-hold clip.