Skip to content
anasfikPublic

About

An advanced real-time audio player supporting all effects (slow, reverb) that elevate your music/audio playing to next level

Topics

Resources

Stars

8 stars

Watchers

0 watching

Forks

Latest commit

 

History

28 Commits

Folders and files

Repository files navigation

SlowedLab — private browser audio studio (slowedlab.app)

SlowedLab studio

An advanced real-time audio player supporting all effects (slow, reverb) that elevate your music/audio playing to next level. Paste a SoundCloud link to play it instantly, or upload your own files.

Features

  • ☁️ SoundCloud link import — paste a link, play it directly in the studio
  • 🎚️ Playback speed from 0.50× to 1.50×
  • 🌊 Professional reverb engine
  • 🎵 Real-time audio effects (EQ, compression, distortion)
  • 📊 Waveform visualization
  • 💾 Preset management
  • 💝 100% Free with optional support

Quick Start with Docker (Recommended)

Prerequisites

  • Docker with Docker Compose v2 (docker compose version)

Run

git clone https://github.com/anasfik/SlowedLab
cd SlowedLab

# First run (or after dependency / Dockerfile changes)
docker compose up --build -d

# Follow logs
docker compose logs -f

# Stop (keeps audio cache in backend/data)
docker compose down

Open:

Both services have healthchecks; docker compose ps should show healthy for each after ~1 minute (frontend needs the dev server compile on first boot).

If 4000/4001 are already taken on your machine, copy .env.example to .env and set FRONTEND_PORT / BACKEND_PORT to free host ports. .env is git-ignored.

Configuration

Variable Default Meaning
FRONTEND_PORT / BACKEND_PORT (.env) 4000 / 4001 Host ports published by compose; container ports are always 4000/4001
PORT (backend) 4001 API port inside the container
MAX_AUDIO_MINUTES 15 Max link-import duration
LINKIMPORT_CONCURRENCY 2 Parallel yt-dlp downloads
AUDIO_CACHE_MB 1024 Audio cache cap
AUDIO_CACHE_FILES 100 Max cached files
YTDLP_COOKIES_FILE auto Explicit cookie path override; otherwise backend/data/cookies.txt is auto-detected
YTDLP_PROXY (.env) unset Residential proxy for yt-dlp (resolve + download); health reports only configured:true/false, never the URL
BACKEND_PROXY_URL (frontend) http://backend:4001 Where the dev server forwards same-origin /api/* calls (docker service DNS; host npm start falls back to http://localhost:4001)

Live source mounts (backend/src, backend/tsconfig.json, frontend/src, frontend/public) mean local edits hot-reload inside the containers; dependency changes (package.json) need docker compose up --build.

