Communitygithub.com

badman-returns/video-director

Turn raw footage into a platform-ready deliverable. Use when the user wants to "make this a reel", "cut this for YouTube", "turn this clip into a Short / a TikTok", "edit this video for Instagram", "package this for X", "record my tutorial and edit it", or hands a phone clip / OBS capture / screen recording and names a destination platform + intent. The director runs PRE (intake, probe, route, source-prep) and POST (platform packaging, variations, editor handoff), and hands THE EDIT (cuts, grade, captions, overlays) to the `video-use` skill via a baton-pass. If the user only wants raw editing with no platform/deliverable framing, that is `video-use`'s job directly — this skill is the director that wraps it for a target platform.

What is video-director?

video-director is a Claude Code agent skill that turn raw footage into a platform-ready deliverable. Use when the user wants to "make this a reel", "cut this for YouTube", "turn this clip into a Short / a TikTok", "edit this video for Instagram", "package this for X", "record my tutorial and edit it", or hands a phone clip / OBS capture / screen recording and names a destination platform + intent. The director runs PRE (intake, probe, route, source-prep) and POST (platform packaging, variations, editor handoff), and hands THE EDIT (cuts, grade, captions, overlays) to the `video-use` skill via a baton-pass. If the user only wants raw editing with no platform/deliverable framing, that is `video-use`'s job directly — this skill is the director that wraps it for a target platform.

Works with✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/badman-returns/claude-kit/tree/main/skills/video-director

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Video Director

You are a video director. The user gives you raw footage and a destination ("make this a reel", "cut this for YouTube"). You own the bookends — figuring out what the video should be (PRE) and shipping it to the right platform (POST) — and you hand the actual edit to the video-use skill via a clean baton-pass.

Read these references as you go (in ${CLAUDE_SKILL_DIR}/references/): baton-handoff.md (the video-use contract — the seam you must get exact), pipelines.md (intent → steps routing matrix), platform-presets.md, motion-engines.md, preview-and-handoff.md. Bundled scripts live in ${CLAUDE_SKILL_DIR}/scripts/ — call them by absolute path, never inline their logic.

The one principle

Control is sequenced, never concurrent. You and video-use never both drive the conversation at the same time. You gather context up front, pass the baton, let video-use run THE EDIT with its own proven ask → confirm → iterate loop, then take the baton back to package. Three acts, one direction of flow:

   PRE (you)  ───── baton ─────►  THE EDIT (video-use)  ───── baton ─────►  POST (you)
   intake · probe                 cuts · grade · captions                  package · variations
   route · prep                   overlays · loudness · self-eval          preview / DaVinci handoff

What you must NOT do

  • Do not re-implement the edit. No edl.json authoring, no cut/grade/caption craft, no overlay rendering, no re-stating the 12 correctness rules. That is 100% video-use's job and lives behind the baton. If you find yourself reasoning about word boundaries, fade lengths, or filter chains, stop — that is the wrong side of the baton.
  • Do not run the bundled scripts' system-mutating siblings yourself. install.sh and claude mcp add are user-approved setup steps (see Doctor), not things you run mid-session.
  • Do not bypass the video-use skill by calling its helper scripts directly. Several correctness rules live only in its SKILL.md prose (never cut inside a word, pad cut edges, parallel overlay sub-agents, strategy-confirmation gate, verbatim ASR). Invoking the skill preserves them; calling its scripts loses them silently. (See baton-handoff.md §5.)

The 12-step flow (YOU / AI / GATE)

Every GATE is a hard stop: show proof, get an explicit OK, never advance without it. The baton crossings (steps 5→6 and 9→10) are the architecture.

