Minimal demo for audio upload pipeline that:
- rejects exact duplicate files
- detects highly similar audio after async fingerprinting
- exposes warning history and realtime warning events
- Frontend: Next.js app for upload, result state, warning tables, and SSE live updates.
- Backend API: Express service for upload handling, dedup checks, warning APIs, and SSE subscriptions.
- Database: PostgreSQL stores audio metadata, upload attempts, and similarity warnings.
- Queue + Worker: BullMQ with Redis processes fingerprint jobs asynchronously.
- Object Storage: Supabase buckets (
temp-uploads,audio-files) store uploaded audio files. - Fingerprinting:
fpcalc(Chromaprint) produces perceptual audio fingerprints.
-
Exact duplicate detection: SHA-256 is computed from file content and stored as
content_hash.
audio_files.content_hashis unique, and insert usesON CONFLICT DO NOTHING, so exact duplicates are rejected safely even under concurrent uploads. -
Similarity detection: For accepted uploads, a BullMQ job is queued.
The worker runsfpcalcand compares the new perceptual fingerprint against existing processed files. -
Similarity scoring: Fingerprints are base64-decoded and compared bit-by-bit with Hamming distance.
Formula:similarityPercent = ((maxBits - distance) / maxBits) * 100
withmaxBits = max(fingerprintA.length, fingerprintB.length) * 6.
Warning threshold:>= 70%. -
Warning output: Similar matches are saved in
similarity_warnings, returned by REST endpoints, and pushed in realtime via SSE (/upload/:audioId/subscribe). -
Further possible improvement: Can add endpoint to delete a similar file based on it's ID from warnings or download any of the files uploaded but so far since the assignment was only focused on duplication detection this is the minimal functional version of the requirements.
-
Overall:
-
SHA-256 hashing for exact duplicate detection generates a deterministic, collision-resistant fingerprint of the file’s binary content, ensuring identical files (regardless of filename) are detected reliably and atomically enforced via a database UNIQUE constraint.
-
For content-level similarity across different encodings (e.g., FLAC vs MP3), using Chromaprint acoustic fingerprinting, which analyzes the audio’s frequency characteristics rather than metadata or raw bytes, allowing detection of perceptually identical audio even when file formats or compression differ.
-
POST /uploadreceives file (Multer) and validates MIME type.- SHA-256 content hash is computed.
- File is uploaded to Supabase
temp-uploads. - Insert into
audio_files: If hash conflict occurs, upload is marked duplicate and returns409. - If unique, file is moved to
audio-filesand fingerprint job is queued. - Worker downloads file, runs
fpcalc, storesperceptual_hashand duration. - Similarity check runs, warnings are stored, SSE events are emitted.
- API and worker run in one Node process for simpler local setup.
Trade-off: convenient for assignment/demo; less scalable than separate deployable services. - Similarity check returns after first match above threshold.
Trade-off: faster and simpler; does not list every possible similar file for one upload. - SSE subscribers are tracked in-memory per server instance.
Trade-off: lightweight for single-instance demo; not shared across multiple backend instances. - Upload validation is MIME-based.
Trade-off: minimal and fast; deeper binary/content validation is possible if needed.
GET /healthPOST /upload(multipart/form-data, field name:audio)GET /upload/warningsGET /upload/:audioId/warningsGET /upload/:audioId/subscribe(SSE)
- Node.js 22+
- PostgreSQL
- Redis
- Supabase project with buckets:
temp-uploadsaudio-files
backend/fpcalc.exe(already in repo)
PORT=5000
NODE_ENV=development
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=postgres
DB_NAME=audio_dedup
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/audio_dedup
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
SUPABASE_URL=https://YOUR_PROJECT_ID.supabase.co
SUPABASE_SERVICE_ROLE=YOUR_SUPABASE_SERVICE_ROLE_KEYNEXT_PUBLIC_API_BASE_URL=http://localhost:5000From backend/:
docker compose up -dcd backend
npm install
npm run devBackend startup initializes database/schema and starts API + fingerprint worker.
cd frontend
npm install
npm run dev