The frontend never bakes in an API host: it always calls same-origin /api/*. Never set REACT_APP_API_URL — an absolute URL baked into the bundle breaks every visitor whose machine is not yours.

Downloaded audio persists in backend/data/audio-cache (host-mounted). cookies.txt is git-ignored — never commit it.

SoundCloud import notes

SoundCloud marks a minority of streams DRM-protected for third-party clients — those tracks can't be imported, and the app says so instead of hanging. If a public track fails to resolve, a Netscape cookies.txt exported from a logged-in browser tab and saved as backend/data/cookies.txt (git-ignored — never commit it) is auto-detected and retried with it. Confirm pickup with:

curl -s http://localhost:4001/api/health
# "linkImport":{"ytDlp":"yt-dlp","proxy":{"configured":false},"cookies":{"configured":true,...}}

Deploying (VPS)

  1. Clone the repo on the server and start the stack:

    docker compose up --build -d
    docker compose ps          # wait for both services to report healthy
  2. Point a domain at the server and put nginx in front. A ready-to-use config lives at deploy/nginx/slowedlab.app.conf (it proxies / to the app and /api/ to the API, adds caching/security headers and gzip, and leaves port 80 free for the ACME challenge):

    sudo cp deploy/nginx/security-headers.conf /etc/nginx/snippets/security-headers.conf
    sudo cp deploy/nginx/slowedlab.app.conf /etc/nginx/sites-available/slowedlab.app
    sudo ln -sf /etc/nginx/sites-available/slowedlab.app /etc/nginx/sites-enabled/
    # edit server_name + the two proxy_pass ports to match your .env
    sudo nginx -t && sudo systemctl reload nginx
  3. Issue the certificate (this also flips nginx to HTTPS and redirects port 80):

    sudo certbot --nginx -d your-domain.tld
  4. Confirm: https://your-domain.tld loads the app and https://your-domain.tld/api/health returns {"status":"ok"}.

Notes:

  • The frontend calls the API through same-origin /api/*, so changing the public URL or the host ports never requires a frontend rebuild.
  • Keep backend/data on a volume; set the MAX_* / cache caps above to bound disk use.
  • Certbot renews automatically; sudo certbot renew --dry-run verifies it.

Manual Setup (Development)

Prerequisites

  • Node.js 18+ and npm installed

Backend

cd backend
npm install
npm run dev        # ts-node, hot reload → http://localhost:4001

For a compiled run: npm run build && npm start (serves the same API from dist/ without ts-node).

Frontend (in a new terminal)

cd frontend
npm install
cp .env.local.example .env.local   # optional: PORT, OpenAI key
npm start

This starts the React dev server on http://localhost:3000 by default, or whatever PORT you set in .env.local. The dev server proxies /api/* to http://localhost:4001, so keep the backend running on that port.

Usage

  1. Open the app at http://localhost:4000
  2. Upload an audio file using the upload area (supports MP3, WAV, FLAC, OGG, AAC, and more)
  3. Apply effects:
    • ⚡ Speed: Slow the track down or push it faster. Pitch shifts with it, which is what gives the slowed sound its depth.
    • ✨ Reverb: Add spatial depth and ambient effects
    • EQ: Shape frequency response (bass, treble)
    • Compressor: Control dynamic range
    • Distortion: Add grit and aggression
  4. Preview in real-time with the interactive waveform viewer
  5. Manage presets using built-in effect presets or create custom ones
  6. Export your processed audio as a WAV file
  7. Report bugs using the 🐞 button for feedback and improvements

Link Import (SoundCloud)

Paste a SoundCloud link in the empty state or queue panel. The backend resolves metadata, mints a short-lived stream URL the browser fetches directly (fastest, no server bandwidth), and falls back to a server-side download with yt-dlp + ffmpeg MP3 conversion, cached under backend/data/audio-cache and fed into the normal playback pipeline. Spotify and YouTube links are rejected: Spotify offers no legal full-track download path, and YouTube blocks server-side downloads from datacenter IPs.

VM deploy notes (also see above):

  • The backend image ships yt-dlp, ffmpeg, and deno already.
  • Cap downloads with MAX_AUDIO_MINUTES (default 15), LINKIMPORT_CONCURRENCY (default 2), AUDIO_CACHE_MB (default 1024).

Tech Stack

  • Frontend: React 18 (Create React App), TypeScript, Web Audio API
  • Backend: Node.js, Express, TypeScript
  • Audio Processing: Web Audio API (100% client-side)
  • Containerization: Docker & Docker Compose
  • Styling: CSS3 with modern gradients and animations

Specifications

  • File Support: MP3, WAV, FLAC, OGG, AAC, and more
  • File Size Limit: 200MB per file
  • Processing: 100% client-side (your files never leave your browser)
  • Storage: Browser caching via IndexedDB for faster reloads
  • Error Handling: Comprehensive validation and user-friendly error messages
  • Real-time Performance: Sub-50ms effect processing
  • UI Responsiveness: Touch-friendly waveform interactions

Legal

Support

This project is 100% free. If you find it useful, consider supporting on Ko-fi ☕


Made with ❤️ for audio enthusiasts | SlowedLab - Elevate Your Audio Experience

About

An advanced real-time audio player supporting all effects (slow, reverb) that elevate your music/audio playing to next level

Topics

Resources

Stars

8 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages