197 lines
7.8 KiB
Markdown
197 lines
7.8 KiB
Markdown
# Furumi-ng
|
||
|
||
A music platform consisting of a remote filesystem, an AI-powered metadata agent, and a database-backed web player.
|
||
|
||
## Components
|
||
|
||
```
|
||
furumi-server gRPC remote filesystem with TLS and auth
|
||
furumi-client-core Cross-platform gRPC client library
|
||
furumi-mount-linux FUSE mount for Linux
|
||
furumi-mount-macos NFS mount for macOS
|
||
furumi-agent AI metadata agent (LLM-powered ingest pipeline + admin UI)
|
||
furumi-web-player Database-backed web music player with OIDC auth
|
||
```
|
||
|
||
### furumi-server
|
||
|
||
Exposes a local directory over encrypted gRPC. Supports Bearer token auth, OIDC/SSO, Prometheus metrics, and a built-in web player for direct filesystem browsing.
|
||
|
||
### furumi-agent
|
||
|
||
Background service that watches an inbox folder for new music files, extracts metadata, normalizes it using a local LLM (via Ollama), and stores canonical metadata in PostgreSQL. Features:
|
||
|
||
- Automatic metadata extraction (Symphonia) and file path parsing
|
||
- LLM normalization with RAG (queries existing artists/albums in DB for consistency)
|
||
- Featured artist detection (`feat.`, `п.у.`, `&`, etc.)
|
||
- Album cover image processing
|
||
- Auto-approval for high-confidence results, review queue for uncertain ones
|
||
- Admin web UI with batch operations, inline editing, album grouping
|
||
- Organized file storage (`Artist/Album/Track.ext`)
|
||
- Configurable system prompt (built-in default or external file)
|
||
- Database migrations via sqlx
|
||
|
||
### furumi-web-player
|
||
|
||
Web music player that reads exclusively from the database populated by the agent. Features:
|
||
|
||
- Browse by Artists, Albums, Tracks
|
||
- Full-text search across the library
|
||
- Audio streaming with HTTP Range request support
|
||
- Album cover art (from DB or embedded in audio files)
|
||
- Queue management with shuffle, repeat, drag-and-drop reorder
|
||
- Media Session API (hardware controls, lock screen integration)
|
||
- OIDC/SSO authentication
|
||
- Deep linking (`?t=<track_slug>`)
|
||
- Relative URL paths (works behind any reverse proxy prefix)
|
||
|
||
## Architecture
|
||
|
||
```
|
||
┌─────────────────┐
|
||
│ Ollama (LLM) │
|
||
└────────┬────────┘
|
||
│
|
||
┌──────────┐ ┌────────────┴────────────┐ ┌──────────────────┐
|
||
│ Inbox │───→│ furumi-agent │───→│ Storage (files) │
|
||
│ folder │ │ (ingest + admin UI) │ └────────┬─────────┘
|
||
└──────────┘ └────────────┬────────────┘ │
|
||
│ │
|
||
┌──────┴──────┐ ┌───────┴────────┐
|
||
│ PostgreSQL │←──────────│ furumi-web- │
|
||
│ (metadata) │ │ player │
|
||
└─────────────┘ └────────────────┘
|
||
```
|
||
|
||
## Quick Start
|
||
|
||
### Remote Filesystem (FUSE/NFS mount)
|
||
|
||
```bash
|
||
cargo build --release --workspace
|
||
|
||
# Server
|
||
./target/release/furumi-server \
|
||
--root /path/to/media \
|
||
--token mysecrettoken
|
||
|
||
# Client (Linux)
|
||
./target/release/furumi-mount-linux \
|
||
--server server-ip:50051 \
|
||
--token mysecrettoken \
|
||
--mount /mnt/remote
|
||
```
|
||
|
||
### Music Platform (Agent + Player)
|
||
|
||
Requires PostgreSQL with `pg_trgm` extension and Ollama for LLM.
|
||
|
||
```bash
|
||
# 1. Start PostgreSQL
|
||
docker run -d --name furumi-pg \
|
||
-e POSTGRES_DB=furumi -e POSTGRES_USER=furumi -e POSTGRES_PASSWORD=furumi \
|
||
-p 5432:5432 postgres:17
|
||
|
||
# 2. Create directories
|
||
mkdir -p /music/inbox /music/storage
|
||
|
||
# 3. Start the agent (runs migrations automatically)
|
||
./target/release/furumi-agent \
|
||
--inbox-dir /music/inbox \
|
||
--storage-dir /music/storage \
|
||
--database-url "postgres://furumi:furumi@localhost:5432/furumi" \
|
||
--ollama-url "http://localhost:11434" \
|
||
--ollama-model "qwen3:14b"
|
||
|
||
# 4. Start the web player
|
||
./target/release/furumi-web-player \
|
||
--storage-dir /music/storage \
|
||
--database-url "postgres://furumi:furumi@localhost:5432/furumi"
|
||
|
||
# 5. Drop music files into /music/inbox — agent processes them automatically
|
||
# 6. Open http://localhost:8080 to play music
|
||
# 7. Open http://localhost:8090 for the agent admin UI
|
||
```
|
||
|
||
## Configuration
|
||
|
||
All options can be set via CLI flags or environment variables.
|
||
|
||
### Server
|
||
|
||
| Flag | Env | Default | Description |
|
||
|------|-----|---------|-------------|
|
||
| `--bind` | `FURUMI_BIND` | `0.0.0.0:50051` | gRPC listen address |
|
||
| `--root` | `FURUMI_ROOT` | `.` | Directory to expose |
|
||
| `--token` | `FURUMI_TOKEN` | *(empty, auth off)* | Bearer token |
|
||
| `--metrics-bind` | `FURUMI_METRICS_BIND` | `0.0.0.0:9090` | Prometheus endpoint |
|
||
| `--web-bind` | `FURUMI_WEB_BIND` | `0.0.0.0:8080` | Built-in web player |
|
||
| `--no-web` | — | `false` | Disable built-in web player |
|
||
| `--no-tls` | — | `false` | Disable TLS |
|
||
|
||
### Client (Linux / macOS)
|
||
|
||
| Flag | Env | Default | Description |
|
||
|------|-----|---------|-------------|
|
||
| `--server` | `FURUMI_SERVER` | `0.0.0.0:50051` | Server address |
|
||
| `--token` | `FURUMI_TOKEN` | *(empty)* | Bearer token |
|
||
| `--mount` | `FURUMI_MOUNT` | — | Mount point directory |
|
||
| `--no-tls` | — | `false` | Disable TLS |
|
||
|
||
### Metadata Agent
|
||
|
||
| Flag | Env | Default | Description |
|
||
|------|-----|---------|-------------|
|
||
| `--bind` | `FURUMI_AGENT_BIND` | `0.0.0.0:8090` | Admin UI address |
|
||
| `--inbox-dir` | `FURUMI_AGENT_INBOX_DIR` | — | Watch folder for new files |
|
||
| `--storage-dir` | `FURUMI_AGENT_STORAGE_DIR` | — | Permanent storage folder |
|
||
| `--database-url` | `FURUMI_AGENT_DATABASE_URL` | — | PostgreSQL URL |
|
||
| `--ollama-url` | `FURUMI_AGENT_OLLAMA_URL` | `http://localhost:11434` | Ollama API endpoint |
|
||
| `--ollama-model` | `FURUMI_AGENT_OLLAMA_MODEL` | `qwen3:14b` | LLM model name |
|
||
| `--poll-interval-secs` | `FURUMI_AGENT_POLL_INTERVAL_SECS` | `30` | Inbox scan interval |
|
||
| `--confidence-threshold` | `FURUMI_AGENT_CONFIDENCE_THRESHOLD` | `0.85` | Auto-approve threshold |
|
||
| `--system-prompt-file` | `FURUMI_AGENT_SYSTEM_PROMPT_FILE` | *(built-in)* | Custom LLM prompt |
|
||
|
||
### Web Player
|
||
|
||
| Flag | Env | Default | Description |
|
||
|------|-----|---------|-------------|
|
||
| `--bind` | `FURUMI_PLAYER_BIND` | `0.0.0.0:8080` | Player address |
|
||
| `--database-url` | `FURUMI_PLAYER_DATABASE_URL` | — | PostgreSQL URL |
|
||
| `--storage-dir` | `FURUMI_PLAYER_STORAGE_DIR` | — | Storage folder (for streaming) |
|
||
| `--oidc-issuer-url` | `FURUMI_PLAYER_OIDC_ISSUER_URL` | *(disabled)* | OIDC issuer |
|
||
| `--oidc-client-id` | `FURUMI_PLAYER_OIDC_CLIENT_ID` | — | OIDC client ID |
|
||
| `--oidc-client-secret` | `FURUMI_PLAYER_OIDC_CLIENT_SECRET` | — | OIDC client secret |
|
||
| `--oidc-redirect-url` | `FURUMI_PLAYER_OIDC_REDIRECT_URL` | — | OIDC redirect URL |
|
||
| `--oidc-session-secret` | `FURUMI_PLAYER_OIDC_SESSION_SECRET` | *(random)* | Session HMAC secret |
|
||
|
||
## Docker
|
||
|
||
Pre-built images are available on Docker Hub:
|
||
|
||
```bash
|
||
docker pull <user>/furumi-server
|
||
docker pull <user>/furumi-web-player
|
||
docker pull <user>/furumi-metadata-agent
|
||
```
|
||
|
||
## Prometheus Metrics
|
||
|
||
Available at `http://<metrics-bind>/metrics` (server only):
|
||
|
||
- `furumi_grpc_requests_total` — request count by method and status
|
||
- `furumi_grpc_request_duration_seconds` — request latency histogram
|
||
- `furumi_bytes_read_total` — total bytes streamed
|
||
- `furumi_active_streams` — current streaming connections
|
||
|
||
## Requirements
|
||
|
||
- Rust 2024 edition
|
||
- PostgreSQL 14+ with `pg_trgm` extension (for agent and web player)
|
||
- Ollama with a local LLM (for agent)
|
||
- Linux with `libfuse3-dev` (for FUSE client only)
|
||
|
||
## License
|
||
|
||
MIT
|