Purpose
Turn a raw founder talking-head recording into a creator-native short-form video ad. The
archetype is creator-talking-head (CREATOR_GRAMMAR.md §8): speech-only audio, karaoke-pop
captions, jump-cut breath removal on every pause above the gap threshold, and optional b-roll
inserts over continuous VO.
The edit/assembly path is the EDL editorial pipeline:
transcribe-audio-fal— generate word-timestamps from the recording.create-jump-cuts— remove every breath/pause gap above 0.35 s (the defining creator-native edit).generate-edit-decision-list(conform mode) — plan the full cut rhythm: reorder so the strongest claim is the hook, placeb-roll-insertcues over VO, mark the payoff-hold clip, and write the validatededl.json.render-edl— assemble the master video from the EDL, burn karaoke captions, write manifest.add-captions-klap(optional override) — use Klap instead of render-edl's ASS captions when brand caption style requires Klap's animated treatment.- Human review +
/watch:watchself-QC.
The goal is to make a founder's raw take feel like a trusted creator made it — tight delivery, hook-first structure, captions as the visual spine, ending that may cut mid-sentence.
Inputs
| Input | Required | Notes |
|---|---|---|
source_video |
yes | path to the raw founder talking-head recording (.mp4, .mov, or .m4v) |
target_duration_s |
yes | target clip length in seconds (typical: 20–60 s) |
brand_brief |
yes | brand name, product claim, audience, platform (default: IG Reels / TikTok 9:16) |
b_roll_clips |
no | list of additional clip paths (screen recordings, product footage) to insert as b-roll over VO |
gap_threshold_s |
no | pause removal threshold (default 0.35 s; raise for deliberately slow delivery) |
caption_preset |
no | caption preset ID from caption-style-presets.json (default platform-default) |
use_klap_captions |
no | boolean; if true, run add-captions-klap instead of render-edl's built-in ASS captions |
output_dir |
yes | directory for all outputs and the run manifest |
Composed Atoms
skills/atoms/voiceover/transcribe-audio-fal— generate word-timestamps JSON from the recordingskills/atoms/editing/create-jump-cuts— remove breath/pause gaps to produce a tighter re-encoded takeskills/atoms/planning/generate-edit-decision-list— produceedl.jsonin conform mode for thecreator-talking-headarchetypeskills/atoms/assembly/render-edl— execute the EDL intomaster.mp4(video + karaoke captions + audio)skills/atoms/captions/add-captions-klap— optional: replace ASS captions with Klap animated captions
Workflow
Phase 1 — Prepare inputs
- Confirm
source_videoexists on disk. If the file is missing, stop and report. - Confirm
ffmpegandffprobeare installed (ffmpeg -version). If missing, stop and report. - Confirm
output_direxists or create it.
Phase 2 — Transcribe
Run transcribe-audio-fal on source_video to produce working/words.json
(word-timestamps in [{"text", "start", "end"}] shape).
# transcribe-audio-fal produces: output_dir/working/words.json
If transcription fails, stop — the word-timestamps are required for every downstream step.
Phase 3 — Jump-cut breath removal
Run create-jump-cuts using the word-timestamps to remove every inter-word and inter-sentence
gap above gap_threshold_s (default 0.35 s):
python3 skills/atoms/editing/create-jump-cuts/scripts/jump_cut.py \
--source <source_video> \
--words <output_dir>/working/words.json \
--output <output_dir>/working/tight-take.mp4 \
--gap-threshold <gap_threshold_s> \
--crf 18
Review manifest.json from this step: confirm total_removed_seconds > 0. If the take has no
pauses above threshold, the tight take equals the source — that is fine, proceed.
Caution: if
gap_threshold_sis unusually low (< 0.20 s) on a slow-paced intentional delivery, jump cuts will over-cut the speaker's cadence. Use the default (0.35 s) unless the brief explicitly calls for a faster chop.
Phase 4 — Generate the EDL (conform mode)
Run generate-edit-decision-list in conform mode with the creator-talking-head archetype.
Pass the word-timestamps from Phase 2 (aligned to the tight take's timeline after Phase 3).
Key behaviors the EDL generator applies:
- Hook-first reorder — identifies the strongest benefit-forward sentence in the transcript and moves it to the first 0–15% of the target duration as the hook clip.
- Jump-cut boundaries — each contiguous speech run in the tight take becomes a clip with
transition_in: "jump-cut". - B-roll inserts — if
b_roll_clipsare provided, inserts them asb-roll-insertcuts over continuous VO at natural phrase boundaries. - Payoff-hold — marks the strongest visual proof moment as
role: "payoff-hold"(~2× mean shot length, per archetype parameters inarchetypes.json). - Karaoke captions — places per-word caption cues from the word-timestamps, using
caption_preset(defaultplatform-default).
python3 skills/atoms/planning/generate-edit-decision-list/scripts/edl_pacing.py \
--archetype creator-talking-head \
--target-duration <target_duration_s>
# then run the LLM-executed planning workflow per generate-edit-decision-list SKILL.md
Validate: run edl_validate.py on working/edl.json. All nine schema validation rules must
pass before proceeding to render.
Phase 5 — Render the master
Run render-edl on the validated EDL:
python3 skills/atoms/assembly/render-edl/scripts/render_edl.py \
--edl <output_dir>/working/edl.json \
--output <output_dir>/finals/master.mp4 \
--crf 18
render-edl will:
- Trim conform clips from
tight-take.mp4(and b-roll source files) persource.in/source.out. - Concatenate as hard cuts.
- Burn karaoke-pop ASS captions (unless
use_klap_captionsis true — see Phase 6). - Write
manifest.jsontofinals/.
Phase 6 — Captions (conditional)
Default (use render-edl built-in ASS): no extra step needed; captions are burned in Phase 5.
Klap override (use_klap_captions: true): run add-captions-klap on the master produced in
Phase 5, replacing the ASS captions with Klap's animated treatment. Use this when the brand's
existing ads use Klap-style animated captions and matching that treatment is required.
Phase 7 — Self-QC and human review
- Run
/watch:watch(or equivalent frame-extraction + transcribe) onfinals/master.mp4. Do not declare done from a still frame — verify captions, cut rhythm, and hook placement by watching the video. - Confirm:
- The hook (first ~15% of the video) contains the strongest product claim.
- Breath/pause gaps are removed; delivery feels tight.
- If b-roll was inserted, audio is continuous (L-cut) under the inserts.
- No caption/hyperframe text collision.
- Duration is within ±0.5 s of
target_duration_s.
- Write
verification.mdtooutput_dir.
Decision Rules
| Decision | Rule |
|---|---|
| Gap threshold | Default 0.35 s. Raise to 0.5 s if the founder's delivery is intentionally slow or conversational; do NOT over-cut measured emphasis. |
| Hook-first reorder | Always reorder in conform mode unless the founder's opening line is already the strongest claim (confirm by reading the transcript before running the EDL generator). |
| B-roll inserts | Insert b-roll clips when b_roll_clips is non-empty AND a clip covers a factual claim that could be visualized. Place at phrase boundaries, never mid-sentence. |
| Karaoke vs. Klap captions | Use render-edl's built-in ASS karaoke by default. Switch to add-captions-klap only when the brand's existing ads demonstrably use Klap captions and matching that style is required. Klap runs last — never before render. |
| EDL conform vs. generative | Always use conform mode for founder talking-head. Generative mode is for new scene creation, not re-editing existing footage. |
| Payoff-hold | Even though payoff_hold.required: false for this archetype, identify and mark the strongest visual/claim moment as payoff-hold. The pacing curve needs an anchor. |
| Scaffolded atoms | If any composed atom is not yet implemented (no script on disk), stop and report exactly which atom is missing rather than silently substituting. |
Output
output_dir/finals/master.mp4— finished 9:16 video with captions burned and audio intact.output_dir/finals/manifest.json— render metadata: skill, run_id, edl_path, clips_rendered, pacing_curve, status, warnings, errors.output_dir/working/edl.json— the validated Edit Decision List.output_dir/working/tight-take.mp4— intermediate jump-cut output.output_dir/working/words.json— word-timestamps from transcription.output_dir/verification.md— self-QC results and human review notes.
Quality Checks
master.mp4exists, is non-zero, andffprobereports both video and audio streams.- Duration of
master.mp4is within ±0.5 s oftarget_duration_s. manifest.jsonreportsstatus: pass.edl.jsonpasses all nine validation rules (validator exits 0).- The first clip in the EDL has
role: "hook"and contains the strongest claim. pacing_curve.payoff_hold_ratiois between 2.0 and 4.0.- Karaoke captions are present and cover every spoken word.
- No caption text appears over a b-roll insert that carries its own on-screen text.
verification.mdexists and documents the watch-through result.
Failure Modes
- Source video missing or unreadable — stop immediately; report the path.
- Transcription fails — no word-timestamps means no jump-cut segmentation or EDL caption cues. Check
FAL_API_KEY/ provider credentials; do not proceed without a validwords.json. - No pauses detected by create-jump-cuts — not an error;
tight-take.mp4equalssource_video. Note inverification.mdthat no gaps were removed. - EDL validator exits non-zero — fix all reported errors before running
render-edl. Common issues: non-contiguous timeline, missing payoff-hold clip, last cliptarget_out>target_duration + 0.5 s. - B-roll clip path does not exist — skip the missing b-roll and log a warning in the manifest. Do not fail the whole render.
- No strongest claim identifiable — keep original order and log a warning in
planning-notes.md; do not silently reorder. ffmpegnot installed — bothcreate-jump-cutsandrender-edlrequire ffmpeg. Install viabrew install ffmpeg.- render-edl missing generate-mode clips — not applicable in conform mode. If the EDL was accidentally set to generative mode, fix
meta.source_modeto"conform". - Caption preset not found —
render-edlfalls back toplatform-defaultand warns. Explicitly set a valid preset fromcaption-style-presets.jsonto avoid the fallback.