Shorts QA skill
The quality gate for edited talking-head shorts.
by timscheuerai·MIT license·★ 37 Stars on the repo·GitHub ↗
npx degit timscheuerai/content-vault/skills/shorts-qa#main ~/.claude/skills/shorts-qaChecked ·commit main
Inside this skill
SKILL.md · the author's own words# shorts-qa ## Align before you measure The SSIM check answers exactly one question: **did the encode soften the image.** It must therefore be read at the *best* alignment, because `src_t -> out_t` comes from EDL floats and can slip by a frame — and on a talking head **one frame of head movement costs 0.005-0.009 SSIM**, which straddles the 0.995 threshold precisely. It failed two perfectly good clips for *moving*: 0.9897 at the assumed offset, **0.9979 one frame over**. `check_video` now takes the max mean over ±2 frames and prints the alignment. Timing is a different question, and `verify_cuts` already owns it. Same check, second bug: it scored `vals[-1]`, the **last per-frame line** of 60, not the window mean. A gate whose number is a coin toss on one frame is not a gate.
Word-for-word excerpt, not a result. Read the full SKILL.md ↓
Files of Shorts QA
Show the full text101 lines
shorts-qa
Align before you measure
The SSIM check answers exactly one question: did the encode soften the image. It must
therefore be read at the best alignment, because src_t -> out_t comes from EDL floats
and can slip by a frame — and on a talking head one frame of head movement costs
0.005-0.009 SSIM, which straddles the 0.995 threshold precisely.
It failed two perfectly good clips for moving: 0.9897 at the assumed offset, 0.9979 one
frame over. check_video now takes the max mean over ±2 frames and prints the alignment.
Timing is a different question, and verify_cuts already owns it.
Same check, second bug: it scored vals[-1], the last per-frame line of 60, not the
window mean. A gate whose number is a coin toss on one frame is not a gate.
Third: measure between the burns. A film burn is a deliberate full-frame warm flash.
Five flashed frames out of sixty drag the mean to 0.984, and the gate then shouts SOFTENED
at the one effect we added on purpose. check_video now rejects any window containing a
burn.
The verifier must be safe to run concurrently
SC was one shared /tmp/shorts_qa, so two qa.py processes overwrote each other's
ref.yuv / out.yuv and the gate compared frames from a different clip — reporting
SSIM 0.9514 on a clip that actually measures 0.9976. It is now per-PID.
Three of the four "failures" in that batch were the harness, not the footage. A verifier that is unsafe under parallelism will eventually lie, and it lies in the direction of failing good work — which is the direction that gets gates switched off.
Nothing is done until this passes. Not "looks good" — passes.
export SHORTS_PROJECT="/path/to/project"
S=~/.claude/skills/content-vault/skills/shorts-edit/scripts # wherever you cloned it
python $S/qa.py # every clip
python $S/qa.py "<clip>" # one
Exit code 1 on any failure.
Why this exists
Every bug in this pipeline's history was invisible to eyeballs and obvious to a measurement. Not one was caught by watching the video.
| Check | The defect it exists to catch |
|---|---|
| cuts | A cut through a voiced "um". Inaudible frame-by-frame; a chewed syllable in motion. |
| captions | "THING" on screen where "THE" belonged. Every eyeball check happened to land on long words and looked perfect; "THE" is 3 frames long. |
| motion | A tier grade revealed 5.7s before it was spoken — the punchline, spoiled. Nothing flagged it; every frame was individually correct. |
| video | A second encode softening the image. SSIM 0.977 vs 0.998. Invisible on a phone, real on a 246 kbps source. |
| audio | loudnorm silently abandoning linear mode and pumping. And a mono SFX bed downmixing the stereo voice into +0.83 dBFS clipping. |
| decode | Corrupt output that still plays in QuickTime. |
| retention | 91% of a clip sitting in blocks where nothing changes for >5s. Passed every other check. |
The seven checks
- cuts — no cut edge lands on live speech. The intersection of two tests: it must land inside a word (per the transcript) AND be voiced (per the audio). Either alone is useless — the word grid gave 25 false alarms, and "voiced at the edge" flags every deliberate filler deletion.
- captions — pixel-matches each rendered frame against the word bitmap we drew, scored against the expected word and its neighbours, sampling biased toward the shortest words. Reads the schedule the renderer wrote.
- motion — every graphic fires within 0.2s of its spoken cue; no typo'd cue silently dropping a graphic; no overlapping panels.
- video — native res/fps preserved, and SSIM > 0.995 vs the source.
- audio — zero clipped samples, peak under −0.5 dBFS, stereo preserved.
- decode — clean full decode.
- retention — the 2026 five-second rule: no block >5s with nothing changing.
The meta-lesson: a verifier that assumes is a verifier that lies
Three times, the verifier was the bug:
- It recomputed the caption frame numbers instead of reading what the renderer wrote — so it re-implemented the code under test and cheerfully agreed with its off-by-one. Fix: verifiers read the artifact the renderer produced, never recompute it.
- It measured the video's SSIM over a region containing the graphics and the progress bar, cried "SOFTENED" at 0.894, and was comparing a blurred overlay to raw video. Fix: measure only where the pipeline is the only thing touching the pixels.
- It read ffmpeg's SSIM from stderr when it goes to stdout, and reported "not measurable" — which passed. A check that cannot measure is worse than no check.
When a check fails, first ask whether the check is wrong. Then fix the video.
When the gate fails
Read the message, don't just re-run. Each failure names the file and the moment. The gate prints the numbers so you can see whether a value is marginal or catastrophic.
Known-acceptable warnings:
107s > 90s LinkedIn sweet spot— informational; shorter is better but not a defect.
| 1 | |
| 2 | name shorts-qa |
| 3 | description The quality gate for edited talking-head shorts. Seven measured checks — cuts, captions, motion-graphic sync, video fidelity vs source, audio integrity, decode, and retention. Use before shipping any clip produced by shorts-edit, or when asked whether a video is ready, whether quality was lost, or to verify an edit. |
| 4 | |
| 5 | |
| 6 | # shorts-qa |
| 7 | |
| 8 | ## Align before you measure |
| 9 | |
| 10 | The SSIM check answers exactly one question: **did the encode soften the image.** It must |
| 11 | therefore be read at the *best* alignment, because `src_t -> out_t` comes from EDL floats |
| 12 | and can slip by a frame — and on a talking head **one frame of head movement costs |
| 13 | 0.005-0.009 SSIM**, which straddles the 0.995 threshold precisely. |
| 14 | |
| 15 | It failed two perfectly good clips for *moving*: 0.9897 at the assumed offset, **0.9979 one |
| 16 | frame over**. `check_video` now takes the max mean over ±2 frames and prints the alignment. |
| 17 | Timing is a different question, and `verify_cuts` already owns it. |
| 18 | |
| 19 | Same check, second bug: it scored `vals[-1]`, the **last per-frame line** of 60, not the |
| 20 | window mean. A gate whose number is a coin toss on one frame is not a gate. |
| 21 | |
| 22 | Third: **measure between the burns.** A film burn is a deliberate full-frame warm flash. |
| 23 | Five flashed frames out of sixty drag the mean to 0.984, and the gate then shouts SOFTENED |
| 24 | at the one effect we added on purpose. `check_video` now rejects any window containing a |
| 25 | burn. |
| 26 | |
| 27 | ## The verifier must be safe to run concurrently |
| 28 | |
| 29 | `SC` was one shared `/tmp/shorts_qa`, so two `qa.py` processes overwrote each other's |
| 30 | `ref.yuv` / `out.yuv` and the gate **compared frames from a different clip** — reporting |
| 31 | SSIM **0.9514** on a clip that actually measures **0.9976**. It is now per-PID. |
| 32 | |
| 33 | Three of the four "failures" in that batch were the harness, not the footage. A verifier |
| 34 | that is unsafe under parallelism will eventually lie, and it lies in the direction of |
| 35 | **failing good work** — which is the direction that gets gates switched off. |
| 36 | |
| 37 | |
| 38 | > **Nothing is done until this passes. Not "looks good" — passes.** |
| 39 | |
| 40 | |
| 41 | export SHORTS_PROJECT="/path/to/project" |
| 42 | S=~/.claude/skills/content-vault/skills/shorts-edit/scripts # wherever you cloned it |
| 43 | python $S/qa.py # every clip |
| 44 | python $S/qa.py "<clip>" # one |
| 45 | |
| 46 | Exit code 1 on any failure. |
| 47 | |
| 48 | ## Why this exists |
| 49 | |
| 50 | **Every bug in this pipeline's history was invisible to eyeballs and obvious to a |
| 51 | measurement.** Not one was caught by watching the video. |
| 52 | |
| 53 | | Check | The defect it exists to catch | |
| 54 | |---|---| |
| 55 | | **cuts** | A cut through a voiced "um". Inaudible frame-by-frame; a chewed syllable in motion. | |
| 56 | | **captions** | "THING" on screen where "THE" belonged. Every eyeball check happened to land on long words and looked perfect; "THE" is 3 frames long. | |
| 57 | | **motion** | A tier grade revealed 5.7s before it was spoken — the punchline, spoiled. Nothing flagged it; every frame was individually correct. | |
| 58 | | **video** | A second encode softening the image. SSIM 0.977 vs 0.998. Invisible on a phone, real on a 246 kbps source. | |
| 59 | | **audio** | `loudnorm` silently abandoning linear mode and pumping. And a mono SFX bed downmixing the stereo voice into +0.83 dBFS clipping. | |
| 60 | | **decode** | Corrupt output that still plays in QuickTime. | |
| 61 | | **retention** | 91% of a clip sitting in blocks where nothing changes for >5s. Passed every other check. | |
| 62 | |
| 63 | ## The seven checks |
| 64 | |
| 65 | **cuts** — no cut edge lands on live speech. The intersection of two tests: it must land |
| 66 | *inside a word* (per the transcript) AND be *voiced* (per the audio). Either alone is |
| 67 | useless — the word grid gave 25 false alarms, and "voiced at the edge" flags every |
| 68 | deliberate filler deletion. |
| 69 | **captions** — pixel-matches each rendered frame against the word bitmap we drew, scored |
| 70 | against the expected word *and its neighbours*, **sampling biased toward the shortest |
| 71 | words**. Reads the schedule the renderer wrote. |
| 72 | **motion** — every graphic fires within 0.2s of its spoken cue; no typo'd cue silently |
| 73 | dropping a graphic; no overlapping panels. |
| 74 | **video** — native res/fps preserved, and SSIM > 0.995 vs the source. |
| 75 | **audio** — zero clipped samples, peak under −0.5 dBFS, stereo preserved. |
| 76 | **decode** — clean full decode. |
| 77 | **retention** — the 2026 five-second rule: no block >5s with nothing changing. |
| 78 | |
| 79 | ## The meta-lesson: a verifier that assumes is a verifier that lies |
| 80 | |
| 81 | Three times, the *verifier* was the bug: |
| 82 | |
| 83 | It **recomputed** the caption frame numbers instead of reading what the renderer wrote — |
| 84 | so it re-implemented the code under test and cheerfully agreed with its off-by-one. |
| 85 | **Fix: verifiers read the artifact the renderer produced, never recompute it.** |
| 86 | It measured the video's SSIM over a region containing **the graphics and the progress |
| 87 | bar**, cried "SOFTENED" at 0.894, and was comparing a blurred overlay to raw video. |
| 88 | **Fix: measure only where the pipeline is the only thing touching the pixels.** |
| 89 | It read ffmpeg's SSIM from **stderr** when it goes to stdout, and reported "not |
| 90 | measurable" — which *passed*. **A check that cannot measure is worse than no check.** |
| 91 | |
| 92 | When a check fails, first ask whether the *check* is wrong. Then fix the video. |
| 93 | |
| 94 | ## When the gate fails |
| 95 | |
| 96 | Read the message, don't just re-run. Each failure names the file and the moment. The gate |
| 97 | prints the numbers so you can see whether a value is marginal or catastrophic. |
| 98 | |
| 99 | Known-acceptable warnings: |
| 100 | `107s > 90s LinkedIn sweet spot` — informational; shorter is better but not a defect. |
| 101 |
Discussion
Browse more free Claude skills.