🎡 Audio Player Debug Guide

Issue: Audio player stuck at 0:00, streaming works but progress not updating
Date: October 3, 2025


Diagnostic Steps

1. Browser Console Check

Open browser DevTools (F12) β†’ Console tab β†’ Play a track β†’ Look for:

🎡 Loading track: [track name]
🎡 Audio load started
🎡 Audio can play
🎡 βœ… Started playing successfully!
⏱️ timeupdate: X.X / Y.Y  (should appear ~1/sec)

2. Network Tab Verification

Check if audio files stream correctly:

  • DevTools β†’ Network β†’ Filter: audio
  • Should see /audio/[id] requests with 200 status
  • Check response headers for Content-Type: audio/mpeg or audio/mp3

3. React Devtools / State Inspection

Install Svelte DevTools browser extension:

  • Inspect AudioPlayer component
  • Check currentTime and duration state values
  • Verify they update as audio plays

4. Manual Tests

Test A: Direct Audio Element

// In browser console
const audio = document.querySelector("audio");
console.log("src:", audio.src);
console.log("readyState:", audio.readyState); // 4 = HAVE_ENOUGH_DATA
console.log("currentTime:", audio.currentTime);
console.log("duration:", audio.duration);
console.log("paused:", audio.paused);
 
// Force play
audio
  .play()
  .then(() => console.log("βœ… Playing"))
  .catch((e) => console.error("❌", e));
 
// Check if timeupdate fires
audio.addEventListener("timeupdate", () =>
  console.log("⏱️", audio.currentTime),
);

Test B: Store State

// Check if store updates propagate
import { playerStore } from "$lib/stores/playerStore.js";
playerStore.subscribe((state) =>
  console.log("πŸ“Š Store:", state.currentTime, state.duration),
);

Known Issues & Solutions

Issue: timeupdate Fires But UI Doesn’t Update

Cause: Svelte 5 $effect reactivity not triggering re-renders

Solution: Force re-render by using $derived instead of $effect:

// BEFORE (AudioPlayer.svelte L31-36)
$effect(() => {
  currentTime = $playerStore.currentTime;
  duration = $playerStore.duration;
});
 
// AFTER
let currentTime = $derived($playerStore.currentTime);
let duration = $derived($playerStore.duration);

Issue: Audio Context Suspended

Symptom: Play button clicks but nothing happens

Solution: Already handled in L421-428 (resume audio context)

Issue: CORS Blocks Audio

Symptom: Console shows CORS errors

Solution: fast_proxy.py L37-49 already configured with proper CORS


Code Locations

  • AudioPlayer Component: beetle/src/lib/components/AudioPlayer.svelte
  • Player Store: beetle/src/lib/stores/playerStore.js
  • Audio Endpoint: beets-docker/scripts/fast_proxy.py L468-569

Key Event Handlers

  • L309: ontimeupdate={handleTimeUpdate} β†’ updates store every 0.1s
  • L310: onloadedmetadata={handleLoadedMetadata} β†’ sets duration
  • L311: ondurationchange={handleDurationChange} β†’ fallback duration
  • L141-150: startProgressLoop() β†’ RAF for smooth updates
  • L159-166: startIntervalFallback() β†’ 250ms interval backup

Store Methods

  • L56: updateTime(time) β†’ updates currentTime in store
  • L57: setDuration(duration) β†’ updates duration in store

Testing Checklist

  • Open http://0rk.de:55667/ in browser
  • Open DevTools Console (F12)
  • Click on a track to play
  • Verify console logs show:
    • 🎡 Loading track
    • 🎡 Audio load started
    • 🎡 βœ… Started playing successfully!
    • ⏱️ timeupdate: X.X / Y.Y (repeating)
  • Check UI displays:
    • Current time updates (left side)
    • Duration shows correct length (right side)
    • Progress bar slider moves
  • Test seek: Drag progress bar β†’ currentTime updates
  • Test pause/play toggle
  • Test next/previous track buttons

Quick Fix: If timeupdate Logs But UI Stuck

The issue is likely Svelte 5 reactivity. Try this patch:

cd beetle/src/lib/components
# Backup
cp AudioPlayer.svelte AudioPlayer.svelte.bak
 
# Edit L22-26 from:
#   let currentTime = $state(0);
#   let duration = $state(0);
# To:
#   let currentTime = $derived($playerStore.currentTime);
#   let duration = $derived($playerStore.duration);
 
# Remove L31-36 $effect block (now redundant)
 
# Rebuild & restart
cd ../../..
npm run build
sudo systemctl restart beetle.service

Emergency Rollback

If audio player breaks after changes:

cd beetle/src/lib/components
git checkout AudioPlayer.svelte
# OR
cp AudioPlayer.svelte.bak AudioPlayer.svelte
cd ../../..
npm run build
sudo systemctl restart beetle.service