← Back to Ships
typoface
Real-time typographic portrait — your webcam rendered as a mosaic of colored word pills
Next.js 15TypeScriptTailwind CSSCanvas APIWeb Audio APIMediaRecorder
A live typographic portrait that reads your webcam and rebuilds it every frame as a dense grid of rounded word badges. Each pill’s opacity tracks the local pixel brightness underneath it — bright areas of your face become opaque, vivid pills; shadows fade into the background.
What’s in it
- 60fps render loop — Float32Array luminance + 22×22 block-mean buffers pre-allocated once, reused every frame
- Audio-reactive mode — Web Audio AnalyserNode on the mic, bass → pulse amplitude, mid → brightness lift
- 8 named color themes — K-Pop, Matrix, Sakura, Ocean, Fire, Neon, Mono, Pastel
- 6 word pools — Korean, Japanese, Arabic, English, Spanish, or fully custom text typed in live
- 3 visual effects — Wave (sine ripple), Glitch (band shift), Breathe (sync pulse)
- Capture & record — PNG snapshot with 3-2-1 countdown overlay, or one-click WebM recording via MediaRecorder
- Keyboard shortcuts —
Mmirror,Iinvert,Ccapture,Rrecord,Spacerandomize theme - Side panel + full randomize — single button rolls theme, language, density, FX, contrast all at once
- All on-device — getUserMedia + Canvas + Web Audio, nothing leaves the browser tab
Learnings
- Pre-allocating Float32Array luminance + 22×22 block-mean buffers and reusing them every frame is what keeps the canvas at 60fps — re-allocating per frame tanks it to 20fps as the GC kicks in
- Unsharp masking via `lum + (lum - blockMean) * 1.6` makes the face pop out of the pill grid more than raw luminance does, because flat midtones get pushed apart instead of all landing in the same alpha bucket
- AnalyserNode bands map cleanly to two visual channels — bass → pulse amplitude, mid → brightness — and that separation feels musical without any beat detection logic
- All processing on-device (getUserMedia + Canvas + MediaRecorder, no server) avoids the privacy conversation entirely; users hit the URL and the camera stream never leaves the tab
- Korean / Japanese / Arabic word pools render denser than Latin scripts at the same pill size because the glyphs fill more of the rounded rect — switching language is the cheapest way to change the visual feel