CamMod
Your camera becomes a mod wheel.
Input · Camera
CamMod
Hand and head motion mapped to up to four MIDI CC lanes. Wave a hand to sweep a filter; in the standalone build it exposes a virtual MIDI port to your DAW. Video never leaves your device.
Parameters
Capture
Lanes 1-4 (identical set per lane)
Output
These knobs move the module's published schema, but the preview engine only renders OSC Mini, FX Mini and the OSC-1 chain — so they won't change what you hear yet.
Output · MIDI messages
Notes and CC drive the page's own preview voice. This is the only route wired up today.
Video is processed in your browser and never uploaded. Nothing leaves the machine but CC numbers.
Presets
Preset names do work: they teach the parameter space faster than the table below does.
About
Every modulation source on a computer is either a slow shape you drew or a knob you have one spare hand for. CamMod is a third option: motion. A webcam watches a region you choose, tracks it, and turns position and movement into four continuous MIDI CC lanes. Raise a hand and a filter opens. Lean in and the reverb gets bigger. It's a mod wheel with an unreasonable amount of travel and no hands required.
The tracking is deliberately dumb, and that's a design decision rather than an apology. It follows motion and gross position - a hand, a head, a drumstick, a cat - inside a box you draw on the preview. It does not identify you, does not do gesture recognition, does not know a fist from an open palm, and does not need to. Simple tracking is predictable tracking, and a modulation source you can't predict is a modulation source you can't perform with.
On this site, CamMod's output routes straight into any other Codex tool: open it alongside OSC Mini, drag lane 1 onto Cutoff, and you're playing a filter with your hand in the browser with nothing installed. In the standalone build it does the same thing for your whole studio by exposing a virtual MIDI port - your DAW sees CamMod in its MIDI input list like any hardware controller, and every plugin you own can learn from it.
Privacy, plainly. Video is captured and analyzed on your device, in the page, and thrown away frame by frame. Nothing is uploaded - not frames, not stills, not landmarks, not a summary. There's no account, no server call and no analytics event carrying camera data, because there is no server in this loop at all. The browser's camera indicator is on while CamMod runs and goes off the moment you stop it. Turn off your Wi-Fi and it works exactly the same; that's the test we'd want to run, so we're telling you to run it.
Take it into your DAW.
Same DSP as this page. The plugin isn't a rebuild — it's the identical kernel from the identical TypeScript source, compiled native instead of to WASM.
Free forever, no account, and playing it in the browser will never ask you for one. VST3 and standalone today; AU and CLAP are on the roadmap.
Every knob, and what it actually does.
Generated from the module's parameter schema — the same source as the web UI, the worklet transport and the VST3 parameter table, so it cannot drift.
| Param | Range | Default | Units | What it does | Automatable |
|---|---|---|---|---|---|
| Capture | |||||
Cameracam.device | available devices | system default | — | Which camera. Nothing starts until you pick one and grant permission. | No |
Tracking Regioncam.region | drawn on preview | full frame | — | The box CamMod watches. Smaller boxes track faster and ignore everything else in the room. | No |
Sensitivitycam.sensitivity | 0 … 1 | 0.5 | — | How much movement counts as movement. Turn it down in a busy room, up in dim light. | Yes |
Mirrorcam.mirror | off · on | on | — | Flips horizontally so moving right moves the lane right. Off if you're tracking something that isn't you. | Yes (stepped) |
| Lanes 1-4 (identical set per lane) | |||||
Sourcelane1.source | X position · Y position · Area/Distance · Motion Energy · Off | X position | — | What this lane measures. Area/Distance grows as the subject nears the camera; Motion Energy is speed, not place - it falls back to zero when you stop. | Yes (stepped) |
CC Numberlane1.cc | 0 … 127 | 1 (lane 2: 11, lane 3: 74, lane 4: 71) | — | Which continuous controller to send. Defaults are the usual suspects: mod wheel, expression, cutoff, resonance. | Yes (stepped) |
MIDI Channellane1.channel | 1 … 16 | 1 | — | Channel for this lane's messages. | Yes (stepped) |
Minlane1.min | 0 … 127 | 0 | — | Output floor. Set Min above Max to invert the lane - a legitimate move, not a mistake. | Yes |
Maxlane1.max | 0 … 127 | 127 | — | Output ceiling. Narrow the Min-Max window when a parameter only sounds good in part of its range. | Yes |
Smoothinglane1.smooth | 0 … 1 | 0.4 | — | One-pole filter on the output. Low is twitchy and immediate; high is syrupy and forgiving. Around 0.4 is where most people land. | Yes |
Curvelane1.curve | linear · exponential · logarithmic · S-curve | linear | — | Maps tracked position to CC value. Exponential gives fine control near the bottom, which suits filter cutoff. | Yes (stepped) |
Ratelane1.rate | 15 … 120 | 60 | Hz | CC messages per second for this lane. Above about 60 you're mostly flooding your MIDI stream. | Yes |
| Output | |||||
Holdout.hold | off · on | off | — | Freezes all lanes at their current values. The panic button for when you need to scratch your nose. | Yes (stepped) |
Virtual Portout.portName | text | CamMod | — | Standalone build only: the name your DAW sees in its MIDI inputs. | No |
Parameter paths (filter.cutoff) are what you'll see in your DAW's automation list and in the SDK. Same names everywhere.
How it works.
A getUserMedia stream goes to an offscreen canvas at a reduced resolution - tracking doesn't need 1080p, and downscaling first is most of why this stays cheap. Inside your tracking region CamMod computes a frame difference against a slowly-adapting background, thresholds it by Sensitivity, and takes the centroid and area of what's left. That gives four raw signals per frame: X, Y, area, and total motion energy.
Each lane picks one of those signals, applies its curve, scales it into the Min-Max window, smooths it with a one-pole filter, and emits CC at its Rate with change-detection so a still subject doesn't spam identical values down the wire. In the browser those messages go to any Codex tool on the page and, if you allow Web MIDI, out to real hardware. In the standalone build the same lane engine drives a virtual MIDI port your DAW treats as an ordinary controller.
None of this is audio DSP, so CamMod has no kernel and makes no sound. It's a controller that happens to ship in the same box as the instruments, and it runs on the video frame clock - nominally 30 Hz - rather than the audio block clock. Expect roughly 30-60 ms between a physical move and an audible change, most of which is camera capture, not us. That's fine for filter sweeps and swells; it's not fine for triggering notes, so CamMod doesn't send notes.
It's yours to read and to fork.
Research preview
npx codex clone cammod
npm run devThe codex CLI name is proposed, not shipped. That command gives you this module's DSP, schema, presets and UI as a local project — change a number, hear it immediately.
no audio kernel · control-rate only