Resume: savedPositionRef appliqué sur loadedmetadata pour survivre
au remontage audio après échec CORS. Analyser: fftSize 256,
smoothing 0.55. Simulation: rythme syllabique avec consonantes.
Approche hybride CORS retry:
- Tentative 1: crossOrigin="anonymous" + createMediaElementSource
→ données de fréquence réelles si le serveur le permet
- Tentative 2 (si CORS bloque): sans crossOrigin, audio direct
→ son fonctionne, visualiseur simulé
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
createMediaElementSource détache l'audio de sa sortie par défaut.
Pour les ressources cross-origin sans CORS, le graphe Web Audio
produit du silence — aucun son.
- Retire createMediaElementSource et tout le pipeline Web Audio
- L'audio joue directement via l'élément <audio> (fiable)
- Le visualiseur utilise une animation simulée (plus de dépendance CORS)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
crossOrigin="anonymous" sur <audio> forçait le navigateur à exiger
les headers CORS des serveurs audio. Les hébergeurs sans
Access-Control-Allow-Origin bloquaient le chargement entièrement.
- Retire crossOrigin="anonymous" de l'élément <audio>
- Ajoute visualisation simulée dans l'egaliseur quand les données
de fréquence réelles sont indisponibles (audio cross-origin)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace static CSS eq-bars with a real-time AudioVisualizer component
using the Web Audio API AnalyserNode. The visualizer is now centered
below the progress bar in the inline hero player, with 28 bars and
boosted mid-range frequencies for better speech visualization.
- AudioContext: wire AnalyserNode, expose getFrequencyData, add
crossOrigin="anonymous" and key on the audio element
- AudioPlayer (inline): remove static eq-bars, add AudioVisualizer
- New AudioVisualizer component: requestAnimationFrame loop,
smooth decay on pause, configurable bar count/height/gap
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- AudioPlayer is now purely presentational — no internal <audio> element or state.
All playback state (currentTime, duration, volume, speed, mute, error, isResuming)
comes from AudioContext, which holds the persistent <audio> at provider level.
This prevents audio from cutting when navigating between pages.
- userId is synced into AudioContext via setUserId() so progress saving/loading
works without the player needing to manage it locally.
- EpisodeCard: isCompleted now triggers at ≥90% listened (progressPercent >= 0.9)
in addition to the isCompleted flag, so the LU badge appears correctly.
Progress bar also hidden when ≥90%.
- Dashboard: episodesInProgress now excludes episodes at ≥90% listened,
removing them from the "Continuer l'écoute" section once effectively finished.
setUserId() called after user loads to wire context progress saving.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>