Files
NovaSonic/README.md
T
2026-05-24 12:32:53 +02:00

174 lines
7.7 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 for Navidrome / Subsonic-compatible servers.
Built with Vite + vanilla ES modules, served via nginx in Docker.
---
## Features
### Home
- Hero card — large banner featuring a random pick from your most-played and recently played albums, labelled "Meistgespielt" or "Zuletzt gehört" accordingly
- Genre browser — top 15 genres (by song count) as a colored card grid; click to browse songs, hover-play to instantly shuffle the genre
### Music Library
- Stream music from your Navidrome / Subsonic library
- Browse artists, albums, playlists, starred tracks, and random picks
- Sort and filter views (albums, favorites) with chip filters
- Search/filter bar inside playlist detail and favorites (instant, client-side)
- Synced and plain lyrics via LRCLIB (auto-fetched per track)
- Play count display — optional toggle in Settings; always shown on artist pages
- Star and context-menu on every song row (artist top songs, all-songs view, playlists, albums)
### Playback
- Queue management with shuffle, repeat (all / once), and radio mode (endless random)
- Spotify-style shuffle — pre-shuffles the full queue so every song plays exactly once
- Now Playing overlay with swipe-to-dismiss; queue tab stays active when selecting a song from the queue
- Lock screen media controls (Android / iOS via Media Session API)
- Gapless-style queue with prev/next, skip forward/back
- Scrobbling — plays are reported to Navidrome after 15 seconds of continuous playback
### Discovery
- iTunes / Last.fm integration — charts, global search, 30-second previews, similar artists, recommendations
- Song Importer — paste a link from Spotify, YouTube, YouTube Music, or SoundCloud to preview and download tracks, enriched with iTunes metadata and cover art
### Downloads (yt-dlp backend)
- Download individual tracks, full albums, or entire artists
- Sources: YouTube Music (primary), YouTube, SoundCloud, Spotify (via playlist importer)
- iTunes enrichment — album, year, track number, genre, 1000×1000 cover art
- Duplicate detection — skips tracks already present on the server
- Standard filename convention: `{01 - }Artist1, Artist2 - Title.ext`
- Files organised into `MusicRoot/AlbumArtist/Album/` folders automatically
### Metadata Editor
- Edit title, artist, album artist, album, genre, year, track number, disc number from within the app
- Update embedded cover art via URL or file upload
- Artist separator normalization — accepts `•`, `·`, `;`, `,` as input; stores as `;` for track artist and `,` for album artist (Navidrome/MusicBrainz style)
- File renamed automatically on save to match the standard naming convention
- File moved to the correct `AlbumArtist/Album/` folder when those fields change
- Empty folders cleaned up after a move
- Navidrome rescan triggered automatically after every save
### Playlists
- Create, edit, and delete playlists
- Edit playlist name, description, cover art, and public/private toggle
- Add / remove tracks; reorder via drag and drop
### Audiobookshelf Integration
- Connect to your Audiobookshelf server (URL + API key)
- Browse and stream audiobooks from your ABS library
- Full player: chapters list, playback speed, sleep timer (preset or custom minutes), progress sync
### App
- PWA — installable on Android / iOS / desktop, offline-capable via service worker
- Android APK (WebView wrapper with native Media3/ExoPlayer backend)
- Robust Android queue sync — song identity verified via media ID on every resume to prevent stale-state mismatches
- Multiple color themes
- Dark theme, mobile-first responsive layout
- German UI
---
## Project Structure
```
Music_App/
├── src/ # ES modules (Vite entry)
│ ├── state.js # Shared mutable state (S object)
│ ├── utils.js # md5, esc, formatDur, toast
│ ├── api.js # Subsonic API, Navidrome REST, iTunes API
│ ├── player.js # Playback, transport, queue, media session, preview
│ ├── views.js # Navigation, page loaders, card makers, search
│ ├── ui.js # Modals, overlays, sidebar, settings, context menu, metadata editor
│ ├── nowplaying.js # Now Playing overlay
│ ├── abs.js # Audiobookshelf integration
│ ├── spotify.js # Spotify importer (resolve + download)
│ ├── youtube.js # YouTube / YouTube Music importer
│ ├── soundcloud.js # SoundCloud importer
│ ├── components.js # Shared UI components (song rows, cards)
│ ├── themes.js # Theme switching
│ ├── pwa.js # Service worker registration + update banner
│ └── main.js # App init, audio wiring, window globals
├── backend/
│ ├── novasonic-server.js # Express API: download jobs, metadata edit, resolvers
│ ├── spotify_resolve.py # Spotify page scraper (track/album/playlist metadata)
│ └── lib/
│ ├── config.js # Backend config (env vars, paths, format)
│ ├── jobs.js # In-memory job store + log helper
│ ├── metadata.js # iTunes lookup, artwork download, lyrics fetch, filename helpers
│ ├── ytdlp.js # yt-dlp download cascade + ffmpeg metadata embedding
│ ├── squid.js # Squid/Qobuz download backend
│ ├── downloader.js # Unified downloadTrack / downloadAlbumTracks entry point
│ └── romaji.js # Japanese → romaji index for search
├── public/ # Static assets (copied as-is to dist/)
│ ├── sw.js # Service worker
│ ├── manifest.json # PWA manifest
│ ├── icon.svg # App icon
│ └── config.js # Runtime config placeholder (generated by Docker)
├── android/ # Android WebView APK wrapper
├── index.html # App shell + Vite entry point
├── styles.css # All styles
├── vite.config.js
├── Dockerfile # Multi-stage: Node build → nginx serve
├── docker-compose.yml
├── nginx.conf
└── docker-entrypoint.sh # Injects NS_SERVER_URL / NS_BACKEND_URL at startup
```
---
## Docker Setup
### Frontend only
```bash
docker compose up -d
```
Environment variables (set in `docker-compose.yml` or via `-e`):
| Variable | Description |
|---|---|
| `NS_SERVER_URL` | Pre-fills the Navidrome server URL on the login screen |
| `NS_BACKEND_URL` | Pre-fills the download backend URL |
### With download backend
The backend requires `yt-dlp` and `ffmpeg`. A separate `docker-compose.yml` lives in `backend/`.
```bash
cd backend
docker compose up -d
```
Environment variables for the backend:
| Variable | Default | Description |
|---|---|---|
| `PORT` | `3700` | Port the backend listens on |
| `MUSIC_PATH` | `/music` | Path to your Navidrome music folder (mount as volume) |
| `AUDIO_FMT` | `mp3` | Output format (`mp3`, `flac`, `opus`, …) |
| `AUDIO_QUALITY` | `0` | yt-dlp audio quality (0 = best) |
| `MAX_PARALLEL` | `2` | Maximum concurrent downloads |
---
## 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
```
---
## First Launch
1. Open the app in a browser
2. Enter your Navidrome server URL, username and password
3. Optionally add a Last.fm API key (Settings) for recommendations and similar artists
4. Optionally add the backend URL (Settings) to enable yt-dlp downloads
5. Optionally connect Audiobookshelf (Settings) to stream audiobooks