SIMP
A DJ instrument built on YouTube's public player, with nothing downloaded
A browser-based DJ sampler built entirely on YouTube's public player — cue points, bar-quantized loops, tap tempo, and a BPM warp engine. The platform doesn't provide raw audio, so nothing is downloaded.
Seven fixed YouTube playback rates treated as the whole tempo space — the warp engine snaps to the nearest one and reports the residual instead of pretending it's exact.
Load a Track, Start Playing
The actual instrument. Paste a YouTube URL, tap a tempo, fire cues on the number keys — nothing is downloaded, and the player underneath is the stock embed.
Every obvious way to sample YouTube is a policy violation. Download the audio and you have broken the terms before the first cue point. The IFrame API is the one sanctioned door, and it hands over almost nothing: play, pause, seek, and a fixed menu of playback rates. No audio buffer. No waveform. No Web Audio graph — architecturally impossible, not just unbuilt.
So the instrument had to be built out of the controls a video player is willing to give you. Seeking became cue points. Rate became tempo. A timer became the sequencer. The player never knows it joined a band.
The folder archaeology, straight from the archive README. Which build was actually
live was established by hash — the bundle the site serves was matched against every SIMP
folder on disk and appears in exactly one dist/.
| Generation | Stack | Fate | Why it died |
|---|---|---|---|
| SIMP v01 | Chrome extension | archived | manifest-v3 sandbox couldn't hold the instrument |
| SIMP v02 | Python + yt-dlp | archived | worked perfectly — and could never ship. It downloads the audio. |
| simp | Create React App | archived | CRA was already deprecated under it |
| simp-backup | CRA copy | archived | a checkpoint, never a direction |
| simp-new | CRA + TS migration | archived | migrating a dead scaffold instead of leaving it |
| simp-v2 ← live | Vite + React + TS + Tailwind | shipped | policy-compliant by construction: IFrame API only |
v02 is the interesting corpse: the version that solved the problem by ignoring the constraint. It sounded best and was unshippable. The live build is the answer to “what survives if the constraint is taken seriously?”
Ableton-style warping needs a continuous playback rate. YouTube offers seven fixed
ones. So bpmWarp.ts computes the ideal rate, snaps it to the nearest entry in the menu,
and — instead of pretending — shows you the residual: the BPM you asked for versus the BPM
you actually got. Try it:
The same math the tool runs: rate = target / source, snapped to
YouTube's supported list. Green pill = the rate the player will actually be set to. The residual
line is the honesty: at most tempos, you don't land exactly.
// bpmWarp.ts — the constraint, then the
// author arguing with himself in comments
export const YOUTUBE_SUPPORTED_RATES =
[0.25, 0.5, 0.75, 1, 1.25, 1.5, 2];
// Example: A 7.5 second loop that is 4 beats
// - BPM = (4 * 60) / 7.5 = 32 BPM...
// wait that's wrong
// Wait, let me recalculate:
// - At 128 BPM: 128/60 = 2.133 beats/sec
// - 4 beats / 2.133 = 1.875 seconds
// So: sourceBPM = (loopBeats * 60) / duration
// tsconfig.json — the gate that lied
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}
// `tsc --noEmit` reads this, finds no files,
// checks nothing, reports zero errors.
// The real gate is `tsc -b`. 32 errors
// accumulated behind the fake green.
vite dev never typechecks either, so the
app ran fine for months while the production build was broken. Found the day it had to ship.Real
Ten cue points on keys 1–9 and 0. Loop lengths in beats, not seconds — 8 divisions, bar-snapped. Tap tempo. A step sequencer whose interval recomputes when the BPM moves. A metronome. BPM warp with the residual readout above.
And the ship path: sync-simp.sh rebuilds the app, embeds it into this site,
and verifies every asset reference resolves before deploying.
Decorative, or unbuilt
The waveform is a sum of four sines — the file says so in a comment. With no audio buffer there is nothing to draw, so it's set dressing, labelled as such.
SoundCloud and Spotify providers exist only as types. The auto-detect-BPM button is three-quarters written: handler, icon and estimator all exist; the button was never added.
Project Elements
Have a Project in Mind?
Animation direction, VFX and creative technology. Message me on LinkedIn or get in touch.