Files
Simon DiesenreiterandClaude Opus 5.5 1e65864c8f 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>
2026-11-05 23:15:48 +01:00
..

Vocaluxe song server

A central song library for Vocaluxe. The server hosts the UltraStar song folders (text file, audio, video, cover, 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 --user 99:100 \
  -v /mnt/user/karaoke/songs:/songs \
  -e Usdb__User=... -e Usdb__Password=... \
  git.disi.dev/projects/vocaluxe-song-server:latest
Setting (environment variable) Default Meaning
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 (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.

Using it in Vocaluxe

In config.xml:

<SongServer>
  <Url>http://192.168.1.108:8099</Url>
  <ApiKey />
</SongServer>

Local song folders keep working alongside the server. The cache is in the Vocaluxe data folder under SongServer/<host>_<port>; it mirrors the server, so songs removed on the server disappear from it. Without a connection Vocaluxe uses the library of the last start, and every song whose files were downloaded before can be sung.

What is downloaded when:

  • Startup: the song list and all song text files (only changed ones after the first time). Covers are downloaded by the cover loader in the background.
  • Song selected (preview): the audio file; the preview starts when it's there. The video is downloaded in the background.
  • 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 ~40 Creative Commons / public domain songs with audio and covers Yes, source free, no account
USDB 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
UltraStar-es Large Spanish database (also other languages) Not yet
Performous packs 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 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 /. The types are in Contracts/LibraryDtos.cs, which Vocaluxe links in.

Endpoint What it does
GET /library Songs (id, path, title, artist) and all files (path, size, modified); ETag/304
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

dotnet run --project VocaluxeSongServer -- --Library:Path=D:\Songs --urls http://localhost:8099 runs it locally. The image is built by .gitea/workflows/song-server.yml: set VERSION, then push the tag songserver-v<version> (pushes :<version> and :latest). Tests: Tests/SongServer.