Express microservice that computes lightweight DSP metrics (loudness, crest
factor, basic spectral/stereo heuristics) via ffmpeg filters and exposes them
through a single authenticated endpoint.
POST /analysisprotected byx-api-keyGET /healthprobeFfmpegAudioAnalysisServiceusesebur128+astatsfilters to extract LUFS, loudness range, true peak, crest factor, spectrum balance, and stereo width hints- Zod validation, ESLint/Prettier, Vitest coverage for service + router layers
src/
ββ app.ts # Express composition
ββ config/env.ts # zod-validated env loader
ββ index.ts # bootstrap entrypoint
ββ middleware/api-key-auth.ts # reusable middleware
ββ routes/analysis.ts # POST /analysis
ββ services/audio-analysis-service.ts
ββ types/analysis.ts # shared analysis schema
- Node.js β₯ 18
ffmpegavailable. Defaults toffmpeg-static, but you can override viaFFMPEG_PATH- The service reads audio files directly from disk (
pathin request body)
npm install
npm run devScripts: build, start, typecheck, lint, format, test, and
generate:api-key.
npm run generate:api-key # rotate AUDIO_ANALYSIS_API_KEY locally
cd ../api && npm run analysis:api-key # copy the key into api/.env| Variable | Description |
|---|---|
PORT |
HTTP port (default 4002) |
AUDIO_ANALYSIS_API_KEY |
Shared secret for x-api-key auth |
FFMPEG_PATH |
Optional override for the ffmpeg binary |
.env / .env.example carry the defaults.
curl -X POST http://localhost:4002/analysis \
-H 'Content-Type: application/json' \
-H 'x-api-key: super-secret-analysis-key' \
-d '{"path":"/tmp/test.wav"}'Response:
{
"loudness": {
"integratedLUFS": -14.3,
"truePeak": -0.8,
"loudnessRange": 4.1
},
"dynamics": { "crestFactor": 13.5 },
"spectrum": { "low": 0.3, "mids": 0.4, "highs": 0.3 },
"stereo": { "widthScore": 0.55 }
}| Status | Body | Reason |
|---|---|---|
| 400 | { "error": "Invalid request body" } |
Missing/empty path |
| 401 | { "error": "Unauthorized" } |
Missing or invalid x-api-key |
| 500 | { "error": "Failed to analyze audio" } |
ffmpeg errors or parsing failures |
A Dockerfile is provided for production deployment:
# Build the image
docker build -t audio-analysis-service .
# Run the container
docker run -p 4002:8080 \
-e PORT=8080 \
-e AUDIO_ANALYSIS_API_KEY=your-secret-key \
audio-analysis-serviceThe Dockerfile:
- Uses
node:22-slimbase image - Builds TypeScript from source
- Removes dev dependencies for smaller image
- Exposes port 8080
::: tip Bundled Binary
The service uses ffmpeg-static which includes the FFmpeg binary. No system FFmpeg installation required!
:::
For standalone repo deployment:
Railway will automatically detect the Dockerfile and build with FFmpeg included.
- Create new Railway project from this repo
- Railway detects Dockerfile automatically
- Set environment variable:
AUDIO_ANALYSIS_API_KEY - Railway builds and deploys
Service URL: Railway provides an internal URL like audio-analysis-service.railway.internal
Use this internal URL in your API service's ANALYSIS_SERVICE_URL environment variable.
See CODE OF CONDUCT, CONTRIBUTING, and SECURITY. Submit PRs with
npm run lint, npm run typecheck, and npm test passing.