A gesture-controlled theremin in a single HTML file — camera hand tracking, historical temperaments, deep synthesis and MIDI out.
3
stars
7
commits
HTML
primary language
Aug 20, 2026
updated
A gesture-controlled theremin in one HTML file. termenvox.vercel.app
Right hand steers pitch across the field, left hand rides volume — lift to swell, drop to hush (swappable for left-handed play). No camera? Drag in the field, or press K and play the keyboard piano-style. Camera frames are processed on-device and never uploaded.
Every control explains itself: hover a label, tap it on a phone, or press What's this? to pin all the descriptions inline.
Space hold · K keyboard · M mute · R record · C camera · L latch · F fullscreen · [ ] octave · 1–6 presets · Esc panic · ? help
npm run dev # http://localhost:4173 — a server is only needed for camera access
npm test
index.html is the whole application; deploying it is copying one file. The
MediaPipe model is the only runtime fetch — without it the blob tracker takes
over. The music maths lives in a dependency-free <script id="tvx-core"> block
inside the page; test/core.test.mjs extracts that block and runs it under
node:test.
Optional, and off unless configured. npm run build — the Vercel build command —
rewrites the <!-- umami --> block in index.html from the environment:
| Variable | |
|---|---|
UMAMI_WEBSITE_ID | Enables analytics. Unset means no script is emitted at all. |
UMAMI_SCRIPT_URL | Instance base URL or full script.js path. Defaults to https://linesofcode-umami.vercel.app/script.js. |
UMAMI_DOMAINS | Comma-separated hosts to count, so previews and forks stay out of the stats. |
Umami is cookieless and collects no personal data. The build is idempotent, so running it without the variables strips the tag back out.
MIT
7 commits
HTML
86.5%
JavaScript
13.5%
A gesture-controlled theremin in a single HTML file — camera hand tracking, historical temperaments, deep synthesis and MIDI out.
3
stars
7
commits
HTML
primary language
Aug 20, 2026
updated
A gesture-controlled theremin in one HTML file. termenvox.vercel.app
Right hand steers pitch across the field, left hand rides volume — lift to swell, drop to hush (swappable for left-handed play). No camera? Drag in the field, or press K and play the keyboard piano-style. Camera frames are processed on-device and never uploaded.
Every control explains itself: hover a label, tap it on a phone, or press What's this? to pin all the descriptions inline.
Space hold · K keyboard · M mute · R record · C camera · L latch · F fullscreen · [ ] octave · 1–6 presets · Esc panic · ? help
npm run dev # http://localhost:4173 — a server is only needed for camera access
npm test
index.html is the whole application; deploying it is copying one file. The
MediaPipe model is the only runtime fetch — without it the blob tracker takes
over. The music maths lives in a dependency-free <script id="tvx-core"> block
inside the page; test/core.test.mjs extracts that block and runs it under
node:test.
Optional, and off unless configured. npm run build — the Vercel build command —
rewrites the <!-- umami --> block in index.html from the environment:
| Variable | |
|---|---|
UMAMI_WEBSITE_ID | Enables analytics. Unset means no script is emitted at all. |
UMAMI_SCRIPT_URL | Instance base URL or full script.js path. Defaults to https://linesofcode-umami.vercel.app/script.js. |
UMAMI_DOMAINS | Comma-separated hosts to count, so previews and forks stay out of the stats. |
Umami is cookieless and collects no personal data. The build is idempotent, so running it without the variables strips the tag back out.
MIT
7 commits
HTML
86.5%
JavaScript
13.5%