Song server: search and download songs, mobile web UI

- Sources: "free" (Creative Commons songs with media from
  github.com/UltraStar-Deluxe/songs) and "usdb" (usdb.animux.de with an
  account; audio/video via yt-dlp from the song's #VIDEO hints or YouTube
  links in the comments, covers from fanart.tv/YouTube)
- Aggregated search (all sources in parallel, in-library flag), download
  queue into <library>/Downloads/<source>/<Artist - Title>, then rescan
- Web UI in wwwroot (plain JS, no build): search, downloads with progress,
  library; phone first, dark mode, installable
- Docker image with yt-dlp, ffmpeg and deno; library mounted writable
- Tests for matching, USDB parsing and song rewriting

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Simon DiesenreiterandClaude Opus 5.5 committed 2026-11-05 23:15:48 +01:00
1 parent efcc63a640
commit 1e65864c8f
19 files changed
+1862 -12

No files matched your search

+35 -3
View File
@@ -4,11 +4,15 @@ A central song library for Vocaluxe. The server hosts the UltraStar song folders
backgrounds). Vocaluxe mirrors the song text files at startup and downloads audio, video and images only when they are
needed, then keeps them in a local cache.
The server also has a **web UI** (`http://<server>:8099/`, made for phones, can be added to the home screen): search
song sources on the internet, download songs into the library with one tap, and browse the library.
## Running it (Docker)
```
docker run -d --name vocaluxe-song-server -p 8099:8080 \
-v /mnt/user/karaoke/songs:/songs:ro \
docker run -d --name vocaluxe-song-server -p 8099:8080 --user 99:100 \
-v /mnt/user/karaoke/songs:/songs \
-e Usdb__User=... -e Usdb__Password=... \
git.disi.dev/projects/vocaluxe-song-server:latest
```
@@ -16,7 +20,12 @@ docker run -d --name vocaluxe-song-server -p 8099:8080 \
|---------------------------------|----------|----------------------------------------------------------------------|
| `Library__Path` | `/songs` | Root folder of the song library; any folder structure below it works |
| `Library__ScanIntervalMinutes` | `10` | Rescan interval; `0` = only at startup and via the rescan endpoint |
| `Library__ApiKey` | empty | If set, clients must send it as `X-Api-Key` |
| `Library__ApiKey` | empty | If set, clients must send it as `X-Api-Key` (the web UI asks for it) |
| `Library__DownloadFolder` | `Downloads` | Where downloaded songs go, below the library root (`<source>/<Artist - Title>`) |
| `Usdb__User`, `Usdb__Password` | empty | Account at usdb.animux.de; enables the USDB source |
The library must be writable for downloads. The image contains yt-dlp (newest at build time; YouTube changes often,
so rebuild the image when downloads start failing), ffmpeg and deno.
A song is any `.txt` file with `#TITLE`, `#ARTIST` and `#MP3` (or `#AUDIO`). All files in its folder are served.
Files outside song folders are never served.
@@ -44,6 +53,25 @@ What is downloaded when:
* **Song started:** everything still missing (video, instrumental/vocals, backgrounds). The sing screen shows the
progress and starts the song when the download is finished.
## Song sources (search and download)
Research (2026-11): where UltraStar songs come from.
| Source | What it has | Used here |
|---|---|---|
| [UltraStar-Deluxe/songs](https://github.com/UltraStar-Deluxe/songs) | ~40 Creative Commons / public domain songs **with audio** and covers | **Yes**, source `free`, no account |
| [USDB](https://usdb.animux.de) | The largest database (tens of thousands of songs), only the text files; free account needed. Songs reference audio/video (mostly YouTube) and covers (fanart.tv) in `#VIDEO` (`v=`, `a=`, `co=`, `bg=`) or in comments | **Yes**, source `usdb`: text from USDB, media via yt-dlp, like [usdb_syncer](https://github.com/bohning/usdb_syncer) |
| [UltraStar-es](https://ultrastar-es.org/en/canciones) | Large Spanish database (also other languages) | Not yet |
| [Performous packs](https://performous.org/songs) | 4 zip packs (libre, restricted, Jonathan Coulton, Shearer; CC licenses) | Not yet (Coulton songs are in `free`) |
| TXT-only GitHub repos (razzertronic/usdx-songs, derco0n/UltrastarSongs, ...) | Text files without media | Not yet |
| [UltraSinger](https://github.com/rakuri255/UltraSinger) | Creates a song from any audio with AI | Planned: songs that exist nowhere |
Songs, videos and lyrics can be copyrighted. The `free` source only has openly licensed songs; what you download from
USDB/YouTube is your own responsibility.
New sources implement `Sources/ISongSource.cs` (search + download into a folder) and are registered in `Program.cs`.
Downloads run one at a time; a song is downloaded into `Downloads/.incoming/<job>` and moved into place when complete.
## API
All endpoints are under `/api/v1` (plus `GET /health`). Paths are relative to the library root and use `/`.
@@ -55,6 +83,10 @@ The types are in `Contracts/LibraryDtos.cs`, which Vocaluxe links in.
| `GET /files/{path}` | One file, with Range support (resumable downloads) |
| `POST /files/bundle` | Several files as a zip, body `{"paths": [...]}` (max. 2000), used for text files |
| `POST /library/rescan` | Rescan now instead of waiting for the interval |
| `GET /sources` | Song sources, enabled or not (with the reason) |
| `GET /search?q=` | Search all enabled sources at once; results say whether a song is in the library |
| `GET /downloads` | Download jobs with state and progress |
| `POST /downloads` | Queue a download: `{"source", "sourceId", "artist", "title"}` from a search result |
## Building and releasing