- Fixed player seek flicker on podcasts (30s skip buttons) - Added dual-layer seek lock mechanism to prevent stale time updates - Optimized cached podcast seeking (direct seek before reload fallback) - Large skips now execute immediately for responsive feel - Mood mix performance optimizations
7.7 KiB
Lidify Bug Handoff Guide
Date: 2025-12-26 Project: Lidify Music Server
Overview
This document provides context for continuing work on several bugs in the Lidify application. The previous agent made partial fixes but issues remain.
Bug 1: Mood Mixer - Multiple Issues
Current State
- Generation is slow - Takes too long to generate mood mixes
- UI not updating - The playlist card on home page doesn't refresh when generating new mood mixes
- Stale playlist persists - User created "Happy" mix first, then replaced it 3 times with other emotions, but the original "Happy" card still shows on the home page even though the actual music changes
Root Cause Analysis Needed
- Slow generation: Check
backend/src/services/programmaticPlaylists.ts- thegenerateMoodOnDemand()function (line ~3104) may be doing expensive database queries - UI not updating: The frontend uses React Query. Check:
frontend/components/MoodMixer.tsx- dispatcheswindow.dispatchEvent(new CustomEvent("mix-generated"))and"mixes-updated"events- The home page component needs to listen for these events and invalidate/refetch
- Stale card: The mix ID or cache key may not be changing. Look at:
- How mood mix preferences are saved:
POST /mixes/mood/save-preferences - How the home page fetches the mix to display
- How mood mix preferences are saved:
Files to Investigate
backend/src/services/programmaticPlaylists.ts- Main playlist generation logicbackend/src/routes/mixes.ts- API endpoints for mood mixesfrontend/components/MoodMixer.tsx- UI componentfrontend/app/page.tsx- Home page that displays mix cardsfrontend/hooks/useQueries.ts- React Query hooks
Previous Fix Attempt
The previous agent added fallback logic in generateMoodOnDemand() (lines 3126-3183) to handle cases where enhanced audio analysis isn't available. The fix converts ML mood params to basic audio features as a fallback. This may have introduced complexity or bugs.
Suggested Approach
- Check database indexes - The query in
generateMoodOnDemandfilters byanalysisStatus,analysisMode, and various audio features. Ensure proper indexes exist. - Simplify the query - Consider limiting the initial pool of tracks rather than applying all filters at once
- Fix cache invalidation - The home page likely caches the mix data. Need to ensure proper invalidation when a new mix is generated
- User said "might need complete overhaul" - Consider refactoring the mood mixer to be simpler
Bug 2: Podcast Seeking - Still Broken
Current Symptoms
- Slow press required - User has to slowly press ±30s buttons, otherwise nothing happens
- Spam causes stuck state - If user presses button rapidly, playback gets stuck in "perpetual play state" where fast forward/rewind stops working entirely
Root Cause
The podcast seeking logic is complex and involves:
- Checking cache status via API
- Reloading the Howler audio engine
- Seeking to position after reload
- Multiple timeout-based checks
Previous Fix Attempts
The previous agent added:
- Seek operation ID tracking (
seekOperationIdRef) to abort stale seeks - Debouncing (150ms) for podcast seeks via
seekDebounceRef - Better cleanup of listeners and timeouts
These fixes were incomplete or introduced new issues.
Files to Investigate
frontend/components/player/HowlerAudioElement.tsx- Main seek handling logic (lines 672-853)- The seek handler is in
useEffectstarting around line 672 - Uses
seekDebounceRefandpendingSeekTimeReffor debouncing - Uses
seekOperationIdRefto track/abort stale operations
- The seek handler is in
frontend/lib/howler-engine.ts- Low-level audio engine wrapperreload()method (line ~293) - calls cleanup then loadcleanup()method (line ~438) - handles Howl instance teardown- The
cleanup()has a delayed unload for playing audio which may cause race conditions
Key Code Sections
HowlerAudioElement.tsx - Seek Handler (lines 672-853):
useEffect(() => {
const handleSeek = async (time: number) => {
seekOperationIdRef.current += 1;
const thisSeekId = seekOperationIdRef.current;
// For podcasts: debounce, check cache, reload if cached, etc.
// Complex async logic with multiple timeouts
};
const unsubscribe = audioSeekEmitter.subscribe(handleSeek);
return unsubscribe;
}, [...deps]);
howler-engine.ts - Cleanup (lines ~438-480):
private cleanup(): void {
// Has delayed unload when wasPlaying (12ms fade + timeout)
// This may race with new loads
}
Suggested Approach
- Remove or increase debounce - 150ms might be too short or the logic is wrong
- Fix the stuck state - Likely caused by event listeners not being properly cleaned up
- Simplify the reload logic - The cache check → reload → seek → play chain is fragile
- Consider immediate cleanup - Skip the fade delay for podcast seeks to prevent race conditions
- Add loading/disabled state - Disable seek buttons while a seek is in progress
Bug 3: Similar Artists ("Fans Also Like") - Partially Fixed
Current State
The previous agent made fixes to show library artists in the "Fans Also Like" section. The fix:
- Checks if similar artists exist in the user's library
- Returns
inLibraryflag andownedAlbumCount - Shows a library badge icon
Files Modified
backend/src/routes/library.ts- Enhanced similar artists response (lines 1369-1533)frontend/features/artist/types.ts- AddedinLibrary?: booleanto SimilarArtist typefrontend/features/artist/components/SimilarArtists.tsx- Updated UI and navigation logic
Status
Believed to be working but needs verification.
Development Environment
Key Commands
# Backend
cd backend
npm run dev # Dev server with hot reload
npm run build # Production build
npx tsc --noEmit # Type check only
# Frontend
cd frontend
npm run dev # Dev server
npm run build # Production build
Architecture
- Backend: Express.js + Prisma + PostgreSQL + Redis
- Frontend: Next.js 14 (App Router) + React Query + TailwindCSS
- Audio: Howler.js for playback
- Analysis: Essentia Docker container for audio feature extraction
Database
- Prisma ORM with PostgreSQL
- Key models: Track, Album, Artist, User
- Tracks have
analysisStatusandanalysisModefields for audio analysis state
Priority Order
- Podcast seeking - Most user-facing, core functionality broken
- Mood mixer UI not updating - Confusing UX
- Mood mixer slow - Performance issue
Quick Reference - Key Files
| Feature | Backend | Frontend |
|---|---|---|
| Mood Mixer | services/programmaticPlaylists.ts, routes/mixes.ts |
components/MoodMixer.tsx, app/page.tsx |
| Podcast Seek | routes/podcasts.ts |
components/player/HowlerAudioElement.tsx, lib/howler-engine.ts |
| Similar Artists | routes/library.ts (lines 1369-1533) |
features/artist/components/SimilarArtists.tsx |
Notes from Previous Agent
-
The mood mixer presets all use ML mood params (
moodHappy,moodSad, etc.) which requireanalysisMode: "enhanced". A fallback to basic audio features was added but may be causing issues. -
The podcast seek debounce was added at 150ms with a
pendingSeekTimeRefto coalesce rapid seeks. This approach may be flawed. -
The Howler engine's
cleanup()method has an intentional 12ms fade delay before unloading to reduce audio pops. This delay may cause race conditions with rapid reloads. -
The
seekOperationIdRefcounter was intended to abort stale seek operations but the logic may have bugs in how it's checked across async boundaries.