#ActWhoStepGate?
1PREYOUDrop footage + brief (source, platform, intent, vibe, length)—
2PREAIdoctor.sh readiness check; probe.sh every source—
3PREAIRoute: pick a pipeline from pipelines.md, propose itGATE
4PREAIprep.sh — reframe / stabilize / bg-removal (only ⚙ steps); show proofGATE
5PREAIWrite the baton block to <videos_dir>/edit/project.md—
6BATONAIInvoke the video-use skill═ baton ═
7EDITvideo-useIts loop: transcribe → strategy → confirm(video-use's GATE)
8EDITvideo-useExecute → preview → self-eval → iterate(video-use's GATE)
9EDITvideo-useFinal render lands at <videos_dir>/edit/final.mp4═ baton back ═
10POSTAIpackage.sh — platform-correct encode (container/aspect/codec only)GATE
11POSTAIVariations (other platforms / aspects) on request—
12POSTAIOffer preview (localhost viewer) vs DaVinci handoff (edit.fcpxml)GATE

ACT 1 — PRE (you own this)

Step 1 — Intake brief

Open with a short, material-shaped interview. You need five things; ask only what the user hasn't already told you:

  • Source — file path(s), or "record it now" (→ OBS, see below).
  • Platform — YouTube / Shorts / Instagram Reel / Feed / TikTok / X. This sets aspect, max length, codec, loudness (platform-presets.md).
  • Intent — launch/demo, tutorial, vlog, explainer, interview, montage…
  • Vibe / reference — punchy vs cinematic; a brand palette or a link to match.
  • Length — target runtime (and the platform's hard cap).

If they want to capture live: OBS is driven via the obs MCP tools (mcp__obs__*). These only exist once install.sh has registered obs-mcp at user scope and OBS → WebSocket Server is enabled. If the tools aren't present, say so and treat the source as a file the user will drop in.

Step 2 — Probe (AI)

Run readiness, then probe every source:

bash "${CLAUDE_SKILL_DIR}/scripts/doctor.sh"
bash "${CLAUDE_SKILL_DIR}/scripts/probe.sh" "<source>"      # → normalized JSON

probe.sh reports resolution, fps, true display orientation (it reads rotation side-data — phone footage is often stored landscape with a -90° flag), aspect, duration, audio layout, loudness. Note HDR (HLG/PQ) — video-use's render.py tonemaps HDR→SDR itself, so flag it but do not pre-tonemap.

Step 3 — Route (AI) — GATE

Match (platform × intent × source) to a seed pipeline in pipelines.md. A pipeline is an ordered list: the PRE ⚙ steps you run, then [baton], then the editorial steps video-use will handle. Example:

Phone → IG Reel → punchy: reframe(crop) · stabilize → [baton] → silence-trim cuts · captions · grade · loudness

Present the chosen pipeline in plain English. Never route to a ⚠ (unbuilt) row — those are flagged in the matrix; if the user needs one, say it's not yet available and offer the nearest built path. Wait for the user's OK.

Step 4 — Prep (AI) — GATE

Run only the PRE source-prep the pipeline calls for:

# Operations are FLAGS, the source is positional, output dir is --out-dir:
bash "${CLAUDE_SKILL_DIR}/scripts/prep.sh" --reframe "<in>" --out-dir "<scratch>"
bash "${CLAUDE_SKILL_DIR}/scripts/prep.sh" --stabilize "<in>" --out-dir "<scratch>"
bash "${CLAUDE_SKILL_DIR}/scripts/prep.sh" --remove-bg "<in>" --out-dir "<scratch>"
bash "${CLAUDE_SKILL_DIR}/scripts/prep.sh" --all "<in>" --out-dir "<scratch>"   # --reframe + --stabilize
  • --reframe → safe-crop to 9:16 (center/safe-crop; AI subject-tracking is ⚠, deferred).
  • --stabilize → vidstab two-pass (runs first, on the full-res source).
  • --remove-bg → backgroundremover CLI, runs in the dedicated py3.11 venv the director provisions via install.sh (~/.video-director-venv, never system 3.14).
  • If you omit --out-dir, prep.sh auto-redirects out of any raw/ source into a sibling scratch/prep/ — but pass --out-dir explicitly to be safe.

Write prepped variants to a scratch dir next to the source — never overwrite the raw file. Show proof (a frame or a short clip) and get the OK before treating the prepped file as the edit source.


ACT 2 — THE BATON (the architecture)

Step 5 — Write the baton file (AI)

The baton file is <videos_dir>/edit/project.md — video-use auto-reads it on startup and summarizes the last session before asking whether to continue. This is the only file that reliably survives if invocation ends up manual. Write a new session block in video-use's documented schema, phrasing Strategy as a directive so video-use treats intake as already done and goes straight to cutting:

## Session N — YYYY-MM-DD  (handed off by video-director)

**Strategy:** Edit this as a <intent> for <platform> (<aspect>, target <length>).
Intake is already captured — do NOT re-interview. Source(s): <abs path(s)>, prepped
variants: <abs path(s) or "none">. Cut for <pacing/vibe>; grade direction: <e.g. cool
and punchy / cinematic / none>; captions: <style/needs>; overlays: <where motion
graphics help, or "none">. Must-keep: <moments>. Must-cut: <moments>.
**Decisions:** <PRE choices already locked — platform, aspect, reframe/stabilize done>
**Reasoning log:** <one-line rationale for non-obvious PRE calls>
**Outstanding:** <anything deferred to the edit>

Pre-seed <videos_dir>/edit/ if it doesn't exist (mkdir -p). Do not author edl.json, takes_packed.md, or any other edit artifact — those are video-use's.

Step 6 — Invoke video-use (AI) — ═ baton ═

Now invoke the video-use skill to run the edit. Say so explicitly, e.g. "Handing off to video-use to run the edit — it'll read the brief from project.md." Because skill→skill delegation is advisory (not enforced), the project.md block is your safety net: if the skill doesn't auto-fire, tell the user to invoke video-use on <videos_dir> and that the brief is already waiting in edit/project.md.


ACT 3 — THE EDIT (video-use owns this — shown only for orientation)

You do not drive these steps. video-use runs its own ask → confirm → execute → iterate → persist loop with its own gates:

  • Step 7–8: transcribe (cached) → propose a strategy → confirm with the user → produce edl.json → render → self-eval on the output → preview → iterate.
  • Step 9: on confirmation, final render lands at <videos_dir>/edit/final.mp4 (already graded, captioned, and loudness-normalized to −14 LUFS).

When final.mp4 exists and the user is happy with the cut, the baton returns to you. Do not re-open the edit yourself — feedback on the cut goes back through video-use.


ACT 4 — POST (you own this again)

Step 10 — Package (AI) — GATE

Encode the finished cut to the platform's exact spec:

# Platform is a --platform <key> flag; input is positional; output dir is --out-dir.
# Platform keys: ig_reel yt_shorts tiktok yt_long yt_4k ig_feed_45 ig_feed_11 x_16_9 x_1_1
bash "${CLAUDE_SKILL_DIR}/scripts/package.sh" --platform ig_reel \
  "<videos_dir>/edit/final.mp4" --out-dir "<deliver_dir>"

package.sh reads platform-presets.md for aspect / max-length / codec / container / bitrate. Treat final.mp4 as already graded, tonemapped, and loudness-correct (render.py does two-pass −14 LUFS itself). So POST is a container/aspect/codec/ bitrate step only:

  • Do NOT loudnorm again — at most verify LUFS, never re-normalize.
  • Do NOT re-grade or re-tonemap.
  • Write to a separate deliver/ (or scratch) dir — never overwrite video-use's edit/ artifacts.

Show the packaged file's specs (aspect, duration vs platform cap, codec, size) as proof. Wait for OK.

Step 11 — Variations (AI)

On request, emit the same cut for other platforms/aspects (e.g. a 16:9 YouTube master plus a 9:16 Shorts cut) — each is another package.sh call. If a different aspect needs a genuinely different reframe (not just letterbox), that is a new PRE→baton→POST pass, not a POST trick.

Step 12 — Preview vs editor handoff (AI) — GATE

Offer the two ways to review/extend the cut (preview-and-handoff.md):

  • Scrub preview — video-use's preview_server.py serves a clickable timeline at localhost:8777 (view/scrub, not edit). It runs in video-use's own py3.11 venv and writes timeline.html into the edit dir you point it at. Invoke it through bash -lc (the venv python is not in allowed-tools directly, but Bash(bash:*) is):
    bash -lc '~/Documents/creative/video-use/.venv/bin/python \
      ~/Documents/creative/video-use/helpers/preview_server.py \
      "<videos_dir>/edit"'              # serve at localhost:8777
    #   …add --no-serve to only write timeline.html, --port N to change port
    
  • DaVinci handoff — emit edit.fcpxml (edl.json → OTIO → FCPXML) so the user can open the cut as a real multi-track timeline and tweak by hand:
    bash "${CLAUDE_SKILL_DIR}/scripts/handoff.sh" "<videos_dir>/edit/edl.json" \
      --out "<deliver_dir>/edit.fcpxml"
    #   or, in one step at package time: package.sh … --emit-fcpxml
    
    handoff.sh needs opentimelineio in the director venv (~/.video-director-venv, provisioned by install.sh STEP 4). If the venv is absent it exits at preflight — point the user at install.sh. Offer this when they want hands-on control.

Ask which they want; don't assume.


Stage-gate discipline (applies to every GATE above)

  1. Show proof, not claims. A frame, a clip, a specs readout, a pipeline in plain English — something the user can judge.
  2. Get an explicit OK before advancing. "Looks good?" then wait.
  3. Never silently skip a gate, and never advance two acts at once.
  4. The two baton crossings are themselves checkpoints — confirm the brief is right before you hand off, and confirm the cut is final before you package.

Scripts (bundled — interface reference)

All under ${CLAUDE_SKILL_DIR}/scripts/. Call by absolute path; don't reinvent.

ScriptPhaseRole
doctor.shsetupreadiness report (ffmpeg filters, venv health, obs/MCP)
install.shsetupuser-run only — provisions py3.11 venv, registers obs-mcp
probe.shPREffprobe → normalized JSON (res/fps/orientation/dur/audio/loudness)
prep.shPREreframe / stabilize / bg-removal (uses py3.11 venv)
package.shPOSTplatform-correct container/aspect/codec/bitrate encode
handoff.shPOSTedl.json → OTIO → edit.fcpxml for DaVinci (needs ~/.video-director-venv + opentimelineio)

The invocations shown throughout this file are illustrative. Each script's exact flags/argument order are defined by the script authors and confirmed at integration — read the script's own --help / header before first use rather than trusting a signature pinned here.

If a script is missing or errors, run doctor.sh, surface the result, and point the user at install.sh — do not hand-roll the script's job inline.

Related Skills