Work Lakes Area Graphix & Signworx
A render you cannot get wrong quietly
A catalog of product-page videos is a scheduling problem disguised as an editing problem: one shape, sixty-odd pages, and a person who will make the same mistake twice. This builds both the 30-second landscape cut and the vertical social loop from a single JSON file per page, and spends most of its effort refusing to render specs that would come out wrong.
- Role
- Sole author — spec format, validation, render, QC tooling
- Stack
- Python · ffmpeg · vidstab · Pillow · Flow
- Links
- Source on GitHub
Rendering is slow, and almost every failure is silent
A bad cut does not crash. It encodes cleanly and is simply wrong — a caption that outlives the beat it belongs to, an in-point two seconds from the end of a four-second clip, a voiceover line nobody can read in the time allowed. You find those by watching thirty seconds of output, which means you find them after paying for the render.
So the build step refuses to write a spec that would not work. It checks that a beat's shots sum to the beat's own length, that beats leave no gap on the timeline, that captions stay inside their beat, that an in-point plus duration does not run off the end of the clip, and that each voiceover line is readable in the time available.
The selection criterion for those checks is not what seemed worth checking. Every one of them is a mistake this program had already made.
A vertical cut inherits what the landscape cut already proved
The social cuts are not crops of the page video — a 9:16 frame keeps about a third of the width, which slices anything wide. They are separate edits, but they re-cut windows the page video has already vetted: measured for camera shake, matched for brightness, screened for brand marks in frame.
So a social spec is about fifteen lines. A shot reads `"from": "<page>:<beat>:0"` and pulls that page's clip, in-point, brightness correction and stabilisation data verbatim. Only what genuinely differs for a vertical frame gets written down: the pan, and a duration on the music bed's bar grid.
The mean sets the target; the histogram sets the limit
Shots that do not match in brightness flash at the cut, so the tool measures each one and corrects it toward a common level. The obvious implementation makes the picture worse. One shot read well above the target not because the scene was bright but because a white sheet filled half the frame; correcting it by offset took seventeen percent of the frame to near-black and lost the background entirely.
The metric was satisfied and the image was ruined. So the correction is now backed off before it clips, and when the tool holds several shots back and a visible step survives, that is information: the shots genuinely do not match, and the fix is a different target or a different shot rather than a bigger correction.
Levelling also has to come after the pans are chosen, not before — a pan changes which part of the frame is in shot and therefore how bright it measures.
Every measurement is keyed to the frame it was taken on
Cropping to vertical magnifies camera shake by the crop factor. A shot that measures steady across the full frame can be unusable once cropped, so shake is re-checked after the pans are settled rather than before.
Stabilisation has the same problem in a form that fails silently. A transform file holds its corrections in pixels, so one measured on a half-size proxy describes shifts half the size a full-resolution frame needs — and the filter applies that half-correction without complaint. The vertical pass re-measures on the source it will actually read.
What it moved
- Reusable across every page in the catalog
- 21 of 30s
- Tools, from footage survey to QC
- 15
- Hand-authored per page — the rest is generated
- 1 file