# 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=`) - 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 Compose The easiest way to run the entire backend stack (PostgreSQL, Agent, Web Player, and gRPC Server) is using Docker Compose. ### Quick Start 1. **Prepare directories**: ```bash mkdir -p inbox storage ``` 2. **Start the services**: ```bash docker compose up -d ``` 3. **Check logs**: ```bash docker compose logs -f ``` The following services will be available: - **Web Player**: [http://localhost:8085](http://localhost:8085) - **Agent Admin UI**: [http://localhost:8090](http://localhost:8090) - **Metrics**: [http://localhost:9090/metrics](http://localhost:9090/metrics) > [!NOTE] > The Agent expects Ollama to be running. By default, it tries to connect to the host at `http://localhost:11434`. ### Reference Commands - **Start**: `docker compose up -d` - **Stop**: `docker compose stop` - **Stop and remove containers**: `docker compose down` - **Clear database and storage**: `docker compose down -v` ### Environment Variables To configure the Agent (especially for remote Ollama or private models) and database, create an `.env` file in the root directory: ```env # Database POSTGRES_PASSWORD=secure-password # LLM (Ollama) OLLAMA_URL=http://your-ollama-host:11434 OLLAMA_AUTH="Bearer your-token" # Server Security FURUMI_TOKEN=secure-server-token ``` For more options, refer to the [Configuration](#configuration) section. ## Docker Pre-built images are available on Docker Hub: ```bash docker pull /furumi-server docker pull /furumi-web-player docker pull /furumi-metadata-agent ``` ## Prometheus Metrics Available at `http:///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