From 28489f722ad61f7014a0907149c0b25149ba1d7f Mon Sep 17 00:00:00 2001 From: Honey Date: Mon, 8 Jun 2026 21:56:54 +0200 Subject: [PATCH] docs: rewrite README with current features, structure and env vars Co-Authored-By: Claude Sonnet 4.6 --- README.md | 215 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 123 insertions(+), 92 deletions(-) diff --git a/README.md b/README.md index e9890a7..02139e1 100644 --- a/README.md +++ b/README.md @@ -1,70 +1,69 @@ # NovaSonic -A self-hosted music streaming PWA for Navidrome / Subsonic-compatible servers. +A self-hosted music streaming PWA and Android app 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) +- Sort and filter views 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) +- Play count display — optional toggle in Settings +- Star and context menu on every song row + +### Artist Pages +- Full-bleed hero card — artist photo as portrait + blurred background (desktop); full-bleed image with name overlay (mobile) +- Bio, similar artists, top songs pulled from Last.fm via Navidrome +- Concert events via Ticketmaster (upcoming shows with venue, date, ticket link) +- Albums cross-referenced against iTunes catalog — shows what's downloaded, partially downloaded, or missing +- Quick actions: play top songs, shuffle all, open concerts ### Playback -- Queue management with shuffle, repeat (all / once), and radio mode (endless random) +- Queue management with shuffle, repeat (all / one), 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 +- Now Playing overlay with swipe-to-dismiss +- Gapless-style playback — next track pre-buffered 60 seconds before current track ends +- Lock screen / notification media controls (Android / iOS / desktop) +- Scrobbling — reported to Navidrome (configurable: 15 s / 30 s / ⅓ / ⅔ / end) ### 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 +- Song Importer — paste a Spotify, YouTube, YouTube Music, or SoundCloud link to preview and download tracks ### Downloads (yt-dlp backend) - Download individual tracks, full albums, or entire artists -- Sources: YouTube Music (primary), YouTube, SoundCloud, Spotify (via playlist importer) +- Sources: YouTube Music (primary), YouTube, SoundCloud, Spotify (via 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 +- Standard filename: `01 - Artist - Title.ext`, organised into `AlbumArtist/Album/` folders ### Metadata Editor -- Edit title, artist, album artist, album, genre, year, track number, disc number from within the app +- Edit title, artist, album artist, album, genre, year, track number, disc number - 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 +- File renamed and moved automatically on save +- Navidrome rescan triggered after every save ### Playlists - Create, edit, and delete playlists -- Edit playlist name, description, cover art, and public/private toggle +- Edit name, description, cover art, 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 +- Browse and stream audiobooks from your Audiobookshelf server +- Chapters list, playback speed, sleep timer, 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 +- PWA — installable on Android / iOS / desktop +- Android APK — native WebView wrapper with Media3 / ExoPlayer backend + - Native OS notification with skip buttons + - Pre-buffers last played track on cold start for instant resume + - Artwork pre-warming so notification never shows blank cover +- Multiple color themes, dark mode, mobile-first responsive layout - German UI --- @@ -72,84 +71,126 @@ Built with Vite + vanilla ES modules, served via nginx in Docker. ## Project Structure ``` -Music_App/ -├── src/ # ES modules (Vite entry) +NovaSonic/ +├── src/ +│ ├── player/ +│ │ ├── player.js # Playback, queue, transport, media session, preload +│ │ └── nowplaying.js # Now Playing overlay +│ ├── views/ +│ │ ├── detail.js # Artist / album detail pages +│ │ ├── views.js # Navigation, page loaders, search +│ │ ├── events.js # Ticketmaster concert events +│ │ ├── home.js # Home page, artist image cache +│ │ ├── 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, settings, 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 # 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 +│ ├── api.js # Subsonic API, iTunes API, cover art │ └── 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) +│ ├── novasonic-server.js # Express API: downloads, metadata, events proxy │ └── 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/) +│ ├── config.js # Env var → config object +│ ├── jobs.js # In-memory download job store +│ ├── metadata.js # iTunes lookup, artwork, lyrics, filename helpers +│ ├── ytdlp.js # yt-dlp download + ffmpeg metadata embedding +│ ├── squid.js # Qobuz (squid.wtf) download backend +│ ├── downloader.js # Unified downloadTrack / downloadAlbumTracks +│ └── romaji.js # Japanese → romaji search index +├── android/ # Android APK (WebView + Media3/ExoPlayer) +├── public/ │ ├── 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 +│ └── config.js # Runtime config (generated by Docker entrypoint) +├── index.html +├── styles.css ├── vite.config.js -├── Dockerfile # Multi-stage: Node build → nginx serve +├── Dockerfile ├── docker-compose.yml ├── nginx.conf -└── docker-entrypoint.sh # Injects NS_SERVER_URL / NS_BACKEND_URL at startup +└── docker-entrypoint.sh # Injects NAVIDROME_URL / BACKEND_URL at runtime ``` --- -## Docker Setup +## Setup -### Frontend only +### 1. Clone and configure + +```bash +git clone +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 # absolute path to your music folder on the host + +AUDIO_FMT=mp3 # mp3 | flac | opus | best +AUDIO_QUALITY=0 # 0 = best (yt-dlp) +MAX_PARALLEL=2 + +DOWNLOAD_BACKEND=auto # ytdlp | squid | auto +SQUID_QUALITY=mp3 # mp3 | flac | hi-res + +TICKETMASTER_API_KEY= # optional — free key from developer.ticketmaster.com +``` + +### 2. Start ```bash docker compose up -d ``` -Environment variables (set in `docker-compose.yml` or via `-e`): +This starts both the frontend (nginx on port 8080) and the backend (Node.js on port 3700). Route both ports through your reverse proxy. + +### 3. First launch + +1. Open the app and enter your Navidrome server URL, username and password +2. Optionally add a Last.fm API key in Settings for recommendations and artist bios +3. Optionally connect Audiobookshelf in Settings to stream audiobooks + +--- + +## Environment Variables + +### Frontend container | Variable | Description | |---|---| -| `NS_SERVER_URL` | Pre-fills the Navidrome server URL on the login screen | -| `NS_BACKEND_URL` | Pre-fills the download backend URL | +| `NAVIDROME_URL` | Pre-fills the Navidrome server URL on the login screen | +| `BACKEND_URL` | Pre-fills the download backend URL on the login screen | -### 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: +### Backend container | 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`, …) | +| `MUSIC_PATH` | `/music` | Absolute path to your Navidrome music folder (mounted as volume) | +| `AUDIO_FMT` | `mp3` | Download output format (`mp3`, `flac`, `opus`, `best`) | | `AUDIO_QUALITY` | `0` | yt-dlp audio quality (0 = best) | -| `MAX_PARALLEL` | `2` | Maximum concurrent downloads | +| `MAX_PARALLEL` | `2` | Max concurrent download jobs | +| `DOWNLOAD_BACKEND` | `auto` | `ytdlp` / `squid` / `auto` (tries Qobuz first, falls back to yt-dlp) | +| `SQUID_QUALITY` | `mp3` | Qobuz quality: `mp3`, `flac`, `hi-res` | +| `TICKETMASTER_API_KEY` | — | Free API key from [developer.ticketmaster.com](https://developer.ticketmaster.com) — enables concert events on artist pages | --- @@ -161,13 +202,3 @@ 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