shipped@di-atomic/video-director · v0.3.0 · beta

Your 60-second video is 57 seconds.

Transitions overlap the shots either side of them, so a plan whose clip lengths add up to sixty renders fifty-seven seconds of video and three seconds of black. Nothing errors. video-director turns a script into a shot list your renderer accepts unmodified: it solves for content rather than for the raw sum, quantizes generated clips to the lengths models actually produce, and names the engine on every row. It also times every voiceover line against the shot it plays over, in seven measured languages. And it can plan from a video you liked: hand it a template that video-analyst measured and it fills the same structure and pace, then hands back what the engines cannot shoot.

For anyone whose agent makes video, and who has watched a render succeed, come back the right file size, and still be wrong.

A dark chalkboard showing one long horizontal bar. The long left portion is filled with white chalk hatching and labelled 57s CONTENT; a short stub at the right end is outlined in gold and left empty, labelled 3s BLACK.
Built by Di-Atomic Marketing & compliance agency Measured on real renders, not inferred 7-language team Clients incl. ONYX Radiance, Pamit Group
3.0sof black a naive 60-second plan ships, unannounced
11 of 35voiceover beats in my own demo scripts that ran past their shot
12 of 12adversarial shot lists rejected, including an empty one
5verifiers that print PASS or FAIL with numbers
Installopvs-skills install @di-atomic/video-director

Then say: “turn this script into a shot list”, “why does my video end in black?”, “does this script fit 60 seconds?” or “make it like this template”.

Why the plan a person writes is the plan that fails

What a hand-written shot list does
want 60s, so pick clips that add to 60
8 + 8 + 8 + 8 + 8 + 10 + 10 = 60
send it to the renderer

→ six cuts overlap; where did 3s go?
→ 10s is not a length veo3 makes
→ is a row a shot, or a whole post?
→ transition left at the default (a crossfade)
→ nothing errors, so nobody checks

(ship it, find out later)

Every one of those is silent. The render succeeds, the file is the right size, and the last three seconds are black.

What video-director produces
mode     REQUIRED, no default, rejected if absent
engine   named on every row, never inferred
len      only a length the model actually makes
content  sum(len) − (n−1) × transition_seconds
target   solved for content, so 8×6 + 15 = 63
seam     axis, direction and speed per cut
default  a defaulted transition is counted
voice    every line timed against its own shot
gate     5 verifiers, before a clip is bought

A plan you can check before you pay for it, because the arithmetic that produced it is printed alongside it.

A render that succeeds is not a render that is right.

Every row names how its asset is made, and the type follows

aiA generated clip. Capped at 5 to 15 seconds, and only on a length the model natively produces.
avatarA lipsync take. Driven by the length of the line it speaks.
screenA real screen recording. Any length, and elastic, so it absorbs the remainder.
motionA composition with props. Any length, and where a title card or logo hold costs no generation.
typeWhat the renderer does with a finished asset. Derived from the engine, never chosen by hand.

What you actually get

🧮

Arithmetic that accounts for overlap

Transitions overlap their neighbours, so content = sum(len) − (n−1) × transition_seconds. Seven clips totalling sixty seconds with six half-second cuts render fifty-seven. The planner solves for content, and the verifier prints the black tail you would have shipped.

🎛️

Durations quantized to what models make

veo3 returns eight seconds. sora2 returns ten or fifteen. No model honours a request for 6.3. So in an all-generated package you close a gap by changing the shot count, not by stretching a clip. In a mixed one, the slack goes on a screen or motion row.

✂️

Cuts you can check before rendering

The schema defaults transition to fade, a crossfade carries nothing across the cut, and the craft rule forbids crossfades. So accepting the default is itself the defect. Seams are graded in the renderer’s own transition vocabulary, on the plan, with no animation library shipped.

One 60-second short, planned and gated

