nexstream-api / backend /README.md
circleci
deploy beb5a90
dae0a8c
|
Raw
History Blame Contribute Delete
6.3 kB
# Backend
the Express 5 + TypeScript service that powers stream resolution, muxing, the Spotify resolution race, and the Remix Lab API. for the project overview see [`../../README.md`](../../README.md). for self-hosting see [`../../docs/run-an-instance.md`](../../docs/run-an-instance.md).
## Layout
```text
backend/
β”œβ”€β”€ src/
β”‚ β”œβ”€β”€ app.ts # Express setup, middleware, route wiring, lifecycle
β”‚ β”œβ”€β”€ instrument.ts # Sentry instrumentation β€” must load before app.ts
β”‚ β”œβ”€β”€ controllers/
β”‚ β”‚ β”œβ”€β”€ video.controller.ts # /info, /convert, /stream-urls handlers
β”‚ β”‚ └── keychanger.controller.ts # pitch-shift / key-change uploads
β”‚ β”œβ”€β”€ routes/
β”‚ β”‚ β”œβ”€β”€ video.routes.ts # core video / stream endpoints
β”‚ β”‚ β”œβ”€β”€ remix.routes.ts # Remix Lab kernel proxy + results
β”‚ β”‚ └── keychanger.routes.ts # key-changer route
β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”œβ”€β”€ spotify/ # ISRC race, Turso registry, AI query synthesis
β”‚ β”‚ β”œβ”€β”€ ytdlp/ # yt-dlp integration: streamer, info, turbo-mux, config
β”‚ β”‚ β”œβ”€β”€ extractors/ # pure-JS extractors (YouTube/FB/IG/TikTok/SoundCloud)
β”‚ β”‚ β”œβ”€β”€ extract.service.ts # generic metadata extractor
β”‚ β”‚ β”œβ”€β”€ seeder.service.ts # background catalog seeder
β”‚ β”‚ β”œβ”€β”€ social.service.ts # metascraper-based social-link metadata
β”‚ β”‚ β”œβ”€β”€ ug-grounding.service.ts # Ultimate Guitar tab lookup
β”‚ β”‚ β”œβ”€β”€ spotify.service.ts # Spotify facade
β”‚ β”‚ └── ytdlp.service.ts # yt-dlp facade
β”‚ β”œβ”€β”€ utils/
β”‚ β”‚ β”œβ”€β”€ api/ # controller, response helpers
β”‚ β”‚ β”œβ”€β”€ infra/ # db (Turso), logger, queue, redis, trace
β”‚ β”‚ β”œβ”€β”€ media/ # format, fsm, metadata, spotify, stream, video
β”‚ β”‚ └── network/ # auth, cipher, cookie, proxy, secrets, security, sse, validation
β”‚ └── types/ # shared TS types
β”œβ”€β”€ tests/ # Vitest suites + e2e helpers
β”œβ”€β”€ scripts/ # test orchestration, benchmarks, Termux shim
└── Dockerfile # container build (node:22-slim base)
```
## Routes
`video.routes.ts`:
| Method | Path | Purpose |
| ------ | -------------------- | --------------------------------------- |
| `GET` | `/events` | SSE telemetry stream. |
| `GET` | `/info` | resolve a URL β†’ metadata + format list. |
| `GET` | `/stream-urls` | refresh CDN URLs for a known video. |
| `POST` | `/telemetry` | frontend β†’ backend telemetry ingest. |
| `ALL` | `/convert` | stream / download a chosen format. |
| `GET` | `/proxy` | authenticated stream proxy. |
| `GET` | `/seed-intelligence` | trigger the background catalog seeder. |
`remix.routes.ts` proxies the Python Remix Lab kernel and serves stem/chord/beat results. `keychanger.routes.ts` handles pitch-shift uploads. `/convert` and `/proxy` are gated by `concurrencyGuard(2)` (`utils/network/security.util.ts`) to keep memory bounded on Termux and free-tier hosts.
response shapes for `/info` and `/convert` are documented in [`../../docs/api.md`](../../docs/api.md).
## Environment
configure via `web/backend/.env`. the full reference is in [`../../docs/env-variables.md`](../../docs/env-variables.md). the backend boots without most of these β€” they enable optional features and degrade gracefully when unset. minimum to get something useful:
- `REDIS_URL` β€” Redis for the metadata cache and BullMQ job queue (defaults to `redis://127.0.0.1:6379`).
- `GEMINI_API_KEY` and/or `GROQ_API_KEY` β€” at least one for the AI fallback in Spotify resolution.
- `SPOTIFY_CLIENT_ID` + `SPOTIFY_CLIENT_SECRET` β€” Spotify Web API for ISRC and metadata.
- `TURSO_URL` + `TURSO_AUTH_TOKEN` β€” global edge registry. unset is fine for local dev (falls back to an in-memory mock).
- `COOKIES_URL` β€” remote `yt-dlp` cookie sync. improves YouTube reliability.
- `API_ONLY=true` β€” disable serving the bundled `frontend/dist` (split deployments).
## Running
```bash
npm install
npm run dev # tsc + node, listens on :5000 (or $PORT)
```
other scripts:
- `npm run build` β€” TypeScript compile to `dist/`.
- `npm test` β€” full Vitest suite (sequential, Termux-friendly).
- `npm run test:fast` β€” core regression tests only.
- `npm run test:lite` β€” node `--test` lite suite (no transpile).
- `npm run lint` β€” ESLint on changed files (`npm run lint:all` for the whole package).
- `npm run bench:convert` β€” convert-pipeline benchmark.
## Requirements
- Node.js β‰₯ 22 β€” matches the Dockerfile and the project root.
- `yt-dlp` and `ffmpeg` on `PATH`. `yt-dlp` is the fallback for sources without a native extractor; `ffmpeg` 7.x or 8.x handles muxing and audio transcoding.
- Redis. an in-process mock is used in tests when none is reachable.
## Notes
- **YouTube player clients**: `services/ytdlp/turbo-mux.ts` passes `--extractor-args youtube:player-client=...` to obtain DASH manifests and bypass the 360p limit on the default web client. the client list is chosen per request based on the requested format.
- **Concurrency**: `concurrencyGuard(limit)` (`utils/network/security.util.ts`) caps in-flight downloads at `limit=2` per process to prevent OOM on small hosts.
- **Cookie sync**: `utils/network/cookie.util.ts` pulls `youtube_cookies.txt` and `facebook_cookies.txt` from `COOKIES_URL` at boot when the variable is set.
- **MP3 transcoding**: `services/ytdlp/streamer.ts` pipes raw audio through `ffmpeg -vn -ab 192k -f mp3 pipe:1` straight to the client β€” no temp files.
- **MP4 finalization**: `-movflags +faststart` is set on finalized MP4 downloads so playback can start before the file finishes.
- **SSE**: `/events` is the canonical telemetry channel. resolvers, downloaders, and the seeder push progress through `utils/network/sse.util.ts`.
before putting an instance on the public internet, read [`../../docs/protect-an-instance.md`](../../docs/protect-an-instance.md).