Inspiration
I make indie games (Drive Away, The Final Room, Fail Hard) and I playtest with friends. When I ask how it went, they say "it was fine." But when I watch them play, I can see them frown at a jump or grin at a crash, and by the time the session is over neither of us remembers where it happened. I wanted a tool that remembers for me.
What it does
Flinch is a free playtest recorder that runs in one Chrome tab. It records the game window and the tester's webcam and mic at the same time. First it spends ten seconds learning the tester's resting face. During the session it pins the moments their expression clearly changed: possible frustration, possible delight, plus my own markers (press M). After the session I click a pin and watch the game and the face from three seconds before.
Exports: a Markdown fix list with timecodes and notes, the full recording, and a short highlight reel of the kept moments. You can also compare two saved playtests of different builds.
Flinch measures facial movement against the tester's own resting face. It does not detect emotions. A pin tells you where to look, and you decide what it meant.
How I built it
I built it with Claude Code, following the course's six skills in order: start, scope, PRD, spec, build, ship. The planning docs became the plan the agent built from, one slice at a time, with tests after each slice.
- Capture:
getDisplayMedia+getUserMedia, recorded as two native WebM files with MediaRecorder, so recording keeps going while the game covers Flinch. - Face reading: MediaPipe Face Landmarker in a Web Worker, about 15 reads a second, which gives blendshape scores (brows down, smile, squint...).
- Signals: frustration and delight scores, measured as how many spreads they sit above the tester's calibrated rest, smoothed, with a resting level that drifts slowly so steady concentration doesn't flood the timeline.
- Moments: a pin goes wherever a signal stays 2.5 spreads above rest for half a second. Pins are boosted when the mic is loud, merged when closer than 5 s, and only the strongest 12 are kept.
- Privacy: no account, no server, no upload. Everything stays in the browser's IndexedDB, and a strict Content-Security-Policy blocks outside requests. The tester ticks a consent box before anything records.
- Tests: Vitest unit tests, plus 19 Playwright journeys in headless Chromium with a fake camera, mic and screen (including a fake face that goes from calm to smiling), and a 10-minute memory soak test.
Challenges
- Background tabs: Chrome can't hand camera tracks to a worker, and it throttles hidden tabs. So after Stop, Flinch reads any missed stretches back from the face recording.
- Faces aren't feelings: a concentration frown or a squint at a bright screen looks like frustration. Calibrating to each tester's own resting face and requiring a sustained change cut most of the false pins, and the labels say "possible" for a reason.
- A hidden tracker: MediaPipe's library sends usage stats to Google from inside its worker, where the page's CSP doesn't apply. I rewrite that URL at build time so nothing leaves the machine.
What I learned
Writing a scope, PRD and spec before any code made the agent's build much more predictable. Each slice had acceptance checks it could test against. I also learned how blendshapes work, and how much of "AI detects emotion" is really just measuring muscle movement.
What's next
Firefox and Safari support, tuning the thresholds with more real playtests, and a way to share a moment with a teammate.
Built With
- indexeddb
- mediapipe
- mediarecorder
- playwright
- typescript
- vite
- vitest
- web-workers
- webrtc
Log in or sign up for Devpost to join the conversation.