Editing real footage by transcript
Read this when the user hands you real video (a talking head, an interview, a screen recording
with narration, a pile of takes) and wants it cut, tightened, captioned, reframed for vertical,
or turned into a short. It covers the workflow, the EDL format, the render and the rules that keep
an edit correct. An EDL (edit decision list) is a JSON file, <job>/edit/edl.json, that lists which stretches of
the recordings to keep, in order; showtime renders from it, so the original footage is never changed. Caption
styles and numbers live in captions.md; the individual tools (scenes,
reframe, denoise, stabilize, grade, looks, timeline views) are in footage-tools.md. For people: see it step by
step, one real run with a picture of each step.
Everything runs locally: speech recognition, speaker labels, audio events, face tracking, grading. You cannot watch or listen to the result, so every step below ends with something you can read (JSON, a packed transcript, a PNG) instead.
Essentials#
- Order:
showtime footage probe <file>,showtime transcribe raw/ --edit-dir <job>/edit,showtime pack <job>(read all oftakes_packed.md), a 3-6 line plan,showtime edit cut ...,showtime edit check edl.json(§1) - Then
showtime edit render edl.json --previewandshowtime edit view edl.json; finalshowtime edit render edl.json(a workflow's-o <job>/final.mp4wins),showtime deliver exportsif needed (§1) - Ask at most 1-2 questions; the user confirms the plan only when it drops content (takes, sentences, order); tell them the transcription time up front for anything long (§1)
- Transcripts: Parakeet (
auto) covers 25 European languages, others need--language xx; never pick--model crisperfor the user;--speakers N,--from/--tofor a window (§2) - Fix spelling in
textonly; never movestart/endby hand (§2) - Never cut inside a word: keep 30-200 ms of padding (defaults 50 ms before, 80 ms after); keep ~0.3 s of breath where material was removed (0.2 s at a filler) (§5)
- Keep the last clean take of a repeated sentence; never splice half of two takes (§5)
- Never compute output offsets yourself; read them from
edit checkor the render report (§5) - Loudness is mastered once: -14 LUFS / -1 dBTP by default; another level only when asked (
--lufs N,--keep-loudness,"loudness": false) (§5) - Outputs are never overwritten without
--overwrite: use the printed path (name-2.mp4); everything lives in<job>/edit/, never beside the user's footage (§5) edit cut: fillers go by default (--keep-fillers); "mm-hmm" is a word; "you know", "este" go only with--filler-set en-discourse/es-discourse;--remove w40-w52drops a retake (§4)output.fitauto: same aspectcover, a taller source into a wider frameblur, wider into tallerreframe(face-tracked crop) (§4)- Leave jump cuts in a talking head; no punch-in on every other range (one scale 1.06-1.12 per section, with a reason) (§6)
- After every render: report
frames_ok: true,warningsempty, loudness within 1 LU,captions.timingall zeros; read everyedit viewPNG; say what you could not check (you did not listen) (§6) - Published work:
showtime transcribe final.mp4 --edit-dir edit/qato confirm no fillers or clipped words; stop after 3 fix-and-render passes and ask (§6) - Copy range times from
takes_packed.mdoredit cut, never from memory (§8) - Cards (title, lower third, pull-quote, data callout, chapter, list, side panel, a big word behind the speaker)
go in the EDL's
cards, anchored to a phrase (say) or a word id, never to seconds;showtime edit cards suggest <edl>lists moments (§9) behindcuts the speaker out over the word (MODNet on the CPU);showtime footage cutout <clip>writes the speaker alone with alpha for another editor (§9)- Cards and captions stay off the face (9:16 cards with no room become splits);
edit checklists each card's times and every problem; captionemphasistakes the 3-5 terms that carry the message (§9) - A long recording into short clips:
showtime edit momentsranks whole-sentence moments (suggestions: read and pick inmoments.json),showtime edit clipsmakes one EDL, render and qa per pick, in parallel, and a sheet (§10)
| Section | Lines |
|---|---|
| 1. The workflow | 70-87 |
| 2. Transcripts | 89-139 |
| 3. Reading the material | 141-146 |
| 4. The EDL | 148-202 |
| 5. Hard rules (correctness) | 204-239 |
| 6. Self-evaluation (you cannot watch it) | 241-261 |
| 7. Recipes | 263-275 |
| 8. Red flags | 277-286 |
| 9. Cards: graphics anchored to the words | 288-382 |
| 10. Highlights: a long recording's best moments as clips | 384-435 |
1. The workflow#
| Step | Command | Done when |
|---|---|---|
| 1. Inventory | showtime footage probe <file> per file, showtime footage scenes <file> --every 5 for a look (written to the job's work/scenes/, never beside the footage) |
you know durations, orientation, fps, HDR, audio tracks, what is on screen |
| 2. Transcribe | showtime transcribe raw/ --edit-dir <job>/edit (folder or files) |
every take has <job>/edit/transcripts/<name>.json |
| 3. Pack | showtime pack <job> |
you have read <job>/edit/takes_packed.md end to end |
| 4. Converse | ask at most 1-2 questions (length, platform, what must stay), only when the request leaves them open | goal, target length and aspect are clear |
| 5. Strategy | state the plan in 3-6 lines: keep/cut logic, order, aspect, captions, music, look | stated as an assumption; confirmed by the user only when it drops content (takes, sentences, order) |
| 6. EDL | showtime edit cut ... then edit the JSON by hand as needed; showtime edit check edl.json (or edit check <job>: its latest EDL) |
edit check passes and the plan reads right |
| 7. Preview | showtime edit render edl.json --preview (a second run writes preview-2.mp4 and prints it; --overwrite reuses the name) |
the render report has frames_ok: true and no warnings |
| 8. Self-eval | showtime edit view edl.json (the newest render of that EDL; it prints which) + read the PNGs; loudness numbers from the report |
every cut looks and reads clean (see section 6) |
| 9. Iterate | edit the EDL, render the preview again (unchanged segments are reused) | at most 3 passes, then ask |
| 10. Final | showtime edit render edl.json (default beside the EDL; a workflow's -o <job>/final.mp4 wins) |
final.mp4 + final.report.json + final.srt, then showtime deliver exports if needed |
Tell the user the time cost up front for anything long: transcription with the default Parakeet model runs at roughly 0.1-0.2 x the audio length on a 6-core laptop (0.3-0.5 x with Whisper turbo; much less on Apple Silicon). The first transcription fetches the model once (~490 MB, announced).
2. Transcripts#
showtime transcribe writes one word-level, verbatim transcript per file (and per audio track):
{"source": "/abs/take1.mp4", "duration": 42.1, "language": "en", "language_source": "guessed",
"model": "sherpa-onnx-nemo-parakeet-tdt-0.6b-v3-int8",
"words": [{"id": "w0", "text": "So,", "start": 0.52, "end": 0.81, "type": "word", "speaker": "S0", "conf": 0.93},
{"text": " ", "start": 0.81, "end": 1.2, "type": "spacing"},
{"id": "w1", "text": "um,", "start": 1.2, "end": 1.5, "type": "word", "speaker": "S0", "conf": 0.8},
{"id": "w9", "text": "(laughter)", "start": 5.1, "end": 6.0, "type": "audio_event"}],
"guards": {"dropped": [], "warnings": []}}
- Model choice.
autouses Parakeet-TDT 0.6B v3: verbatim (it writes "um"/"uh" as words), 25 European languages including English and Spanish, fetched on first use. For other languages pass--language xx: auto then uses Whisper (turbo when installed, else small).--model parakeet-v2is the English-only Parakeet;--model turbo/smallpick Whisper for anyone who wants it.--model crisperis the opt-in CrisperWhisper 2.0 "max accuracy" model: its weights are for non-commercial use only (it asks for--accept-licenseonce), it needs PyTorch and is not available on Intel Macs. Never pick it for the user. - Language.
language_sourcesays wherelanguagecame from:given(--language),model(an English-only model),detected(Whisper heard it;language_probabilityis its confidence),guessed(Parakeet v3, from common words) ordefault(nothing to go on, soen). Onguessedordefaultwith speech that is not English, transcribe again with--language xx. - Fillers are kept on purpose; they are edit points. After ASR a gap scan looks at voiced
stretches no word covers (150-800 ms) and at words far longer than their spelling (an "uh" folded
into them), decodes each again on its own, and adds the fillers found as words with
"filler": true, "detected": "gap-scan". A real word found that way is never marked (the transcript lists it underfiller_scan).--no-gap-scanturns it off. - Speech under music. For a video showtime rendered itself (a voiced motion render, or an edit
with a music bed), transcribe reads the dry narration stem the render kept, not the mix, and says
so (
audio_from;--no-stemfor the mix). For other footage it measures the background: when music sits within ~8 dB of the speech it first separates the voice (UVR MDX-Net, 67 MB on first use; credit UVR) and transcribes that (stats.separation);--separate on|offforces it. - Word edges are snapped to the audio energy (typically 200-300 ms raw error -> ~10-80 ms).
- Guards against invented text: silent tracks are refused (
--audio-track Nfor OBS-style multi-track files), words with no speech energy nearby, words after the audible end and repetition loops are dropped and listed inguards.dropped. Readguards.warnings. - Speakers:
--speakers 2(orauto) labels words S0, S1... Pass the real count when known. It can miss short interjections ("Yeah.") or label a long window as one voice; when a published transcript exists, align it (showtime voice align <audio> -f transcript.txt) and take each turn's speaker from its labels instead (captions.md, section 6). - Names and jargon:
--prompt "showtime, Kokoro, ffmpeg"biases Whisper toward them. - Results are cached by content: re-running is instant unless the media changed (
--forceto redo). - Part of a long file:
--from 12:30 --to 18:00(seconds or mm:ss) transcribes only that stretch. Word times stay on the file's own clock (offset by--from), the transcript gets"range": [750, 1080],durationis the range's end, and it is written as<name>.750-1080.jsonbeside any full transcript (cached per range). Cuts planned from it drop everything outside the range. Use it to find a moment in a long recording fast; transcribe the whole file when the edit spans it. - Correcting a transcript is allowed (fix spelling in
text), never movestart/endby hand.
3. Reading the material#
takes_packed.md shows every phrase as [start-end wFirst-wLast] SPEAKER text, breaking at pauses
of 0.5 s or more. Read all of it before proposing an edit. Look for: the strongest opening line
(hook), false starts and retakes (keep the last clean take of a sentence), the payoff line, dead
air, laughter/applause events worth keeping.
4. The EDL#
{"sources": {"a": "../raw/take1.mp4", "b": {"file": "../raw/obs.mkv", "audio_track": 1}},
"ranges": [{"source": "a", "start": 2.40, "end": 7.95, "note": "hook"},
{"source": "b", "start": 31.10, "end": 38.42, "zoom": 1.12},
{"source": "a", "start": 9.10, "end": 15.30, "grade": "punch"}],
"output": {"aspect": "9:16", "fps": 30, "fit": "auto"},
"grade": {"auto": true, "lut": "teal-orange", "strength": 0.5},
"captions": {"style": "bold-pop"},
"overlays": [{"file": "../assets/logo.png", "start": 0.5, "duration": 3, "position": "top-right", "width": "18%", "fade": 0.3},
{"file": "../broll/city.mp4", "start": 12.0, "duration": 2.5, "position": "full", "offset": 4.0}],
"audio": {"music": {"file": "../music/bed.wav", "gain_db": -4}, "denoise": "auto"},
"loudness": {"lufs": -14, "tp": -1}}
Paths are relative to the EDL file. Times are seconds ("1:02.5" also works).
| Field | Meaning | Default |
|---|---|---|
sources |
name -> file (or {file, audio_track}) |
required |
ranges[] |
source, start, end in source seconds, played in order |
required |
ranges[].fit / zoom / focus |
per-range framing: fit mode, punch-in 1.0-3.0, fixed centre {"x","y"} 0..1 |
output fit, 1.0, face track |
ranges[].grade / stabilize / volume_db / mute / note |
per-range overrides | global / off / 0 / false |
ranges[].hold |
freeze the range's last frame this many seconds (0-10), the sound fading out: an ending with air | 0 |
ranges[].fade_out |
fade the range's sound out over its last seconds (0-5, a quadratic curve): a clip that ends on applause | 30 ms edge fade |
output.aspect |
16:9 9:16 1:1 4:5 4:3 21:9 720p 1080p 4k 4k-vertical or width/height |
first source's size (max 4K) |
output.fps |
output rate; every source is normalised to it | first source, snapped to a standard rate |
output.fit |
cover, contain, blur (whole frame on a blurred copy), reframe (face-tracked crop), auto |
auto |
grade |
none, auto, preset, look, or {auto, preset, lut, strength, filter} |
none |
captions |
style name or {style, font, highlight, color, position, max_words, fillers, srt, emphasis} (emphasis: words or phrases coloured in the look's accent, §9) |
none |
subtitles |
a ready .ass/.srt/.vtt to burn instead of generated captions |
none |
overlays[] |
file (png/jpg/mov/webm/mp4), start (output time), duration, offset (in the overlay), position (full, center, top-left ... bottom-right), x/y/width/height (px or "10%"), scale, opacity, fade, fit, audio, volume_db, duck_db |
centred, 40 % wide, silent |
audio.music |
a file (or {file, gain_db, fade_in, fade_out, loop}): looped, faded, ducked under speech |
none |
audio.tracks[] |
any audio/mix.json track (music, sfx, synth, library id), times on the output timeline |
none |
audio.denoise |
auto, deepfilter, rnnoise, afftdn |
off |
loudness |
{lufs, tp}, a number, or false / "source" (keep the source level) |
-14 LUFS / -1 dBTP |
cards[] |
designed cards anchored to the words: type, say or word, timing and content (§9) |
none |
look |
a look signature id (showtime signature) for the cards and the caption emphasis |
the brand kit, else one picked once for the EDL |
A formula or diagram over footage: render it with showtime manim render <scene.py> --alpha -o <job>/edit/eq.webm (VP9 with alpha) and add it as an overlays[] entry with "position": "full"; the alpha channel is kept (references/manim.md, integration).
auto fit: same aspect -> cover; a taller source into a wider frame (phone clip in 16:9) ->
blur; a wider source into a taller frame -> reframe (face tracking, centre when no face).
showtime edit cut writes a correct EDL from transcripts: --max-pause 0.5 shortens long pauses,
fillers go by default (--keep-fillers; words the gap scan flagged go too; the pause left where a
filler was is capped at --filler-pause, 0.2 s; every cut edge moves to the quietest point within
40 ms, --no-snap to keep them; --strict-fillers cuts only fillers a second, isolated decode heard
again: fewer false cuts, some fillers stay). A listener's "mm-hmm" / "uh-huh" is a word (it means yes),
never a filler. Spanish "este", "o sea" and English "you know", "like" are real words
elsewhere, so they go only when asked: --filler-set es-discourse / en-discourse, or --filler "o sea". --remove w40-w52 drops a retake, --remove-time,
--keep-time, --aspect, --captions, --grade, --music, --denoise. It also stores a
cut_summary (what was removed and why) for you to review. Several transcripts play in order.
5. Hard rules (correctness)#
- Never cut inside a word. Range edges come from word boundaries plus padding: keep 30-200 ms (defaults: 50 ms before a word, 80 ms after; plosive endings need 60-80 ms).
- Pad removals generously. Fillers have soft onsets; the cut reaches 40 ms past them.
- Leave breath. Where material was removed keep ~0.3 s of pause (0.2 s where a filler was); long pauses shrink to that.
- Keep the last clean take of a repeated sentence, never splice half of two takes.
- Frame-exact offsets. Each range becomes
round(duration x fps)frames; the output time of every segment is the running sum of frames actually written. Captions, overlays and music use those offsets, so there is no drift however many cuts there are. Do not compute offsets yourself; read them fromedit checkor the render report. - 20 ms equal-power audio crossfades at every cut (automatic;
audio.crossfadein the EDL, 0-0.05 s, 0 = the older 30 ms fade-out/fade-in); the first and last edges fade 30 ms. Segments keep PCM audio until the final encode, so no codec gap appears at cuts. A range that starts exactly where the previous one ended in the same source (a reframe-only split: same take, newzoom/focus) joins with no fade, so the sound stays continuous; set such splits to frame-aligned times (start + frames / fps):edit checkreports two ranges of one source that overlap or miss by less than a frame and prints the exact start to use. With face tracking on (fitauto resolves toreframe), a range'sfocusis only the fallback; for a fixed crop use"fit": "cover"plusfocuson the range. The tracker starts where the face settles (the median of the first second) and its dead zone shrinks withzoom, so a punch-in stays centred. - Captions and subtitles are burned last, over overlays.
- Loudness is mastered once, on the final program: -14 LUFS / -1 dBTP by default, the same
target as every other showtime delivery, whatever the source level was (a -16 LUFS recording
comes out at -14). Another level only when asked:
edit render --lufs Nor"loudness": N; to leave the source level alone,edit cut --keep-loudness/edit render --keep-loudnessor"loudness": false(the report saysloudness_target: sourceand qa notes it instead of failing it). The renderer masters 0.5 dB under the ceiling to leave room for AAC. - One output frame rate; mixed sources are converted. HDR (PQ/HLG) is tone-mapped to SDR, phone rotation is honoured, sources without audio get silence.
- Outputs are never overwritten unless
--overwrite; the next freename-2.mp4(oredl-2.jsonforedit cut) is used and printed. Use the printed path, or a job argument, from then on. - Everything the session makes lives in an
edit/folder inside a job:<job>/edit/(transcribemakes a<name>-editjob when there is none). Never next to the user's footage unless they say so (--edit-dir), never in the skill.
6. Self-evaluation (you cannot watch it)#
After every render:
- Read
<out>.report.json:frames_okmust be true,warningsempty,loudnesswithin 1 LU of the target,true_peak_dbtpat or under the ceiling. showtime edit view edl.jsonand read every PNG. Each cut shows the filmstrip, the waveform, the words and the pauses around it. Look for: a word clipped at a cut (waveform cut mid-shape, word label missing), a double word across a join, dead air over 0.6 s. Jump cuts in a tightened talking head are left as they are by default: they read as a clean edit, while a punch-in that goes back out at the next cut reads as a bouncing zoom (edit checkandedit renderflag alternating scales). Usezoomonly when asked or for a reason in the content: one scale held for a whole sentence or section (1.06-1.12, e.g. a tighter frame for the key answer), a single push for emphasis, or a vertical reframe; never a different scale on every other range.- For captions, check the render report's
captions.timing(all zeros is correct) and a frame or two (showtime footage view final.mp4 --from 3 --to 6). - For anything published, transcribe the output (
showtime transcribe final.mp4 --edit-dir edit/qa) and confirm no fillers or clipped words remain. - Say what you checked and what you could not (you did not listen to it).
Stop after 3 fix-and-render passes and ask the user.
7. Recipes#
- Tighten a talking head:
edit cut t.json --max-pause 0.5-> preview -> view. - Vertical short from a landscape interview:
edit cut t.json --aspect 9:16 --captions bold-pop --remove w0-w25(drop the warm-up); the face-tracked reframe already frames it, so no alternating punch-ins. - Best-of from several takes: transcribe all, pack, write
rangesby hand from the packed lines (one source key per take),edit check, preview. - Podcast clip with speakers:
transcribe --speakers 2, choose ranges by speaker lines, captionsclean(loudness stays -14 unless asked). For a long episode, transcribe only a window around the part you want (transcribe ep.mp3 --from 21:30 --to 24:00; times stay on the episode's clock). - Same edit, many formats: render once per aspect with
--aspect/-o, or render the 16:9 master and useshowtime deliver exports.
8. Red flags#
| Tempting shortcut | Do this instead |
|---|---|
| Writing ranges from memory of the transcript | Copy times from takes_packed.md or use edit cut |
| Cutting exactly at a word's start/end time | Keep the padding; let edit cut compute edges |
| Declaring the edit done after the render exits 0 | Read the report and the cut views first |
| Re-transcribing to "check" a cached transcript | The cache is keyed by content; it is already current |
Using .en Whisper models on non-English audio |
--language xx (switches to a multilingual model) |
| Hard-coding caption offsets or overlay times from range sums | Use output times from edit check |
9. Cards: graphics anchored to the words#
A talking head, a podcast clip, a lecture or an interview looks produced when designed cards appear as the words are said. They live in the EDL, so a re-cut moves them with the words:
"look": "tidewater",
"captions": {"style": "clean", "emphasis": ["space weather", "twenty two thousand miles"]},
"cards": [
{"type": "lower-third", "say": "directly affected by the sun", "name": "Sarah Jones", "role": "Mission Scientist"},
{"type": "list", "say": "it directly affects", "title": "Space weather affects",
"items": [{"text": "Satellites", "say": "safety of our satellites"}, {"text": "GPS navigation", "say": "GPS navigation"}]},
{"type": "stat", "say": "twenty two thousand miles", "value": 22000, "suffix": " miles", "label": "above Earth"},
{"type": "panel", "say": "a whole half of the Earth", "title": "Half of Earth in one view", "until": "play out below"},
{"type": "quote", "say": "the most comprehensive view we've ever had"}
]
| Type | Shows | Needs |
|---|---|---|
title |
kicker + headline on a plate | title (kicker, text) |
lower-third |
name and role (the lower-third component) | name (role, variant) |
quote |
the line as said, word by word on its spoken times; a cut into a sentence gets an ellipsis | (text replaces the words) |
stat |
a number counting up, its label, a source line | value (or a number in say), prefix, suffix, label, source_note |
chapter |
a full-frame interstitial on a scrim | title (kicker) |
list |
items that appear as each is said | items [{text, say}] (title) |
panel |
the speaker moves to one half (face-tracked), the panel fills the other: title, body, items, a value |
title |
behind |
a big word behind the speaker: the plate, the word, then the speaker cut out on top | (text, else the words said; kicker, background, color) |
- When.
sayis a phrase as spoken (case, punctuation,%and number words do not matter: "twenty two thousand" matches "22,000", "two point five" 2.5, "nineteen ninety five" 1995); it takes the first match after the previous card's anchor and may span a cut; a card on the same words as the one before shares its anchor only when those words are not said again later (else anchor it withword). A stat's figure comes from its words only when they hold exactly one number; otherwise the card givesvalue.word("w57", withsourcefor several takes) anchors to a transcript word. A card appearslead(0.12 s) before its first word and staysholdseconds after its last (per type, 1.8-4 s), until a later phrase (until), ordurseconds. Times snap to frames. A phrase that is not in the edit is an error that says why: never said, cut out (with its source time), or said only before the previous card. - Where. 16:9: title top, lower third bottom-left above the captions, quote/stat/list in the half away from
the face (YuNet;
sideoverrides), chapter centred. 9:16: cards sit in the tallest stretch the face and the captions leave free inside the platform's safe box (under the chin); a card that does not fit there becomes a split (the speaker moves to the lower 45 %, the card fills the top, as for a panel);"layout": "overlay"keeps it on the full frame (thenedit checkreports the missing room),"split"asks for one. A card is never up while a split moves the speaker (check). Abox({x, y, w, h}frame fractions) places one by hand. A list on a plate grows as each item is said. A chapter in 9:16 is a split too (no scrim over the face). Splits or panels under 1.5 s apart keep the split between them, and a card's hold ends on the next cut once it has had its time. A card that would leave in the last second stays to the last frame (with a rangehold, it rests there). - Captions never cover the face. With cards (or
"captions": {"avoid_face": true}), the face is tracked in windows of about 3 s and where the caption band would cover it (eyes to chin) the captions move just below the chin, else just above the eyes; with no room either way,edit checkand qa (caption_face) say so."avoid_face": falseturns it off. A caption that runs across a split's edge (or a move) is cut there, each piece in its own place (qa reads the pieces as one caption). - Panel. The render splits the ranges at the panel's first and last frame (reframe-only joins: continuous sound, no new cuts) and frames the speaker into their part of the frame. Captions under a panel centre on the speaker's half (16:9) or sit in the panel just above the seam (9:16), never over the speaker.
- Behind.
{"type": "behind", "say": "faster than ever before", "text": "Faster"}: the word in the look's display face, as big as the frame allows, behind the speaker. 16:9: a speaker off-centre gets it on the free side with its last letter half behind the head ("side"picks a side, orcenter), its foot on the chin line so the shoulders never cover it; 9:16 and square: across the top with the head over its lower part, and when a close-up leaves no room above the head the speaker moves down for the card (a reframe-only split, like a panel; captions follow under the chin;"layout": "overlay"keeps the full frame).background:footage(the shot, default),dim,blur(a background blur),ground(the look's ground: a background swap), a colour ("#0b1d3a") or an image file; a moved speaker gets the ground (there is no shot above them).color:auto(the look's accent when it reads),accent,accent-2,fg,whiteor#rrggbb. One word or two: a newline intextmakes two lines. How it renders: the render cuts the speaker out of its own frames (a person matte per frame: MODNet, Apache-2.0, 26 MB, fetched on first use; CPU only, about 25 fps at 1080p on 64 cores, 6.7 on 6 cores; smoothed over time and reset at every cut, refined at full size, cached) and composites the plate, the word, then the speaker, under every other card and the captions. The report'scards.behindhas, per card, how much of the word the speaker hides (hidden, the widest hidden stretchhidden_run) and the matte'sflicker;edit checkestimates the share from the face before a render and prints the last render's numbers; qa warns (behind_hiddenover 45 % hidden or a hidden stretch over 40 % of the word,matte_flickerover 2 % of the speaker's area jumping on a still picture).edit cards suggestoffers the most stressed single word as a behind card. - Cut-out alone.
showtime footage cutout talk.mp4 [--from 12 --to 18]writes<name>.cutout.webm(VP9 with alpha: browsers, EDL overlays,<video>layers;--format proresa ProRes 4444.movfor an editor,pnga numbered PNG folder),<name>.matte.mp4(the matte alone, white = person: a luma matte anywhere) and<name>.cutout-sheet.jpgto look at (most players show a VP9 cut-out without its alpha). It cuts out people, not objects; the report gives the speed and the flicker.--size 384is about twice as fast and softer. - Look. The EDL's
look, else the job's brand kit, else a look signature picked once (kept inwork/<edl>/cards/look.json). The caption emphasis uses its accent when it reads on footage. - How it renders. Every card goes into one page (cards back to back) rendered once with alpha (QuickTime
Animation) at the render's size, cached by its content, then composited as overlays under the captions (a
behind card's layers first, so the other cards sit on the speaker). The render report has a
cardsblock (times, boxes, problems) and qa repeats its problems (card_problem). - Checks.
edit checkprints each card's output times and lists: reading time (0.5 s + characters / 13; a quote read along as said: characters / 20 + 0.5 s), cards sharing the screen and the place, a card on the caption band or out of the 9:16 safe box, a card taller than its room, a card up during a 9:16 split, captions with no room off the face, a list item said after its card leaves, a stat whose counted figure is up under 1.5 s, over 12 s (a panel 30 s), and caption emphasis said more than once per 6 s or with more than 5 terms.edit viewwrites<video>-cards-N.png, one band per card with its in and out marked. - Suggestions.
showtime edit cards suggest <edl | transcript>lists numbers with units, names after "my name is"/"I'm", list markers and "X, Y and Z" enumerations, quotable lines, topic shifts and stressed words (louder and longer than their sentence), each with paste-ready card JSON. Pick the few that carry the story; every on-screen fact comes from the speaker's words or the source.
10. Highlights: a long recording's best moments as clips#
A talk, panel, podcast, interview or stream becomes 3-10 short clips in two commands. showtime finds candidates
and makes the clips; you judge which moments stand alone (workflows/footage-edit.md, Highlights).
showtime edit moments <transcript(s) | job> [--count 8 --min 20 --max 60] prints a table and writes
<edit dir>/moments.json (moments-2.json when it exists). A candidate is a run of whole sentences of one
source whose clip would last --min..--max s once fillers and pauses over 0.5 s are trimmed; it starts where the
sentence before ended cleanly (end punctuation, or a pause or a new speaker without a trailing comma or "and"),
not on a reply ("Yeah.", "Thank you.") or a word in lower case after a pause; it never holds a 3 s pause or ends
on a lone "So". Speaker changes count only after a 0.3 s pause, and a label held for under 4 words is taken as
diarization noise. Each candidate gets these signals (0-1; the score is their weighted mean, leaving out what
could not be measured, which the table names):
| Signal | What counts | Weight |
|---|---|---|
hook |
the first 3 s (the rest of the first sentence at half): a question, a number, a strong claim, a contrast, a story opener ("I remember"), emotion, direct address | 0.20 |
complete |
a clean start (not "And", "Because", "That's why", "It's also") and end (a full stop, not a question, a pause or a new speaker after); a moment that switches speaker must end with the answer | 0.18 |
events |
laughter, applause or cheering from the transcript's audio events inside or right after the last word (before anyone speaks again); music under it counts against | 0.16 |
energy |
against the speaker's own median: level, level spread, pitch spread (autocorrelation pitch, 70-400 Hz) and pace, as percentiles over all candidates | 0.14 |
lines |
the best quotable line (claims, contrast, emotion, a number), short punchy sentences, a 3-word phrase said twice | 0.10 |
topic |
inside one topic segment (TextTiling over content words, no model), focused on a few of them | 0.10 |
flow |
no pause over 1.2 s, few fillers | 0.08 |
length |
near the middle of --min..--max |
0.04 |
Introductions, thanks, logistics and sponsor reads ("please join me in welcoming", "QR code", "use code") score
x0.7 and say so. The best non-overlapping candidates win (at least 3 s apart). Each moment has id, rank,
score, source, transcript, start/end (the first word's start and the last word's end, source seconds),
span, duration (the clip's estimated length), words (first and last id), title (the most quotable phrase,
the speaker's own words), opening, closing, keywords, signals, why, speakers (share of words),
events, topic (its segment; the file lists every segment with keywords under sources), fillers,
housekeeping and the full text. You edit the file: "pick": true, title, start/end (any time: the
edges snap to whole words) and "remove": ["w12-w18"] for a stretch to cut inside.
showtime edit clips [job] [--moments FILE] [--pick m1,m4 | --count 3] [--aspect 9:16] [--preview] makes the
picks (--pick, else "pick": true, else the best --count). Per moment it writes
<job>/edit/clips/<NN>-<title>.json: edit cut's cut (fillers out, pauses over --max-pause 0.5 s down to 0.3 s,
edges at the quietest 10 ms), a start on the first real word (a filler or a "Yeah," / "Well," lead-in goes),
0.15 s of breath before and 0.35 s after that never reach within 40 ms of a word outside the moment; a laugh or
applause that follows the last word stays in for up to 2.5 s (a trailing "So" said into it is cut) and fades out
(fade_out). The output is the aspect's size, smaller when the source would be enlarged more than 1.78x (a 9:16
crop of 1080p footage is 1.78x: accepted with allow_upscale, qa notes it; 720p renders 720x1280). Captions:
bold-pop at 0.09 of the width in tall frames, kept off the face (avoid_face; 0.08 when only that keeps the line
under the chin throughout, instead of a jump above the eyes), clean in wide ones (--captions).
--cards adds a title card on the first words with the moment's title, and a data callout when the speaker says a
number with a unit (edit cards suggest on the clip). The clips render with the EDL renderer, several at once
(cores / 4, at most the clips), each through qa (--platform, else the job's); they go to <job>/clips/ (drafts:
clips/preview/) with clips.json (moment, source range, EDL, video, length, qa verdict, LUFS, true peak and
findings per clip) and sheet.jpg (five frames per clip, qa's colour on the border). Re-running updates an EDL in
place when nobody edited it since it was written (its render cache stays valid); one edited by hand is kept and
the new EDL goes beside it. Videos never overwrite (--overwrite to replace them). In the job ledger a clip is
never the job's final: the batch is one history line and one verified line per clip with its qa verdict.
View or edit skills/showtime/references/editing.md on GitHub