# 🎡 Kithara Studio A self-hosted webapp for generating, playing, and managing music clips using Google's Lyria music generation models. Built by [Kagamine Rin](https://rin.captcouch.xyz) & Ryan. > **⚠️ Under Active Development** > Kithara Studio is pre-1.0 software under rapid development. Features change, APIs shift, and things break. We use it daily and it works for us, but expect rough edges. Issues and feedback are welcome β€” PRs are welcome too if you're into that sort of thing. --- ## Features - **Music Generation** β€” Generate clips from text prompts using Google's Lyria models (currently Lyria 3 Clip Preview) - **Structured Prompts** β€” Build prompts with genre, mood, instrumentation, and description fields - **Maestro Mode** β€” Visual playback animation with cycling musical notes - **Audio Player** β€” Stream MP3 playback with waveform visualization - **Metadata & ID3 Tags** β€” Auto-detect BPM and key; set artist, album, genre, and comment; embed cover art and tags on download - **Artwork Generation** β€” AI-generated cover art via Gemini - **Favorites** β€” Heart clips to pin them (DB-backed, multi-user ready) - **Dark Theme** β€” Purpose-built dark UI for late-night production sessions - **Multi-User Auth** β€” Optional JWT auth with invite codes (single-user mode by default) - **Admin CLI** β€” `kithara-admin` for user management from the command line - **Docker Ready** β€” Full Docker Compose setup with Nginx reverse proxy --- ## Quick Start ### Docker (Recommended) ```bash # Clone and configure git clone https://gitea.captcouch.xyz/Public/kithara-studio.git cd kithara-studio cp .env.example .env # Edit .env β€” set your LYRIA_API_KEY # Launch docker compose up -d --build # Open http://localhost:3100 ``` ### Manual (Development) ```bash # Backend cd backend python -m venv .venv source .venv/bin/activate pip install -r requirements.txt cd src uvicorn main:app --reload --port 8000 # Frontend (new terminal) cd frontend npm install npm run dev # Open http://localhost:5173 ``` --- ## Configuration All configuration is via environment variables (`.env` file): | Variable | Default | Description | |----------|---------|-------------| | `LYRIA_API_KEY` | *(required)* | Google Lyria API key | | `LYRIA_DEFAULT_MODEL` | `lyria-3-clip-preview` | Default Lyria model | | `KITHARA_MODE` | `single` | `single` = no auth, `multi` = JWT auth required | | `KITHARA_ADMIN_USER` | `admin` | Bootstrap admin username (multi mode) | | `KITHARA_ADMIN_PASS` | `admin` | Bootstrap admin password (multi mode) | | `DEFAULT_ID3_ARTIST` | `Kagamine Rin` | Default artist tag | | `DEFAULT_ID3_ALBUM` | `Kithara Studio` | Default album tag | | `DEFAULT_ID3_GENRE` | `Hardcore Techno` | Default genre tag | | `TZ` | `America/New_York` | Timezone | ### Authentication Modes **Single-user mode** (`KITHARA_MODE=single`) β€” No login required. All clips belong to a default user. Best for personal use or trusted networks. **Multi-user mode** (`KITHARA_MODE=multi`) β€” JWT authentication required. Users register with invite codes. Admin user is bootstrapped on first startup. Best for shared deployments. --- ## Admin CLI Manage users and invite codes from the host: ```bash # List users python3 kithara-admin list-users # Create a user python3 kithara-admin create-user alice --password secret --role user # Create an invite code python3 kithara-admin create-invite python3 kithara-admin create-invite --max-uses 5 # List invite codes python3 kithara-admin list-invites # Change role python3 kithara-admin change-role alice admin # Reset password python3 kithara-admin reset-password alice newpass123 # Delete user (requires --confirm) python3 kithara-admin delete-user alice --confirm # Revoke invite code python3 kithara-admin revoke-invite CODE_HERE ``` > **Note:** The CLI reads `data/kithara.db` directly. If running in Docker, ensure the database file is writable by your host user, or run the CLI with appropriate permissions. --- ## API | Endpoint | Method | Description | |----------|--------|-------------| | `GET /api/health` | β€” | Health check (includes mode: single/multi) | | **Clips** | | | | `POST /api/generate` | β€” | Start clip generation | | `GET /api/clips` | β€” | List clips | | `GET /api/clips/{id}` | β€” | Clip metadata | | `GET /api/clips/{id}/audio` | β€” | Stream MP3 | | `PATCH /api/clips/{id}` | β€” | Update clip (title, metadata) | | `DELETE /api/clips/{id}` | β€” | Delete clip | | `POST /api/clips/{id}/favorite` | β€” | Toggle favorite | | **Artwork** | | | | `PATCH /api/clips/{id}/artwork` | β€” | Upload cover art | | `DELETE /api/clips/{id}/artwork` | β€” | Remove cover art | | `POST /api/clips/{id}/generate-artwork` | β€” | AI-generate cover art | | **Analysis** | | | | `GET /api/clips/{id}/analysis` | β€” | BPM and key detection | | **Auth** (multi mode) | | | | `POST /api/auth/login` | β€” | Login (returns JWT) | | `POST /api/auth/register` | β€” | Register (requires invite code) | | `GET /api/auth/me` | β€” | Current user info | | `PUT /api/auth/api-key` | β€” | Set per-user Lyria API key | | **Admin** (multi mode) | | | | `GET /admin/users` | β€” | List users | | `POST /admin/users` | β€” | Create user | | `DELETE /admin/users/{id}` | β€” | Delete user | | `PUT /admin/users/{id}/role` | β€” | Change user role | | `POST /admin/invites` | β€” | Create invite code | | `GET /admin/invites` | β€” | List invite codes | | `DELETE /admin/invites/{code}` | β€” | Revoke invite code | --- ## Architecture ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Nginx │────▢│ FastAPI │────▢│ SQLite β”‚ β”‚ (reverse β”‚ β”‚ Backend β”‚ β”‚ (data/) β”‚ β”‚ proxy) β”‚ β”‚ :8000 β”‚ β”‚ β”‚ β”‚ :3000 β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β” β”‚ β”‚ Lyria β”‚ β”‚ β”‚ API β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β” β”‚ React + β”‚ β”‚ Vite + TS β”‚ β”‚ Tailwind β”‚ β”‚ (SPA) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` - **Backend**: FastAPI (Python) β€” async API client for Google's Lyria models, SQLite metadata, file storage, JWT auth - **Frontend**: React + Vite + TypeScript + Tailwind β€” dark theme SPA with audio player and waveform visualization - **Storage**: SQLite for clip metadata + user data, local filesystem for MP3 files and cover art - **Auth**: JWT tokens (multi-user mode), bcrypt password hashing, invite-based registration --- ## Models | Version | Model | Duration | Status | |---------|-------|----------|--------| | v0.1 | Lyria 3 Clip Preview | ~30s | βœ… Active | | v0.2 | Lyria 3 Pro | ~3min | βœ… Active | | v0.3 | Lyria RealTime | Streaming | πŸ”œ Planned | --- ## Roadmap This is Phase 1 of a multi-phase roadmap: - [x] **Phase 1** β€” Users & Auth, `KITHARA_MODE` switch, admin CLI - [ ] **Phase 2** β€” Data isolation (per-user clip scoping) - [ ] **Phase 3** β€” Per-user Lyria API keys (BYOK) - [ ] **Phase 4** β€” Community gallery (sharing, discovery) - [ ] **Phase 5** β€” Remix (fork clips into new generations) - [ ] **Phase 6** β€” Email notifications (optional) --- ## Development ```bash # Run tests (requires librosa, librosa dependencies) cd backend pip install -r requirements.txt pytest tests/ -v # Type check frontend cd frontend npx tsc --noEmit ``` --- ## License MIT β€” Hardcore will never die. 🎡