How it is built
Audio cache
How Nuvo stores audio encrypted, serves it by range, prefetches, and limits its size.
File format
Each cached track is one file named <sha256(track id)>.lac in ~/.cache/nuvo/audio/. The name hides the track id. The database indexes the files.
"LAC1" | 16-byte nonce prefix | sealed chunk | sealed chunk | ...
- The audio is cut into 64 KiB chunks. Each chunk is sealed on its own with XChaCha20-Poly1305. The nonce is the file’s random prefix plus the chunk number.
- Chunks are independent. A seek decrypts only the chunks it needs. A damaged chunk fails authentication.
- The key comes from the master key. A file written with another key is reported as corrupt.
Fetching
The renderer asks the daemon to fetch a stream URL, or uploads audio it already holds. Fetch jobs:
- accept only
httpsURLs on the playback hosts (*.googlevideo.com,*.sndcdn.com,playback.media-streaming.soundcloud.cloud), with no credentials and no custom port, - check that every address the host resolves to is public,
- follow at most three redirects, each checked the same way,
- download in 10 MiB ranges, run two jobs at a time, and time out after ten minutes,
- keep the status of the last 50 jobs.
A download writes to a temporary .part file with a random name and renames it when finished. On start the daemon removes partial files and files that the index does not know.
Prefetch
While a track plays, Nuvo fetches the next one in the background so the next start comes from the cache.
Size limit
The default limit is 5 GiB. The minimum is 256 MiB. A limit of 0 means no limit. When the cache is over its limit the daemon removes files, fewest plays in the last 30 days first, then the longest unplayed. It keeps liked tracks, tracks in playlists pinned for offline use, and tracks you finished at least three times in the last 30 days. Settings, Cache and Storage shows usage and lets you change the limit or clear it.
Covers
Cover art lives in a separate encrypted cache, sized for display, with one fetch per cover and size.
Local files
Local files are never copied into this cache. They play from where they are.