Catalog npm
Back to packageRELEASE DETAILS

0.1.7

npm

4track

A 4-track cassette recorder component for Svelte 5

4-trackaudiocassetterecordersvelte
Published6 Apr 2026
Direct dependencies9
Transitive dependenciesNot calculated

README

Current package documentation

4track

A browser-based 4-track audio recorder built with the Web Audio API and SvelteKit. Designed for low-latency recording with overdub support, latency compensation, and sample-accurate multi-track playback — all running entirely client-side with no server required.

4-Track Recorder

Give it a try

You can try out the 4 track recorder on 4track.cc

Installation

npm install 4-track-recorder

Basic Usage

<script>
  import { FourTrack } from "4-track-recorder"
</script>

<FourTrack />

Saving and Loading Projects

The component uses a custom .4trk binary format that stores all track audio data and mixer settings (volume, pan, master volume).

Bind save and load functions

Use bind:save and bind:load to get functions you can call from your own UI:

<script>
  import { FourTrack } from "4-track-recorder"

  let save
  let load

  function handleSave() {
    const blob = save()
    // Download as file
    const url = URL.createObjectURL(blob)
    const a = document.createElement("a")
    a.href = url
    a.download = "my-song.4trk"
    a.click()
    URL.revokeObjectURL(url)
  }

  function handleLoad(event) {
    const file = event.target.files?.[0]
    if (file) load(file)
  }

  // Or load directly from a URL
  function loadFromUrl() {
    load("https://example.com/songs/demo.4trk")
  }
</script>

<FourTrack bind:save bind:load />

<button onclick={handleSave}>Save Project</button>
<input type="file" accept=".4trk" onchange={handleLoad} />

Load a project on mount

Pass a URL or File to initialProject to auto-load a project when the component mounts:

<FourTrack initialProject="/songs/demo.4trk" />

Props

PropTypeDescription
hiddenTracksHiddenTrackConfig[]Background audio tracks (e.g. cassette hiss)
onready(detail: { engine: AudioEngine }) => voidCallback when the engine is initialized
save() => Blob (bindable)Bind to get a function that exports the project as a .4trk blob
load(source: File | string) => Promise<void> (bindable)Bind to get a function that imports a .4trk file or URL
initialProjectstring | FileURL or File to auto-load on mount
configPartial<AudioEngineConfig>Extra engine config passed through to AudioEngine (see below)

Engine configuration

FourTrack creates an AudioEngine internally; pass extra options via the config prop, or construct new AudioEngine(config) yourself.

OptionTypeDefaultDescription
sampleRatenumber32000Storage/export rate. The live graph always runs at the hardware's native rate; tracks are resampled to this rate on export. 0 = export at native.
bitDepth8 | 16 | 3216PCM bit depth in exported .4trk files
audioConstraintsMediaTrackConstraintsMerged over the engine's getUserMedia defaults (echo cancellation, noise suppression and AGC off)
captureStream(constraints) => MediaStream | Promise<...>Supplies the mic stream instead of the engine calling getUserMedia
persistentCapturebooleanfalseAcquire the mic once and record each take from a clone(); avoids WebKit's level ramp at take start. Release with engine.releaseCapture()
monitoringAdapter{ start(detail), stop() }Takes over the live mic-to-speakers pass-through (e.g. a native audio path). Capture, meters, playback and export stay on Web Audio
recordingLatencyOffsetnumber (seconds)Overrides the computed recording latency compensation. Also settable at runtime via engine.recordingLatencyOffset

Recording latency compensation

When you overdub, the backing track reaches your ears after the output latency and your playing reaches the recorder after the input latency, so every recorded sample lands late by roughly the sum. The engine shifts each take earlier by outputLatency + baseLatency + mic latency as advertised by the browser. Browsers (WebKit especially) understate these values, so if takes still land late, measure the real round trip (a loopback click test works) and set recordingLatencyOffset:

<FourTrack config={{ recordingLatencyOffset: 0.045 }} />

External monitoring

If your host can monitor the mic with lower latency than Web Audio (for example a native audio path in a desktop wrapper), hand it the pass-through:

const config = {
  monitoringAdapter: {
    start: ({ stream, trackIndex, context }) => native.startMonitoring(),
    stop: () => native.stopMonitoring(),
  },
  captureStream: (constraints) => navigator.mediaDevices.getUserMedia({ audio: constraints }),
  recordingLatencyOffset: 0.012,
}

License

4track is dual-licensed under GPL-3.0-only or a commercial license. Use it under the GPL for free, or reach out for a commercial license if you need to embed it in a closed-source product (e.g. an App Store app).

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 10

Native requirements
9 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
sass
Environment
{
  "local_name": "sass",
  "alias": false,
  "peer_metadata": null
}
^1.97.3development
vite
Environment
{
  "local_name": "vite",
  "alias": false,
  "peer_metadata": null
}
^7.3.1development
svelte
Environment
{
  "local_name": "svelte",
  "alias": false,
  "peer_metadata": null
}
^5.49.2development
prettier
Environment
{
  "local_name": "prettier",
  "alias": false,
  "peer_metadata": null
}
^3.8.1development
typescript
Environment
{
  "local_name": "typescript",
  "alias": false,
  "peer_metadata": null
}
^5.9.3development
svelte-check
Environment
{
  "local_name": "svelte-check",
  "alias": false,
  "peer_metadata": null
}
^4.3.6development
@sveltejs/package
Environment
{
  "local_name": "@sveltejs/package",
  "alias": false,
  "peer_metadata": null
}
^2.5.7development
prettier-plugin-svelte
Environment
{
  "local_name": "prettier-plugin-svelte",
  "alias": false,
  "peer_metadata": null
}
^3.5.0development
@sveltejs/vite-plugin-svelte
Environment
{
  "local_name": "@sveltejs/vite-plugin-svelte",
  "alias": false,
  "peer_metadata": null
}
^6.2.4development
svelte
Environment
{
  "local_name": "svelte",
  "alias": false,
  "peer_metadata": null
}
^5.0.0peer

Distribution files

1 collected
Distribution 1

Source distribution

Source file
Checksums from source
{
  "shasum": "0616542d9e81c2a2c6570f0919245b29b44d4d43",
  "tarball": "https://registry.npmjs.org/4track/-/4track-0.1.7.tgz",
  "fileCount": 78,
  "integrity": "sha512-gLyU5wTRMjORW4PnmNEaESx7MEgDlT+Fn2phSTMlFQqLjHcIG+QxkMCmmw39mGvfGMlQ0mS8pSxWQ1tWKfHZqA==",
  "signatures": [
    {
      "sig": "MEQCIHiFNqKEFravlZBHFqAsvB5pV7yl2eQOc0IERRTa56IkAiBVR5gqp/hrpP7l6JsvyGdMoM3qa6M2jNG7G77i0khJ6Q==",
      "keyid": "SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"
    }
  ],
  "unpackedSize": 2470939
}

Repository

PENDING
andreboekhorst/4-track-recorder

Shared repository data · GitHub

License detected in repository
Not collected

Repository

PENDING
andreboekhorst/4track.cc

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 20:18 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:4f0b0f287c9bbfb3b702df55ab8d6f6d6baa978af7bc384fa125fe0be20deb20

Other collected versions

0.2.16 Sept0.2.06 Sept0.1.1523 Aug0.1.1413 Apr0.1.1313 Apr0.1.1213 AprView all collected versions →