Adds database.InsertLyrics/GetSongStructuredLyrics storing multiple lyrics entries per song with per-line start times and, when the source provides it, word-level cues carrying precomputed UTF-8 byte offsets. library.IndexLyrics wires this into the scanner: embedded plain-text tags are stored unsynced, and a same-basename sidecar .lrc (plain or Enhanced) is parsed and stored synced, with word cues when present. IndexFile now takes the media file's absolute path so lyrics indexing can locate sidecar files. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014r98AtcBbevpscWLsfwVvv
VibeSonic
VibeSonic is a lightweight, self-hosted music/media server written in Go.
It follows the same philosophy as other small Vibe* tools: a single Go
binary, SQLite storage, server-rendered Bootstrap 5 templates, dark mode
by default, minimal JavaScript, and no external services (no Redis, no
message broker, no microservices, nothing Kubernetes-specific).
This is Phase 2 of 4. Phase 1 built the foundation (config, schema,
auth, scanner, metadata, streaming, cover art, web UI shell). Phase 2
adds a complete implementation of the original Subsonic REST API
through version 1.16.1 under /rest/* — every endpoint, backed by
real data, including transcoding, HLS, a real mpv-backed jukebox, and a
real podcast subsystem. See
docs/subsonic-compatibility.md for
the full endpoint-by-endpoint matrix. OpenSubsonic extensions are not
yet implemented (Phase 3).
Features
Phase 1: foundation
- SQLite storage (WAL mode, foreign keys, versioned migrations) with a schema already modeling artists, albums, songs, genres, contributors, playlists, favorites, ratings, scrobbles, playback history, bookmarks, play queues, shares, podcasts, internet radio, and settings
- Native authentication: Argon2id password hashing, HTTP-only signed session cookies, CSRF-protected forms, session revocation
- Optional Navidrome-style external authentication via a trusted reverse
proxy header, gated on the real TCP peer address (never on
spoofable
X-Forwarded-For/X-Real-IP/Forwardedheaders) - A library scanner supporting multiple music folders, incremental rescans, new/changed/deleted/renamed file detection, and a bounded worker pool — never a blind full rebuild
- Real metadata extraction via
ffprobe(multi-artist, multi-genre, MusicBrainz IDs, ReplayGain, embedded artwork/lyrics, sort fields, and more) - Stable, opaque, URL-safe IDs that survive restarts and rescans
- Direct media streaming with HTTP range request support, correct MIME types, and no full-file buffering
- Cover art discovery (embedded artwork or folder images) with a resized-image disk cache
- A server-rendered, dark-mode, keyboard-friendly web UI: browsing, search, playlists, favorites, a persistent bottom player, and an admin section (users, music folders, scanner status, system settings)
/healthzand/readyz
Phase 2: Subsonic REST API
- All 76 endpoints of the original Subsonic API through 1.16.1 — browsing (filesystem and ID3), search, playlists, favorites/ratings/ scrobbling, sharing, user management with the full permission model, bookmarks, play queue, chat, and library scan status
- Real ffmpeg-backed transcoding (mp3/opus/aac) and HLS segmenting for
stream/hls, bounded concurrency, killed on client disconnect - A real podcast subsystem: RSS feed refresh, bounded background downloads, restart recovery, downloaded episodes stream like any other song
- A real jukebox backed by
mpvover its JSON IPC socket — server-side playback, not a simulation; administratively unavailable (with a clear error) ifmpvisn't installed - Both original Subsonic auth modes (token/salt and password, including
enc:hex), verified against an AES-256-GCM-encrypted credential kept separate from the Argon2id hash used for native login — seedocs/subsonic-compatibility.md /rest/*authentication is entirely independent of the browser session/CSRF/external-auth flow
Quick start
go build -o vibesonic ./cmd/vibesonic
VIBESONIC_SESSION_SECRET=$(openssl rand -hex 32) ./vibesonic
Then open http://localhost:8080 — on a fresh database you'll land on
the setup wizard, which creates the administrator account, your first
music folder, and kicks off the first scan.
ffmpeg/ffprobe should be on PATH (or pointed to via
VIBESONIC_FFMPEG_PATH/VIBESONIC_FFPROBE_PATH) for metadata reading,
cover art extraction, and transcoding/HLS to work. mpv should be on
PATH (or pointed to via VIBESONIC_MPV_PATH) for the jukebox to be
available — without it, jukeboxControl returns a clear "unavailable"
error rather than pretending to work.
Docker
docker compose up -d
See docker-compose.yml — mount your music
directory read-only at /music and set VIBESONIC_SESSION_SECRET.
systemd
See systemd/vibesonic.service.
Configuration
VibeSonic is configured entirely through VIBESONIC_* environment
variables — see docs/configuration.md for the
full list and defaults. There is no separate config file.
Documentation
docs/architecture.md— how the pieces fit togetherdocs/configuration.md— every environment variabledocs/external-auth.md— trusted reverse-proxy authenticationdocs/subsonic-compatibility.md— protocol endpoint status
Development
go fmt ./...
go vet ./...
go test ./...
Most tests exercise real SQLite databases and, where relevant, the real
ffmpeg/ffprobe binaries (skipped automatically if not installed).
No mocks are used for the database.