> "turn this script into a 60-second short"

  mode ........... single_video   (asked, never guessed)
  aspect ......... 9:16  fps 30

  FIRST ATTEMPT: the plan a person writes
  8 + 8 + 8 + 8 + 8 + 10 + 10 = 60

  verify-shot-list.mjs --target 60
    shot 6: len 10s is NOT native for veo3 (native: 8s)
    content 57.00s misses target 60s by 3.00s
    black tail a naive sum would ship: 3.00s
    solve for sum len = 60 + 3.00 = 63.00s
  RESULT ......... FAIL (2 violations)

  CORRECTED
  8 × 6 + 15 = 63
    n = 7,  overlap = 6 × 0.5 = 3.0
    content = 60.00s

  verify-shot-list.mjs ............ PASS
  verify-projectability.mjs ....... PASS  0 unmapped fields
  verify-seam-ledger.mjs .......... PASS  0 defaulted transitions
  verify-prompt-grammar.mjs ....... PASS

  → handed to media-generator: 7 rows, 0 edits

Checking a plan is free. Rendering it is not. So the whole list is graded before a single clip is generated. The gate also reports the black tail even on a PASS, as a reminder of what the raw sum would have cost.

Two constraints, and they are coupled

A dark chalkboard showing exactly two white chalk rectangles side by side, overlapping slightly, with the narrow overlapping sliver filled solid gold. Labelled ONE CUT above and 0.5s below, with x 6 = 3.0s in the lower right.
Every cut subtracts. The overlap is real time removed from the finished video. Six half-second cuts cost three seconds, and the renderer fills the gap with black rather than complaining.
A dark chalkboard showing four upright blocks in a row of increasing width, the first three outlined in white chalk and labelled 8s, 10s and 15s, the fourth outlined in gold with a white chalk X drawn across it and labelled 6.3s.
You cannot ask for the length you are missing. Generated clips come in fixed native sizes, so hitting a target is a small search over shot counts rather than a subtraction.

Every voiceover line, timed against its own shot new in v0.2.0

A chalk film frame labelled SHOT with a voiceover wave that runs past its right edge. The part outside the frame is drawn in gold and labelled TOO LONG, under a chalk stopwatch.
> "does this script fit 60 seconds?"

  verify-vo-fit.mjs demo-script.md
  lang en · rate 2.38 words/s (measured, conservative)

  beat                 window    est.    status
  0-5s Hook              4.9s    4.62s   PASS
  5-15s Setup            9.9s   11.76s   FAIL  +1.86s  max_words 23
  15-25s draftCopy       9.9s    7.14s   PASS
  25-40s editCopy       14.9s   13.87s   PASS
  40-50s scoreCopy       9.9s    6.72s   PASS
  50-58s compliance      7.9s   10.08s   FAIL  +2.18s  max_words 18
  58-60s Close          1.75s    5.46s   FAIL  +3.71s  max_words 4

  measured total speech ... 55.1s of 60s   (the total fits)
  RESULT .................. FAIL (3 beats)

  → 3 beats back to copy-engine, each with its max_words
  → --tts with the real voice: 2 real overflows, the setup fits

The total fit with five seconds to spare. Three beats did not. Your agent hands only those beats back to the writer, with the word count that fits, before anyone records a word.

Two chalk rows of the same width. The top row is one long box whose voiceover wave ends early, labelled TOTAL FITS. The bottom row is cut into three boxes and the wave in the narrow last box spills past its edge in gold, labelled ONE BEAT FAILS.
The total is the wrong number. Your viewer hears a line over one shot, not over the whole video. On six of my own 60-second demo scripts, 11 of 35 spoken beats ran past their shot.
Seven chalk bars labelled EN, FR, ES, DE, RO, RU and HE, each the same 55 seconds of English speech timed in that language, against a dashed gold line labelled SAME VIDEO. EN and FR end before the line; the other five run past it.
Seven languages, measured. The same lines run 6 percent longer in French and 27 percent longer in Hebrew. A script with 55 seconds of English speech no longer fits 60 seconds in five of the seven.

Hand your agent a video you liked, not a blank page new in v0.3.0

