Niko McGrathSelected work, 2021–2026
← All work

No. 08 · Videography · 2026

Roughcut

Built for a Japanese-learning YouTube channel I edit. Roughcut finds every read of every scripted line in the raw footage, picks the keepers, and builds the rough cut in DaVinci Resolve. Then the editing starts: the graphics, the sync, and rounds of notes with the creator.

Role
Editor and builder
Stack
Python · Whisper · Resolve
Episodes
Five so far

The channel’s episodes are recorded as long takes: the creator reads the script to camera and reads any line again when it comes out wrong. The first three episodes each arrived as 40 to 85 minutes of footage, with the good read of every line somewhere inside. Finding those reads is the slowest part of the edit, and the most mechanical, because the script already says what belongs there. Roughcut does that part, and stops at a rough cut.

One episode, through the tool

Eight clips, in shooting order

EP003 came in as eight clips from one afternoon, 41 minutes 48 seconds of footage. probe reads each file’s frame rate, length and start timecode, and puts the clips in shooting order.

That order matters more than anything else this stage does. The rule for picking a take is “the last clean one wins”, which only works if the tool knows which clip was recorded later. So the order is written into sources.json as an explicit clip_index. I can edit that file when a pickup lands in the wrong place, and every later stage reads it exactly as written.

Every word, with a time

transcribe runs Whisper over each clip and keeps every word with its start, its end and how sure Whisper was: 3,142 words for this episode.

It’s the only stage that needs the GPU, and it runs once. Everything after it reads the cached transcript, so changing how lines are matched or cut is a re-run of a few seconds, never a re-transcribe. The highlighted half-minute is one line of the script being read again and again.

Every place a line was read

align matches the script against the transcript. Aligning the whole script in one pass would find each line once, usually at its first read, which is the one that went wrong. So the tool first pins the script to the transcript with phrases that only occur once, then runs a local alignment (Smith-Waterman) inside each pinned stretch to find every separate read of every line.

Each read is scored on coverage, accuracy, Whisper’s confidence, stumbles and speaking rate, then sorted into clean, usable or flubbed. This line was read eight times; the four the tool kept are a stop halfway and three clean reads. The last clean read wins.

The channel is a client’s, so the line and its reads in the panel are stand-ins of the same length. The takes, their timings and their scores are the episode’s own.

One path through all of them

Choosing each line’s take on its own goes wrong in two ways: neighbouring lines can claim the same words, and a cut can jump back in time. So the tool chooses every line’s take at once, with a Viterbi pass over the whole script. It penalises cuts that run backwards or overlap, and rewards takes that sit next to each other in one clip, so a paragraph read cleanly in one go stays one clip instead of eight jump cuts.

The last-clean-take rule stays the default. The pass only overrules it to fix the order, and flags every line where it did. Switch the panel between the two: on this episode they differ on 15 lines. Line by line, one cut runs backwards; the whole-script path has none, and fewer cuts.

Cutting in the silence

Whisper’s word timings are inferred, not measured, and they’re often wrong by more than the pause between two words. Its word ends tend to fall inside the word, which clips the last consonant. So align measures the audio instead: one decode per clip gives a loudness curve in 10 ms steps, and each cut snaps to the nearest real silence on the safe side of the word.

In the panel, Whisper ends the line’s last word at −18 dB, while it’s still sounding. The measured cut lands 300 ms later, at −80 dB. Across 193 cuts in one clip of an earlier episode, measured out-points landed at −78.9 dB instead of −45.3, and not one landed inside speech.

What it couldn’t decide

Nothing the tool decides is hidden. proof renders the cut list straight to sound and picture with ffmpeg, so I can listen before Resolve is involved, and it cross-checks the cut list’s seconds against its frames. The report lists every line the tool wasn’t sure of, each with every take it found, so I check its choice instead of redoing it.

For EP003 that was 61 of 147 lines. Most are small: 37 cuts with no silence to land in, and lines whose takes scored too close to call. Two lines were never found in the footage, and 24 stretches of speech matched no line of the script, 3 minutes 29 in all. Each one is listed with a command that plays it.

The rough cut

plan turns the cut list into the exact calls Resolve’s scripting API needs, without calling Resolve itself, so the plan can be read before anything is built. Claude then builds the timeline in Resolve from that plan, following a written procedure.

EP003’s cut list is 157 clips, 18 minutes 48 seconds out of 41:48. In Resolve, the 60 alternate reads went onto their clips as native takes, so switching a read is a click and its sound comes with it. The notes became 69 markers on the clips themselves, so they move when I cut. From there the edit is mine: pacing, graphics, the grade and the sound.

EP003 Source clips 24 fps · config 5bf5d3c3

What the first episodes broke

EP001’s first assembly flashed black at every cut, 135 times. Resolve’s scripting API treats a clip’s end frame as exclusive and the cut list’s was inclusive, so every clip landed one frame short. The gap check had reported every one of them; an earlier pass had waved off one-frame gaps as rounding.

The same assembly cut 33 times in the middle of a phrase. The tool removed any pause over 0.9 seconds, and in someone talking to camera a pause that long is usually a breath, so it was splitting phrases in two. Now the limit depends on where the pause is: 0.9 seconds after the end of a sentence, 2.5 inside one. That took the 33 down to 7, all of them real stalls. Both fixes went into the tool, not the timeline, so they hold for every episode after.

