Files
NovaSonic/README.md
T
HoneyandClaude Sonnet 4.6 f1bdd811ca chore: remove squid.wtf (Qobuz) backend — yt-dlp only
Deletes backend/lib/squid.js; strips all references from downloader.js,
config.js, novasonic-server.js, docker-compose.yml, .env.example, README,
and CHANGELOG. Default DOWNLOAD_BACKEND is now ytdlp.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 20:59:30 +02:00

215 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NovaSonic
A self-hosted music streaming PWA and Android app for Navidrome / Subsonic-compatible servers.
Built with Vite + vanilla ES modules (web) and Jetpack Compose + Media3/ExoPlayer (Android).
---
## Features
### Music Library
- Stream music from your Navidrome / Subsonic library
- Browse artists, albums, playlists, starred tracks, genres, and random picks
- Search across songs, albums, and artists
- Star and context menu on every song row
- Play count display (optional)
### Lyrics
- Synced and plain lyrics via lrclib.net, auto-fetched per track
- Fallback chain: exact match → no-duration match → fuzzy artist+title search → title-only search
- In-memory cache per session
### Artist Pages
- Hero card with artist photo and blurred background
- Bio, similar artists, top songs from Last.fm
- Concert events via Ticketmaster
- Albums cross-referenced against iTunes catalog — shows downloaded vs. missing tracks
- Artist cards with images in search results
### Playback
- Queue with shuffle, repeat (all / one), and radio mode (endless similar songs)
- Now Playing overlay with synced lyrics, queue view, star, and multi-artist links
- Gapless-style playback — next track pre-buffered before current track ends
- Lock screen / notification media controls
- Scrobbling to Navidrome (configurable delay)
### Discovery
- iTunes / Last.fm — charts, global search, 30-second previews, similar artists
- Song Importer — paste a Spotify, YouTube, YouTube Music, or SoundCloud link to download
### Downloads
- Download tracks, albums, or entire artists from YouTube Music / SoundCloud / Spotify via yt-dlp
- iTunes metadata enrichment — album art, year, track number, genre
- Duplicate detection, standard folder/filename structure
### Metadata Editor
- Edit tags (title, artist, album, genre, year, track, disc, cover art)
- File renamed and moved automatically; Navidrome rescan triggered on save
### Playlists
- Create, rename, and delete playlists
- Add tracks via "Add to Playlist" context menu
- Remove tracks from a playlist (edit mode on Android; inline on Web)
- Cover image upload (Web + Android)
### Audiobookshelf Integration
- Browse libraries and audiobooks on both Web and Android
- Stream audiobooks with chapter-by-chapter navigation
- Playback speed control (0.5× – 2.0×)
- Sleep timer
- Progress sync — current position saved back to ABS server every 30 s
- Chapter track mode — progress bar shows current chapter length instead of full book (toggle in Settings)
- Tab/section hidden until ABS is configured in Settings
### App — Web PWA
- Installable on Android / iOS / desktop
- Multiple color themes, German UI
### App — Android (native Jetpack Compose)
- Media3 / ExoPlayer backend
- OS notification with playback controls
- ABS audiobook notification: chapter name shown as title, book title as artist; extra buttons — Kapitel zurück | 30s zurück | Play/Pause | 30s vor | Kapitel vor (compact + expanded)
- Last played song shown in mini player bar on restart; tap to resume
- Full playlist management: create, rename (with description), delete, remove tracks, cover upload
---
## Project Structure
```
NovaSonic/
├── src/
│ ├── player/
│ │ ├── player.js # Playback, queue, transport, media session, preload
│ │ └── nowplaying.js # Now Playing overlay + synced lyrics
│ ├── views/
│ │ ├── detail.js # Artist / album detail pages
│ │ ├── views.js # Navigation, page loaders, search
│ │ ├── events.js # Ticketmaster concert events
│ │ ├── home.js # Home page
│ │ ├── search.js # Search, artist/album navigation
│ │ ├── playlists.js # Playlist management
│ │ ├── spotify.js # Spotify importer
│ │ ├── youtube.js # YouTube importer
│ │ ├── soundcloud.js # SoundCloud importer
│ │ ├── navigation.js # Client-side router
│ │ └── abs.js # Audiobookshelf integration
│ ├── ui/
│ │ ├── ui.js # Modals, sidebar, context menu
│ │ ├── components.js # Song rows, cards, shared UI
│ │ ├── downloads.js # Download modal + job tracker
│ │ ├── metadata.js # Metadata editor
│ │ ├── modals.js # Song info, events modals
│ │ ├── notify.js # Toast notifications
│ │ └── settings.js # Settings page
│ ├── state.js # Shared mutable state (S object)
│ ├── utils.js # Helpers (md5, esc, formatDur, toast)
│ ├── api.js # Subsonic API, iTunes API, cover art
│ └── main.js # App init, audio wiring, window globals
├── backend/
│ ├── novasonic-server.js # Express API: downloads, metadata, events proxy, ABS proxy
│ └── lib/
│ ├── config.js # Env var → config object
│ ├── jobs.js # In-memory download job store
│ ├── metadata.js # iTunes lookup, artwork, filename helpers
│ ├── ytdlp.js # yt-dlp download + ffmpeg metadata embedding
│ ├── downloader.js # Unified downloadTrack / downloadAlbumTracks
│ └── romaji.js # Japanese → romaji search index
├── android/ # Native Android app (Jetpack Compose + Media3)
│ └── app/src/main/kotlin/com/novasonic/app/
│ ├── api/ # SubsonicClient, AbsClient, LrcLibClient, ItunesClient
│ ├── data/ # PrefsStore (DataStore), MusicRepository
│ ├── player/ # PlayerController, MusicService (Media3)
│ ├── ui/
│ │ ├── screen/ # HomeScreen, NowPlayingScreen, AbsScreen, SettingsScreen, …
│ │ ├── component/ # MiniPlayer, SongRow, SongContextSheet, …
│ │ └── theme/ # Color, Type, Theme
│ └── viewmodel/ # ViewModel per screen
├── public/
│ ├── sw.js # Service worker
│ ├── manifest.json # PWA manifest
│ └── config.js # Runtime config (generated by Docker entrypoint)
├── index.html
├── styles.css
├── vite.config.js
├── Dockerfile
├── docker-compose.yml
├── nginx.conf
└── docker-entrypoint.sh # Injects NAVIDROME_URL / BACKEND_URL at runtime
```
---
## Setup
### 1. Clone and configure
```bash
git clone <repo>
cd NovaSonic
cp .env.example .env
```
Edit `.env`:
```env
NAVIDROME_URL=https://music.yourdomain.com
BACKEND_URL=https://novasonic-api.yourdomain.com
MUSIC_PATH=/srv/navidrome/music
AUDIO_FMT=mp3 # mp3 | flac | opus | best
AUDIO_QUALITY=0 # 0 = best (yt-dlp)
MAX_PARALLEL=2
TICKETMASTER_API_KEY= # optional — free key from developer.ticketmaster.com
```
### 2. Start
```bash
docker compose up -d
```
Frontend on port 8080, backend on port 3700. Route both through your reverse proxy.
### 3. First launch
1. Enter your Navidrome server URL, username, and password
2. Optionally add a Last.fm API key in Settings for bios and recommendations
3. Optionally connect Audiobookshelf in Settings
4. Optionally add the NovaSonic backend URL in Settings to enable downloads
---
## Environment Variables
### Frontend container
| Variable | Description |
|---|---|
| `NAVIDROME_URL` | Pre-fills the Navidrome server URL on the login screen |
| `BACKEND_URL` | Pre-fills the download backend URL on the login screen |
### Backend container
| Variable | Default | Description |
|---|---|---|
| `PORT` | `3700` | Port the backend listens on |
| `MUSIC_PATH` | `/music` | Absolute path to your Navidrome music folder |
| `AUDIO_FMT` | `mp3` | Download format (`mp3`, `flac`, `opus`, `best`) |
| `AUDIO_QUALITY` | `0` | yt-dlp audio quality (0 = best) |
| `MAX_PARALLEL` | `2` | Max concurrent download jobs |
| `TICKETMASTER_API_KEY` | — | Free key from [developer.ticketmaster.com](https://developer.ticketmaster.com) |
---
## Development
```bash
npm install
npm run dev # Vite dev server with HMR
npm run build # Production build → dist/
npm run preview # Preview the production build locally
```