video-analyst measures a video: how long each section runs, how fast it cuts, which engine each part needs, what the first three seconds do. Your agent now fills that template into a shot list with no hand edits. On the one real template so far, the 4-minute Intro to Linear, one row per section broke 4 checks. Split by its own pace, it fills 24 rows with 0 structural violations. What is left is the place where a human presenter cuts faster than an avatar can shoot.

> "make it like this template"

  fill-template.mjs template__explainer__presenter-screen__v1
  (n=1, strength single: a hint) · target 240.641s · vo_wpm 168.7 (measured)

  section    engine   template pace   used pace   ratio     level
  hook       avatar       1.6s          5s        3.1250×   FAIL  avatar floor 5s
  promise    avatar       3.8s          5s        1.3158×   WARN
  context    avatar       3.678s        5.517s    1.5000×   WARN
  recap      avatar       3.094s        6.187s    1.9997×   WARN
  (8 screen and motion sections, all within 1.17×)

  HANDED BACK (2)
  ✗ hook 3.1250× (n=1, strength single: a hint)
      → --engine "hook=motion"   no floor, keeps 1.6s shots
      → --accept "hook=<reason>"
  ✗ first_shot_change_by_3s: now at 5s (measured)

  VERDICT: HAND_BACK (2 handed back, 4 warn) · 24 rows

  > fill-template.mjs … --engine "hook=motion"
  VERDICT: WARN (0 handed back, 4 warn) · 24 rows
  ⚠ face_by_3s now at 5.632s (judged)
Two chalk rows on one timeline. A short box labelled PRESENTER 1.6 S ends before a dashed line at 3 S. A box labelled AVATAR 5 S runs past it, the part beyond the line in gold, and a gold arrow labelled HANDED BACK bends back from its end.

The hook is the problem. The original’s first shot lasts 1.6 seconds and an avatar clip cannot be shorter than 5, so it comes back 3.1 times slower and misses the template’s measured first cut by second 3. Move it to motion and the hand-back clears, but a face now first appears at 5.6 seconds. You choose. Every borrowed number prints its sample size: one video is a hint you may decline, 2 to 5 a default, 6 or more a norm you may not. The template’s speaking pace only warns you when a script is too sparse. It never decides whether a line fits. The printout is trimmed: columns cut, and the eight screen and motion sections summarised in one line.

What it will tell you it cannot do

  • It renders nothing and writes no words. It decides, composes and checks the clock. The words come from copy-engine. Generation goes to media-generator, screen capture to a recorder, compositing to the renderer. This produces the one document all three read.
  • No solver for all-generated lengths yet. A template fill scales its sections to your target, but picking clip lengths for an all-AI video is still a written procedure you run. A 45-second target has exactly one solution in that space, and a person will not find it by trial and error.
  • Pacing is graded only against a template, and there is one so far. Give it a video-analyst template and rhythm, tutorials included, is checked at that template’s strength. The one that exists is a single video, Intro to Linear, so everything the fill borrows is a hint (n=1). AI sections and non-English templates are untested, because none exist yet.
  • The speech rates come from one engine. One neural voice per language on edge-tts. Your real timings (--tts) or your measured brand rate beat the table, and the skill says so on every run.
  • It over-flags short-word Russian. A Russian script of short everyday words speaks faster than the table, so the estimate flags lines that fit. The measured check clears them. In my test it still caught the one real overflow.
  • It will not guess the mode. Nothing in a script says whether a row is a shot or a whole post. If you did not say, it asks rather than assumes.
Why this exists

I got tired of renders that succeeded and were still wrong.

video-director is one skill in the system behind Di-Atomic, the marketing and compliance agency that runs cognitoAI, SpiderIQ and OPVS. If you want video produced on a pipeline that checks its own arithmetic, in any of my team’s seven languages and including regulated categories, that is the day job.

Book a 30-min call with Di-Atomic

Just want the skill? Get @di-atomic/video-director free.