rauchg/vinyl
Media & DesignA browser-based record player that physically simulates cutting, pressing and playing vinyl records.
Project Overview
vinyl is a browser-based record player in which the audio you hear is not a decoded audio file, but the result of physically simulating a stylus reading a groove. The project cuts audio into the shape of a 45/45 stereo groove, presses it into a virtual disc, and runs a stylus, cantilever, tonearm and cartridge model on the audio thread. What the listener hears is the voltage that such motion would induce, after RIAA de-emphasis.
The project is aimed at people interested in audio, Web Audio, WebGL2, and physical simulation. It offers pre-cut public-domain records on a shelf, plus a "cut a file" flow that processes audio dropped by the user in a worker. The simulation covers groove roughness, dust, scratches, warp, off-centre holes and groove echo; these affect the geometry itself rather than being added as audio effects README.
Quick Start
To use the hosted version, open vinyl-gl.vercel.app in a modern browser with WebGL2 and Web Audio support; no installation is required.
To run it locally, you need Node.js 22 or later. The README's run command is vercel dev README; it builds once, serves the result at localhost:3000, and requires a restart after edits.
If you prefer not to use Vercel, the build itself is plain Node and can be run directly:
npm run build # writes dist/: index.html, src/, assets/, records/
npm test # offline checks of the physics
npm run bench # CPU cost of the engine per second of audio
To create a new record or re-cut one after changing the lathe, you need ffmpeg. Run npm run lathe for every out-of-date record, or node lathe.mjs <name> for a single one, then commit the resulting assets/ README. The build refuses to deploy a shelf record that has never been cut.
How It Works
The pipeline has four stages, each with its own source file README:
- Cut — src/cut.js converts audio into the two groove walls at 33⅓ rpm, applying RIAA pre-emphasis, an acceleration limiter, and a spiral pitch that fits the side on a 12-inch disc.
- Press — src/press.js changes the disc geometry: wall roughness, dust, scratches, warp, off-centre hole, groove echo. It is seeded, so the same record always presses the same way.
- Play — src/engine.js, src/engine-core.js and src/groove.js run the stylus over the walls. Tracing distortion, pinch effect and inner-groove loss emerge from the finite tip radius rather than being applied as effects.
- Draw — src/render.js and src/shaders.js draw the actual spiral, lit by how hard each revolution is modulated.
Usage Constraints
The project is browser-based and relies on WebGL2 and Web Audio; the simulation runs inside an AudioWorklet. The build and tests require Node.js 22 or later. No dependencies or bundler are used; the build simply copies files. Re-cutting records requires ffmpeg, and cutting a full side takes a while, which is why shelf records are pre-cut and committed to assets/.
The code is MIT-licensed LICENSE. The bundled recordings keep their own licenses; one of them, Summer: Presto, is CC BY-SA 4.0, so its cut is too. The source audio lives in records/ and is listed in src/records.js.
HotRepo's take
The repository entered HotRepo's new-project board for JavaScript on 2026-11-10, with 104 stars and 26 forks, and 4 stars gained in a roughly 1.5-hour window starting 2026-11-09T23:15Z. That is a single short-window record, so it does not yet support a trend claim. What stands out technically is the project's unusual premise: it does not add vinyl noise as an effect, but derives playback artifacts from simulated groove geometry and contact mechanics, and ships the pre-cut records needed to make that load quickly in a browser README.
Written by AI from the project's README, updated . The project's own docs are the source of truth.