Frame rates are the other trap. Resolve rounds down when it converts source frames to timeline frames, so a 29.97 fps clip in a 23.976 timeline can land a frame short. All of the frame arithmetic now lives in one module and nowhere else, and when every source shares a rate the timeline is built at that rate, which turns the conversion into nothing at all.

EP002 turned up two design errors, and I found both by using the timeline. Alternate reads were stacked on tracks above the cut as picture only: none of the 73 had any sound. My note at the time: “there are multiple video clips, however there is only one audio line, so because of that I can’t actually switch between takes.” Choosing a take is mostly a judgement about sound, so they couldn’t do the one thing they existed for. They now go onto each clip as Resolve’s native takes, and the sound switches with the picture. The notes had the same flaw: timeline markers are pinned to a frame and drift the moment anything is moved, so they became markers on the clips.

The bigger lesson was about checking. EP002’s build passed every check I had: as many clips on V1 as on A1, and the right total length. It was still missing 3.7 seconds off its opening line, and every alternate was silent. A matching count proves very little. Now, after a build, every clip is read back from the saved project and compared with the plan, one by one: its span, its source in-point, its name, its markers.

Cards in layers

The rough cut is the start of the edit. Much of the work after it is what gets laid over it: section titles, diagrams, the prompts on screen. Those cards are drawn in Python from one shared kit of marks, so line weights and colours can’t drift from card to card or episode to episode.

Every card ships as separate alpha passes, never as one flat clip: the paper, the marks, and the type, each on its own track. Effects in Resolve then apply to one layer at a time. A wobble on the marks doesn’t smear the type, and a glow on the type doesn’t bloom the paper.

V2 · paper
V3 · marks
V4 · type
View
Effect
Delivered as
A stand-in card, drawn for this page the way the channel's cards are built: paper, marks and type as three separate alpha passes, stacked in Resolve.

The layers are drawn so that no pixel carries alpha on two of them, and that’s checked. Then the stacking order doesn’t matter, and no effect on one layer can clip its neighbour. Each pass is ProRes 4444 with straight alpha. A flat composite is rendered too, for reference, and it’s built by stacking the exported layers rather than drawing the card again, so it can’t drift from what ships.

The colour rules are set by medium, not by importance. One accent is only ever a drawn line, a rule that wipes on; the other is only ever emphasised type. The first time the line colour was used as a fill, on a numeral a quarter of the frame tall, it ran hot. As a thin stroke that animates on, the same colour reads as energy.

When the footage arrives cut

The fourth and fifth episodes didn’t need Roughcut’s alignment: the creator cut them first and sent a single file. EP004’s was cut by an AI tool, and it had problems of its own that none of the obvious checks showed.

EP004’s file was variable frame rate. It had 23,865 frames over 996.5 seconds, 51 short of 24 fps, because the AI tool left an irregular frame at each of its 58 cuts. Resolve plays frames back to back at 24, so by the end the picture would have drifted about two seconds early. It was conformed to a constant frame rate before import.

Worse was found when the creator re-exported in 4K. Comparing the two files showed the 1080p one had been out of lip sync all along, with a frame count that looked fine: by 16:04 the mouth moves through a second and a half of silence. The 4K file was in sync, but its sound had gaps hidden at the AI’s splices, 1.6 seconds in all. Played back to back the way Resolve plays it, the sound would have run early, so it was conformed by timestamp instead.

How far the picture ran ahead of the sound

Two exports of the same AI cut of EP004, in frames at 24 fps

0
12
24 (1 s)
36
1080p export +41 frames, 1.7 s 4K export, conformed within a frame
0:004:008:0012:0016:00

Source: the sync check written for this episode. The 1080p file had a believable frame count the whole time.

See the numbers
Time in the cut1080p export, picture ahead
0:060.6 frames (0.02 s)
2:046 frames (0.25 s)
8:3422 frames (0.92 s)
16:1741 frames (1.7 s)
Whole cut4K export, conformed: 64 of 67 audio splices within 1 frame of a picture jump

The test that settles it is simple: in a correct export, every audio splice sits on a picture jump. In the conformed 4K file, 64 of the 67 do.

By then the edit had been built on the 1080p file. Carrying that edit across by frame number would have carried the drift with it, so it was carried by sound. Each of the 4K file’s 625 stretches of speech was found in the 1080p audio. The offset between the two files stepped 66 times, always in a pause. All 91 cut points, placeholders and markers landed within half a frame of where they belonged.

Rounds with the creator

Each episode goes through versions, and each version is a new timeline, so the one before is never lost. EP004 went from the creator’s file to its eighth version in eight days:

  • v02: duplicate takes pulled.
  • v03: the 4K re-delivery, with the edit carried across by sound.
  • v04: my first editing pass, gaps closed.
  • v05: graphics and sound effects re-timed to follow the new cut.
  • v06: punch-ins, dialogue crossfades, and a trial music bed.
  • v07: a re-cut, then the creator’s notes on the draft, applied the same day.
  • v08: the prompt cards out, once the creator chose to make those themselves.

EP005 went from the creator’s file to an export in four days. Every decision goes into the episode’s notes file as it’s made, along with what’s still open. That file is the memory between sessions, mine and Claude’s, which is why a note from three weeks earlier can still be acted on.