Two bugs fixed:
1. handle_transcode was writing cdn_hls_base = "hls/{version_id}" to the DB
even though HLS files were only in a temp dir (never uploaded to Nextcloud).
The stream endpoint then tried to serve this non-existent path, returning 404
and breaking audio playback for every transcoded version. Removed the
cdn_hls_base write — stream endpoint falls back to nc_file_path (raw file),
which works correctly.
2. Added extract_peaks worker job type: lightweight job that downloads audio
and computes waveform_peaks + waveform_peaks_mini only. No transcode, no HLS,
no full analysis.
3. Added POST /internal/reindex-peaks endpoint (protected by internal secret):
finds all audio_versions with null waveform_peaks and enqueues extract_peaks
jobs. Safe to call multiple times. Use after a fresh DB scan or peak algorithm
changes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Band creation now starts with a Nextcloud credentials step when
storage is not yet configured. Users can save NC credentials
(or skip) before proceeding to band name/slug/folder entry.
- StorageStep: NC URL, username, app password; PATCH /auth/me/settings
- BandStep: name, slug (auto-generated), NC folder with warning when NC not set
- StepDots: animated pill indicators for current step
- Modal fetches /auth/me on open to determine starting step
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The "New band" button in TopBandBar previously navigated to the HomePage
which immediately redirected back if any bands already existed, making it
impossible to create additional bands.
Replaced the navigation with an inline modal that:
- Opens directly from the "New band" button in the band switcher dropdown
- Fields: band name (with auto-slug), slug, Nextcloud folder path
- NC folder input shows placeholder based on current slug, links to
Settings → Storage so the user knows where to configure Nextcloud
- Validates: disabled submit until name + slug are filled
- On success: invalidates band list cache and navigates to the new band
- Closes on backdrop click or Escape key
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Store waveform peaks inline in audio_versions (JSONB columns) so WaveSurfer
can render the waveform immediately on page load without waiting for audio
decode. Adds a 100-point mini-waveform for version selector thumbnails.
Backend:
- Migration 0006: adds waveform_peaks and waveform_peaks_mini JSONB columns
- Worker generates both resolutions (500-pt full, 100-pt mini) during transcode
and stores them directly in DB — replaces file-based waveform_url approach
- AudioVersionRead schema exposes both fields inline (no extra HTTP round-trip)
- GET /versions/{id}/waveform reads from DB; adds ?resolution=mini support
Frontend:
- audioService.initialize() accepts peaks and calls ws.load(url, Float32Array)
so waveform renders instantly without audio decode
- useWaveform hook threads peaks option through to audioService
- PlayerPanel passes waveform_peaks from the active version to the hook
- New MiniWaveform SVG component (no WaveSurfer) renders mini peaks in the
version selector buttons
Fix: docker-compose.dev.yml now runs alembic upgrade head before starting
the API server, so a fresh volume gets the full schema automatically.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Swaps violet (#8b5cf6) for teal (#14b8a6/#0d9488) across all components
and updates dark backgrounds to have a green-tinted hue instead of blue-navy.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Library and PlayerPanel now display one at a time on all screen sizes.
Selecting a song navigates to the player; the back button returns to
the library. Removes isMobile breakpoint logic and fixed 340px panel width.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Collapsible sidebar (68px icons / 230px expanded, toggle via logo)
- LibraryPanel: sessions expand inline to show tracks, search + filter chips
- PlayerPanel: extracted from SongPage, used as embeddable panel
- BandPage: Library + Player side by side; song selection via ?song= URL param
- SongPage: thin wrapper around PlayerPanel (kept for direct deep-links)
- CSS palette updated to v2 violet/cyan/emerald scheme
- Mobile (<900px): BandPage shows library or player, never both
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>