Files
Vocaluxe/VocaluxeSongServer
Simon DiesenreiterandClaude Opus 5.5 efcc63a640 Song server: central song library with on-demand downloads
- VocaluxeSongServer: ASP.NET Core server that scans an UltraStar library and
  serves the song list (ETag), single files (Range) and zip bundles; optional
  API key; Dockerfile and Gitea workflow for git.disi.dev/projects/vocaluxe-song-server
- Game: config section SongServer (Url, ApiKey). At song loading, the song text
  files are mirrored into a local cache that is loaded like a song folder;
  without connection the last library is used
- VocaluxeLib: CSongFiles hook for all song file access; media are downloaded on
  demand (covers in the background, preview audio, everything before singing
  with progress in the sing screen)
- Tests for scanner, API and downloads (incl. resume); AGENTS.md for the fork

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 17:23:00 +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.

Running it (Docker)

docker run -d --name vocaluxe-song-server -p 8099:8080 \
  -v /mnt/user/karaoke/songs:/songs:ro \
  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

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.

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

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.