Beatrove is a DJ-focused music library manager with an optional vinyl-ingest backend. The browser UI handles all day-to-day crate digging (filters, playlists, waveforms), while an opt-in FastAPI service lets you upload sleeve scans, run OCR, and normalize the metadata with a local LLM.
- Browser UI (
index.html,assets/js/) – Single-page app that loads tracklists, applies search/filter logic, and renders the DJ tooling. Usesnpm run serve(Python HTTP server) so no Node backend is required. - FastAPI Vinyl API (
server/app.py) – Handles/api/v1/recordsfor vinyl intake. Stores records inserver/vinyl.db(SQLite) with inline base64 cover images. - OCR Pipeline (
server/ocr/) –service.pyiterates provider strategies (providers.py). The default providers support HTTP-based OCR endpoints and local CLI commands; responses are flattened into plain text via shared utilities (utils.py) so downstream components receive uniform transcripts. - Metadata Enrichment (
server/metadata/) – Uses strategy objects to interpret OCR transcripts.LLMEnrichmentStrategyprompts your configured LLM endpoint to produce structured record data, whileHeuristicEnrichmentStrategyextracts keys/genres/catalog codes deterministically. Additional strategies can be added by implementingEnrichmentStrategy.apply. - SQLite Storage (
server/vinyl.db) – Persisted records with merged manual fields, LLM-enriched metadata, cover images, and raw OCR payloads for auditing.
- Node.js 20+
- Python 3.11+ (with
pip) - Git
- Clone the repo
git clone https://github.com/jcrouthamel/Beatrove.git cd Beatrove - Install front-end dependencies
npm install
- Create a Python virtual environment (recommended)
python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate
- Install backend requirements
pip install -r server/requirements.txt
- Run the static UI
This starts
npm run serve
python -m http.server 8000. Visithttp://localhost:8000to work with the client-only features (CSV import, filtering, playlists). - Run the FastAPI service (optional vinyl intake)
The UI expects the API at
uvicorn server.app:app --reload --port 9000
http://localhost:9000/api/v1. SetVITE_API_BASEor update your local config if needed. - Configure OCR/LLM (optional)
Set either
# HTTP OCR endpoint (path defaults to /v1/chat/completions if omitted) export VINYL_OCR_HTTP_URL="http://127.0.0.1:8089" export VINYL_OCR_MODEL="nanonets/Nanonets-OCR2-3B" # or provide a local CLI command that prints plain text to STDOUT # export VINYL_OCR_COMMAND="python /path/to/ocr.py --image {image}" export LLM_ENDPOINT="http://127.0.0.1:8088/v1/completions" export LLM_MODEL="gemma3" # optional tuning variables: LLM_TEMPERATURE, LLM_TOP_P, LLM_MAX_TOKENS, LLM_TIMEOUT_SECONDS
VINYL_OCR_HTTP_URLorVINYL_OCR_COMMAND(HTTP is tried first if both exist). The LLM strategy runs only whenLLM_ENDPOINTis defined.
make test– Run the Vitest suite (npm test)make python-test– Run Python unit tests (python -m unittest discover)npm run test:watch– Watch mode for the UI testsuvicorn server.app:app --reload– Start the FastAPI vinyl API
- OCR still returns JSON – Ensure your OCR provider obeys the prompt or add a custom adapter in
server/ocr/providers.py. - LLM not invoked – Confirm
LLM_ENDPOINTandLLM_MODELare set. Without them, only heuristics run. - SQLite locked errors – Stop other FastAPI instances or delete
server/vinyl.db(after backing up) before restarting.