cookcut
Raw cooking footage in, short-form video out.
A local tool that turns raw cooking clips into platform-ready vertical video: scene and audio-event detection, a hook-first edit, loudness-normalised render — plus an editor UI and a batch CLI.
- role
- Side project · solo
- year
- 2026
- platform
- Local web app + CLI
- live
- private
- stack
- FastAPIffmpegfaster-whisperNext.js 16Python
localhost:3000 — cookcut


$ cookcut auto ./recipe --targets vertical_9x16
131s → 31s · 21 shots · hook first
131s → 31s
real footage, auto-cut
21
shots, opens on the dish
18
tests passing
$ ls ./screens
2 screens · scroll →The problem
Cooking content lives on short-form video, and editing it is the bottleneck: forty minutes of phone clips have to become thirty seconds that open on the finished dish. I wanted a tool that does the first cut for me — locally, with no uploads.
What I built
cookcut: a local web app and CLI that turns raw cooking footage into platform-ready video.
- Backend: FastAPI + ffmpeg. Ingest is hash-deduplicated and streamed, so it never loads a whole video into memory. Scene detection and audio-event detection pick the moments; faster-whisper transcribes speech for captions.
- The edit: hook-first — open on the finished dish — then pace the shots, cap how much of the runtime any single source clip can take, and render 9:16, 1:1, 4:5 or 16:9.
- Review:
review.pyscores every cut on hook, pace, runtime and coverage, so "is this cut any good" is a test, not a feeling. - Frontend: a Next.js editor to nudge cuts. CLI: one-click, batch and watch-folder modes.
The hard part: real footage
Everything passed on synthetic test clips. The first real iPhone run found seven bugs. Three favourites:
- Double rotation. ffmpeg autorotates portrait clips from the display matrix; the code was also applying a transpose. Every portrait clip came out sideways. Fix:
-noautorotateon any input that feeds a rotation filter. - Audio events found nothing. The threshold was "noise floor + 12 dB", but real kitchen audio only spans 3–18 dB. Now the threshold is relative to each clip's own dynamic range.
- True peak over the ceiling. AAC reconstructs peaks 0.6–1.2 dB above the PCM it's given, so loudness normalisation now aims lower and verification measures the encoded file.
Outcome
- 131 seconds of real footage → a 31-second vertical cut, 21 shots, opening on the dish, passing every structural check.
- 18 tests, now with real-footage fixtures where synthetic ones lied.