Video Use
Principle
- LLM reasons from raw transcript + on-demand visuals. The only derived artifact that earns its keep is a packed phrase-level transcript (
takes_packed.md). Everything else — filler tagging, retake detection, shot classification, emphasis scoring — you derive at decision time. → verify: step output matches expected outcome - Audio is primary, visuals follow. Cut candidates come from speech boundaries and silence gaps. Drill into visuals only at decision points. → verify: step output matches expected outcome
- Ask → confirm → execute → iterate → persist. Never touch the cut until the user has confirmed the strategy in plain English.
- Generalize. Do not assume what kind of video this is. Look at the material, ask the user, then edit. → verify: diff matches intended change
- Artistic freedom is the default. Every specific value, preset, font, color, duration, pitch structure, and technique in this document is a worked example from one proven video — not a mandate. Read them to understand what's possible and why each worked. Then make your own taste calls based on what the material actually is and what the user actually wants. The only things you MUST do are in the Hard Rules section below. Everything else is yours. → verify: file content matches expected shape
- Invent freely. If the material calls for a technique not described here — split-screen, picture-in-picture, lower-third identity cards, reaction cuts, speed ramps, freeze frames, crossfades, match cuts, L-cuts, J-cuts, speed ramps over breath, whatever — build it. The helpers are ffmpeg and PIL. They can do anything the format supports. Do not wait for permission. → verify: step output matches expected outcome
- Verify your own output before showing it to the user. If you wouldn't ship it, don't present it.
Hard Rules (production correctness — non-negotiable)
These are the things where deviation produces silent failures or broken output. They are not taste, they are correctness. Memorize them.
- Subtitles are applied LAST in the filter chain, after every overlay. Otherwise overlays hide captions. Silent failure. → verify: step output matches expected outcome
- Per-segment extract → lossless
-c copyconcat, not single-pass filtergraph. Otherwise you double-encode every segment when overlays are added. - 30ms audio fades at every segment boundary (
afade=t=in:st=0:d=0.03,afade=t=out:st={dur-0.03}:d=0.03). Otherwise audible pops at every cut. → verify: step output matches expected outcome - Overlays use
setpts=PTS-STARTPTS+T/TBto shift the overlay's frame 0 to its window start. Otherwise you see the middle of the animation during the overlay window. → verify: step output matches expected outcome - Master SRT uses output-timeline offsets:
output_time = word.start - segment_start + segment_offset. Otherwise captions misalign after segment concat. → verify: step output matches expected outcome - Never cut inside a word. Snap every cut edge to a word boundary from the Scribe transcript. → verify: step output matches expected outcome
- Pad every cut edge. Working window: 30–200ms. Scribe timestamps drift 50–100ms — padding absorbs the drift. Tighter for fast-paced, looser for cinematic. → verify: step output matches expected outcome
- Word-level verbatim ASR only. Never SRT/phrase mode (loses sub-second gap data). Never normalized fillers (loses editorial signal). → verify: diff matches intended change
- Cache transcripts per source. Never re-transcribe unless the source file itself changed. → verify: step output matches expected outcome
- Parallel sub-agents for multiple animations. Never sequential. Spawn N at once via the
Agenttool; total wall time ≈ slowest one. → verify: step output matches expected outcome - Strategy confirmation before execution. Never touch the cut until the user has approved the plain-English plan. → verify: step output matches expected outcome
- All session outputs in
<videos_dir>/edit/. Never write inside thevideo-use/project directory. → verify: output exists + parses without error
Everything else in this document is a worked example. Deviate whenever the material calls for it.
Directory layout
The skill lives in video-use/. User footage lives wherever they put it. All session outputs go into <videos_dir>/edit/.
<videos_dir>/
├── <source files, untouched>
└── edit/
├── project.md ← memory; appended every session
├── takes_packed.md ← phrase-level transcripts, the LLM's primary reading view
├── edl.json ← cut decisions
├── transcripts/<name>.json ← cached raw Scribe JSON
├── animations/slot_<id>/ ← per-animation source + render + reasoning
├── clips_graded/ ← per-segment extracts with grade + fades
├── master.srt ← output-timeline subtitles
├── downloads/ ← yt-dlp outputs
├── verify/ ← debug frames / timeline PNGs
├── preview.mp4
└── final.mp4
Setup
ELEVENLABS_API_KEYin.envat project root or env. Ask and write.envif missing.ffmpeg+ffprobeon PATH.- Python deps:
pip install -e .. yt-dlp,manim, Remotion installed only on first use.- This skill vendors
skills/manim-video/. Read its SKILL.md when building a Manim slot.
Helpers
transcribe.py <video>— single-file Scribe call.--num-speakers Noptional. Cached.transcribe_batch.py <videos_dir>— 4-worker parallel transcription. Use for multi-take.pack_transcripts.py --edit-dir <dir>—transcripts/*.json→takes_packed.md(phrase-level, break on silence ≥ 0.5s).timeline_view.py <video> <start> <end>— filmstrip + waveform PNG. On-demand visual drill-down. Not a scan tool — use it at decision points, not constantly.render.py <edl.json> -o <out>— per-segment extract → concat → overlays (PTS-shifted) → subtitles LAST.--previewfor 720p fast.--build-subtitlesto generate master.srt inline.grade.py <in> -o <out>— ffmpeg filter chain grade. Presets +--filter '<raw>'for custom.
For animations, create <edit>/animations/slot_<id>/ with Bash and spawn a sub-agent via the Agent tool.
The process
-
Inventory.
ffprobeevery source.transcribe_batch.pyon the directory.pack_transcripts.pyto producetakes_packed.md. Sample one or twotimeline_views for a visual first impression. → verify: step output matches expected outcome -
Pre-scan for problems. One pass over
takes_packed.mdto note verbal slips, obvious mis-speaks, or phrasings to avoid. Plain list, feed into the editor brief. → verify: step output matches expected outcome -
Converse. Describe what you see in plain English. Ask questions shaped by the material. Collect: content type, target length/aspect, aesthetic/brand direction, pacing feel, must-preserve moments, must-cut moments, animation and grade preferences, subtitle needs. Do not use a fixed checklist — the right questions are different every time. → verify: all tests pass
-
Propose strategy. 4–8 sentences: shape, take choices, cut direction, animation plan, grade direction, subtitle style, length estimate. Wait for confirmation. → verify: step output matches expected outcome
-
Execute. Produce
edl.jsonvia the editor sub-agent brief. Drill intotimeline_viewat ambiguous moments. Build animations in parallel sub-agents. Apply grade per-segment. Compose viarender.py. → verify: command exit code 0 -
Preview.
render.py --preview. → verify: step output matches expected outcome -
Self-eval (before showing the user). Run
timeline_viewon the rendered output (not the sources) at every cut boundary (±1.5s window). Check each image for: → verify: command exit code 0- Visual discontinuity / flash / jump at the cut
- Waveform spike at the boundary (audio pop that slipped past the 30ms fade)
- Subtitle hidden behind an overlay (Rule 1 violation)
- Overlay misaligned or showing wrong frames (Rule 4 violation)
Also sample: first 2s, last 2s, and 2–3 mid-points — check grade consistency, subtitle readability, overall coherence. Run
ffprobeon the output to verify duration matches the EDL expectation.If anything fails: fix → re-render → re-eval. Cap at 3 self-eval passes — if issues remain after 3, flag them to the user rather than looping forever. Only present the preview once the self-eval passes.
-
Iterate + persist. Natural-language feedback, re-plan, re-render. Never re-transcribe. Final render on confirmation. Append to
project.md. → verify: step output matches expected outcome
Cut craft (techniques)
- Audio-first. Candidate cuts from word boundaries and silence gaps.
- Preserve peaks. Laughs, punchlines, emphasis beats. Extend past punchlines to include reactions — the laugh IS the beat.
- Speaker handoffs benefit from air between utterances. Common values: 400–600ms. Less for fast-paced, more for cinematic. Taste call.
- Audio events as signals.
(laughs),(sighs),(applause)mark beats. Extend past them. - Silence gaps are cut candidates. Silences ≥400ms are usually the cleanest. 150–400ms phrase boundaries are usable with a visual check. <150ms is unsafe (mid-phrase).
- Example cut padding (the launch video shipped with this): 50ms before the first kept word, 80ms after the last. Tighter for montage energy, looser for documentary. Stay in the 30–200ms working window (Hard Rule 7).
- Never reason audio and video independently. Every cut must work on both tracks.
The packed transcript (primary reading view)
pack_transcripts.py reads all transcripts/*.json and produces one markdown file where each take is a list of phrase-level lines, each prefixed with its [start-end] time range. Phrases break on any silence ≥ 0.5s OR speaker change. This is the artifact the editor sub-agent reads to pick cuts — it gives word-boundary precision from text alone at 1/10 the tokens of raw JSON.
Example line:
## C0103 (duration: 43.0s, 8 phrases)
[002.52-005.36] S0 Ninety percent of what a web agent does is completely wasted.
[006.08-006.74] S0 We fixed this.
Editor sub-agent brief (for multi-take selection)
When the task is "pick the best take of each beat across many clips," spawn a dedicated sub-agent with a brief shaped like this. The structure is load-bearing; the pitch-shape example is not.
You are editing a <type> video. Pick the best take of each beat and
assemble them chronologically by beat, not by source clip order.
INPUTS:
- takes_packed.md (time-annotated phrase-level transcripts of all takes)
- Product/narrative context: <2 sentences from the user>
- Speaker(s): <name, role, delivery style note>
- Expected structure: <pick an archetype or invent one>
- Verbal slips to avoid: <list from the pre-scan pass>
- Target runtime: <seconds>
Common structural archetypes (pick, adapt, or invent):
- Tech launch / demo: HOOK → PROBLEM → SOLUTION → BENEFIT → EXAMPLE → CTA
- Tutorial: INTRO → SETUP → STEPS → GOTCHAS → RECAP
- Interview: (QUESTION → ANSWER → FOLLOWUP) repeat
- Travel / event: ARRIVAL → HIGHLIGHTS → QUIET MOMENTS → DEPARTURE
- Documentary: THESIS → EVIDENCE → COUNTERPOINT → CONCLUSION
- Music / performance: INTRO → VERSE → CHORUS → BRIDGE → OUTRO
- Or invent your own.
RULES:
- Start/end times must fall on word boundaries from the transcript.
- Pad cut boundaries (working window 30–200ms).
- Prefe