Hold up both hands and play. The webcam tracks 21 landmarks per hand: your left hand picks the chord, and your right hand shapes it — height sets the volume, rotation sweeps a filter. Everything — vision and audio — runs in the browser. No video ever leaves your device.
| Gesture | Effect |
|---|---|
| ✋ Left hand, 1–5 fingers | Plays chord slot 1–5, sustained while you hold it — or arpeggiated |
| ✊ Left hand, fist | Silence |
| Volume — higher is louder | |
| 🔄 Right hand rotation | Filter sweep — lowpass, highpass or bandpass |
| 🤚 Right hand, 1–5 fingers | Switches to song section 1–5 |
Five named song sections, each with its own five chord slots, the voice — up to
three wave shapes stacked and detuned against each other, and the ADSR they share —
the arpeggiator — five patterns, an octave span and a gate — the timing — the
tempo everything follows, a metronome you can hear and see, and the grid a chord
change snaps to — the filter and volume
ranges, the effects rack — amounts, the order it runs in, and rates free or locked
to that tempo — which camera feeds the tracker, and tracking steadiness are all
configurable in-app and persist to localStorage.
Whole songs can be saved by name and reopened later — an open song keeps every edit you make from then on, with nothing to press — and copied out as text to send to somebody else. See the user guide.
npm install
npm run dev # also vendors the tracking model + wasm on first runOpen http://localhost:5173, click Start camera & audio, and allow webcam access.
npm test # pure-logic tests (chords, finger counting, rotation, synth engine, overlay)
npm run build # typecheck + production build
npm run lint # oxlintwebcam ──▶ HandLandmarker ──▶ fingerCount ──▶ SynthEngine ──▶ 🔊
(21 landmarks) handRotation PolySynth ×3 ◀── Loop (arp)
│ (per hand) → Filter
└──▶ drawOverlay (canvas) → Effects rack ×6
▲ → Volume
│ └─▶ Meter
│
└──────── level ───────────────┘
MediaPipe Tasks Vision does the tracking, Tone.js does the sound, and the render loop drives the synth imperatively so rendering never gates the audio. Details in architecture.
| Getting started | Install, run, build, test, project layout |
| User guide | Gestures, the sound, chords, HUD, settings |
| Architecture | Module map, data flow, the render loop |
| Audio | Chord model, Tone graph, voice handling |
| Vision | Landmarks, finger counting, debouncing |
| Configuration | Settings schema, persistence, env vars |
| Deployment | Pages pipeline, domain, analytics, SEO and prerendering, releases, rollback |
| Troubleshooting | Camera, WebGL, reversed hands, no sound |
| Contributing | Tests, conventions, extension points |
| AI usage | Claude Code setup, the skills in this repo, vendoring and updating them |
DJ Hands is free, has no ads and no accounts, and runs entirely on your own machine — there is no server to pay for, just the time. If it made you play something you liked, you can buy me a coffee. The same button sits in the top-left corner of the app.
Built by Yusif Aliyev — LinkedIn · Joe in the Studio, my music project.
Inspired by gesture-synth — respect to the original for the idea of turning a webcam into an instrument. DJ Hands is an independent take on it: chord slots with inversion and slash bass, an editable ADSR voice, a rotation-swept filter, and a rotation-invariant finger counter.
Licensed under the Apache License, Version 2.0. You are free to use, modify, and redistribute DJ Hands, including commercially, provided you keep the license and attribution notices and state your changes.