Build Soundtrap
KINDAreplaces $14.99/mosaves $179.88/yrback to the verdict
A browser multitrack recorder with a click, latency-compensated recording that lands on the beat, regions you can move and trim without destroying the take, a mixer with levels and pan, and export of the mix and every stem at sample-aligned starts.
Before step 1
Everything below is assumed from the first step. Tick each one when you actually have it, not when you plan to.
- installfree
Why Runs the build.
Get it nodejs.org, or nvm install 22. open ↗
Verify
node --version prints v22 or higher - have readya basic interface is around 100 US dollars; measurement works without one
Why Latency compensation can be measured with any input, but playing along to a click through browser monitoring is genuinely difficult past about twenty milliseconds, and direct monitoring removes that.
Get it Any USB audio interface with a direct monitor control, or headphones plus a built-in microphone for measurement only.
Verify
The device appears as an input and a round trip measurement completes - have readyfree with a cable you own
Why Phase 2 needs the click to reach the input. A physical loop is the most accurate method and a microphone in front of a speaker is adequate.
Get it A cable from output to input if your interface allows it, or place a microphone near a speaker in a quiet room.
Verify
The calibration routine produces a stable figure across three runs - have readyfree
Why Alignment is verified by looking at transients against the grid, and a sustained sound has no transient to look at.
Get it Clapping works. So does tapping a desk.
Verify
A four-hit recording shows four clear transients - installfree
Why Metering and any per-sample work must run on the audio thread, and the worklet is how that happens.
Get it A current Chromium, Firefox or Safari. Test in at least two, since audio behaviour differs.
Verify
An AudioWorklet loads and posts messages
Data model
Create these before the first phase that stores anything. Changing a table later is the expensive kind of change.
- projects(id, name, tempo_bpm, time_signature, sample_rate, created_at) - tracks(id, project_id, name, ordinal, gain_db, pan, muted, soloed, input_device_id) - takes(id, track_id, buffer_key, recorded_at, raw_start_ms, compensated_start_ms, duration_ms, latency_applied_ms) - regions(id, track_id, take_id, timeline_start_ms, source_offset_ms, duration_ms, gain_db, fade_in_ms, fade_out_ms) - calibrations(id, device_id, measured_round_trip_ms, measured_at, method) - A region references a take with an offset. Trimming moves the region's window, never the recorded audio, so every edit stays reversible.
Environment variables
These go in a .env file the app reads at startup. The pack's .env.example is this table as a file · copy it, never commit the filled-in version.
| Variable | Needed | Example | Where the value comes from |
|---|---|---|---|
VITE_DEFAULT_TEMPO | required | 120 | Starting tempo for a new project. |
VITE_SCHEDULER_LOOKAHEAD_MS | required | 120 | How far ahead events are queued against the audio clock. Longer is safer and less responsive to tempo changes. |
VITE_MAX_PROJECT_MB | required | 800 | Warn as a project approaches this size, before the browser quota fails a recording. |
VITE_MONITOR_WARN_MS | required | 20 | Above this measured monitoring delay, warn that playing along will be difficult. |
VITE_EXPORT_SAMPLE_RATE | required | 48000 | Render rate for export. Matching your recording rate avoids a resample. |
The build, in order
Playback on a clock
A click plays in perfect time and does not drift over ten minutes.
Schedule events a short window ahead against the audio clock, driven by a timer that only refills the queue.
Files
src/clock.tsterminalnpm create vite@latest . -- --template vanilla-ts
Scheduled clicks, not triggered ones. This is the pattern everything timed will use.
Files
src/metronome.tsCompare the final click's actual time against the calculated time. This is the test that catches a timer-based scheduler.
Files
src/clock.test.ts
done when · tick each as it passeswatch out- Scheduling audio with setTimeout or setInterval produces audible jitter immediately and measurable drift within minutes, because those timers are not real-time and are throttled in a background tab. Use a lookahead scheduler that queues events against the audio context's own clock, which is sample accurate.
Recording that lands on the beat
What you play on the beat is recorded on the beat.
Play a click, record it through the loop, and measure the offset. Store the result per device with a timestamp.
Files
src/calibrate.tsShift the recorded start back by the measured round trip. Store both times so the correction is inspectable.
Files
src/record.tsFour hits on the beat, then look at the transients against the grid. Do not skip the visual check.
done when · tick each as it passeswatch out- Round trip latency varies by device, browser and buffer size, so a hard coded compensation value will be right on your machine and wrong on every other one. Measure it, store it per device, and re-measure when the device changes.
- Verify alignment visually and audibly, not by trusting the number. Record a sharp percussive sound exactly on four beats and look at where the transients sit relative to the grid.
Tracks, takes and non-destructive regions
You can record several tracks, move and trim them, and never lose a take.
To IndexedDB as recording finishes. A lost take is the failure people abandon a tool over.
Files
src/store.tsTake reference, source offset, duration. Trimming edits the window only.
Files
src/regions.tsReference counting, so deleting one region does not destroy another's source.
Files
src/takes.ts
done when · tick each as it passeswatch out- Trimming by rewriting the audio buffer destroys the material outside the trim, and the first time someone trims too far they have lost the take. A region is a window onto a take: trimming moves the window, and dragging the edge back out restores what was there.
Monitoring and the mixer
You can hear yourself while recording without the delay making it impossible to play.
Gain and pan per track into a master. Solo is a mute of everything else, computed rather than stored per track.
Files
src/mixer.tsAn AudioWorklet computing levels and posting them, so metering never blocks audio.
Files
src/meter-worklet.jsShow the measured number next to the toggle. It is the difference between a usable session and a frustrating one.
Files
src/monitor.ts
done when · tick each as it passeswatch out- Monitoring your own voice through the browser adds the full round trip to what you hear, and past roughly twenty milliseconds that delay makes singing or playing genuinely difficult. Offer the option, state the measured delay next to it, and recommend hardware or direct monitoring where the interface provides it.
Export, mix and stems
What you export is what you heard, and the stems line up when reassembled.
An OfflineAudioContext rendering the graph. Faster than real time and deterministic, unlike capturing playback.
Files
src/export.tsSame length, same start, leading silence included. This is what makes them portable.
Files
src/export.tsSum the stems and compare against the mix numerically. A difference means a gain or pan is applied in one path and not the other.
Files
src/export.test.ts
done when · tick each as it passeswatch out- Exporting stems trimmed to each track's first sound means they no longer share a start, and dropping them into another tool puts everything in the wrong place. Every stem starts at timeline zero including its leading silence, which is what makes them usable elsewhere.
Projects, storage and honest limitsproduct builder
Projects survive, storage does not fill silently, and you know what this is not.
State plus audio. Reload and play to confirm, since a project that loads but is silent is a common failure.
Files
src/project.tsEstimate available storage and warn before recording rather than failing during it.
Files
src/quota.tsStems plus a manifest with tempo, track names and region positions.
Files
src/export.ts
done when · tick each as it passeswatch out- Browser storage has a quota and audio fills it quickly, and hitting it mid-recording loses the take you were making. Check available quota before arming a recording and warn well before the limit rather than failing at the worst moment.
That is the whole plan for Soundtrap. What it deliberately does not cover is below · check the gaps before you call it a replacement.
- Real-time collaboration.
- Instruments, loops and the licensed sound library.
- The education and classroom workflow.
- Effects beyond gain and pan.
- realtime collaboration, loops, instruments, education workflow, and hosted rendering
- licensed music catalog
- royalty and distribution relationships
- global streaming infrastructure
- artist network and recommendations
- Punch recording over a region, which the take and region model already supports
- A simple equaliser per track, once timing and export are trustworthy
- Tempo mapping so a recording made without a click can be gridded afterwards
Need the files? The project pack on the verdict page hands your agent the whole brief · more music & audio.