Add debug logging for audio source handling and API initialization; improve error handling in AudioPlayer and AudioPlayerContext

This commit is contained in:
2025-08-01 18:17:09 +00:00
committed by GitHub
parent be2266bf3a
commit fd7690b725
2 changed files with 81 additions and 18 deletions

View File

@@ -248,8 +248,71 @@ export const AudioPlayer: React.FC = () => {
// Always clear current track time when changing tracks // Always clear current track time when changing tracks
localStorage.removeItem('navidrome-current-track-time'); localStorage.removeItem('navidrome-current-track-time');
console.log('🔄 Setting audio source:', currentTrack.url);
// Debug: Check if URL is valid
if (!currentTrack.url || currentTrack.url === 'undefined' || currentTrack.url === '') {
console.error('❌ Invalid audio URL:', currentTrack.url);
return;
}
// Debug: Log current audio element state
console.log('🔍 Audio element state before loading:', {
src: audioCurrent.src,
readyState: audioCurrent.readyState,
networkState: audioCurrent.networkState,
crossOrigin: audioCurrent.crossOrigin,
canPlayType_mp3: audioCurrent.canPlayType('audio/mpeg'),
canPlayType_mp4: audioCurrent.canPlayType('audio/mp4'),
canPlayType_webm: audioCurrent.canPlayType('audio/webm'),
canPlayType_ogg: audioCurrent.canPlayType('audio/ogg'),
canPlayType_flac: audioCurrent.canPlayType('audio/flac'),
canPlayType_wav: audioCurrent.canPlayType('audio/wav')
});
// Clear any previous error handlers
audioCurrent.onerror = null;
audioCurrent.onloadstart = null;
audioCurrent.oncanplay = null;
// Simple error handling
audioCurrent.onerror = (e) => {
const event = e as Event;
const error = event.target as HTMLAudioElement;
console.error('❌ Audio element error:', {
error: error.error,
networkState: error.networkState,
readyState: error.readyState,
src: error.src
});
};
audioCurrent.onloadstart = () => {
console.log('📥 Audio load started');
};
audioCurrent.oncanplay = () => {
console.log('✅ Audio can play');
};
// Set source without any CORS configuration
audioCurrent.removeAttribute('crossorigin');
audioCurrent.src = currentTrack.url; audioCurrent.src = currentTrack.url;
// Force load and log state after setting source
audioCurrent.load();
// Log state after load
setTimeout(() => {
console.log('🔍 Audio element state after load:', {
src: audioCurrent.src,
readyState: audioCurrent.readyState,
networkState: audioCurrent.networkState,
error: audioCurrent.error,
duration: audioCurrent.duration
});
}, 100);
// For iOS, ensure audio element is properly loaded // For iOS, ensure audio element is properly loaded
if (isMobile) { if (isMobile) {
audioCurrent.load(); audioCurrent.load();
@@ -721,10 +784,7 @@ export const AudioPlayer: React.FC = () => {
<button <button
className="p-4 hover:bg-muted/50 rounded-full transition-all duration-200 active:scale-95 bg-primary/10 touch-manipulation" className="p-4 hover:bg-muted/50 rounded-full transition-all duration-200 active:scale-95 bg-primary/10 touch-manipulation"
onClick={togglePlayPause} onClick={togglePlayPause}
onTouchStart={(e) => { style={{ touchAction: 'manipulation' }}
// Prevent iOS double-tap zoom on the play button
e.preventDefault();
}}
type="button" type="button"
data-testid="play-pause-button" data-testid="play-pause-button"
aria-label={isPlaying ? 'Pause' : 'Play'} aria-label={isPlaying ? 'Pause' : 'Play'}
@@ -746,11 +806,8 @@ export const AudioPlayer: React.FC = () => {
{/* Single audio element - shared across all UI states */} {/* Single audio element - shared across all UI states */}
<audio <audio
ref={audioRef} ref={audioRef}
hidden
playsInline playsInline
preload={isMobile ? "none" : "auto"} preload="metadata"
controls={false}
crossOrigin="anonymous"
style={{ display: 'none' }} style={{ display: 'none' }}
/> />
<audio ref={preloadAudioRef} hidden preload="metadata" /> <audio ref={preloadAudioRef} hidden preload="metadata" />
@@ -814,11 +871,8 @@ export const AudioPlayer: React.FC = () => {
{/* Single audio element - shared across all UI states */} {/* Single audio element - shared across all UI states */}
<audio <audio
ref={audioRef} ref={audioRef}
hidden
playsInline playsInline
preload={isMobile ? "none" : "auto"} preload="metadata"
controls={false}
crossOrigin="anonymous"
style={{ display: 'none' }} style={{ display: 'none' }}
/> />
<audio ref={preloadAudioRef} hidden preload="metadata" /> <audio ref={preloadAudioRef} hidden preload="metadata" />
@@ -929,11 +983,8 @@ export const AudioPlayer: React.FC = () => {
{/* Single audio element - shared across all UI states with mobile support */} {/* Single audio element - shared across all UI states with mobile support */}
<audio <audio
ref={audioRef} ref={audioRef}
hidden
playsInline playsInline
preload={isMobile ? "none" : "auto"} preload="metadata"
controls={false}
crossOrigin="anonymous"
style={{ display: 'none' }} style={{ display: 'none' }}
/> />
<audio ref={preloadAudioRef} hidden preload="metadata" /> <audio ref={preloadAudioRef} hidden preload="metadata" />

View File

@@ -53,7 +53,15 @@ export const AudioPlayerProvider: React.FC<{ children: React.ReactNode }> = ({ c
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [shuffle, setShuffle] = useState(false); const [shuffle, setShuffle] = useState(false);
const { toast } = useToast(); const { toast } = useToast();
const api = useMemo(() => getNavidromeAPI(), []); const api = useMemo(() => {
const navidromeApi = getNavidromeAPI();
if (!navidromeApi) {
console.warn('⚠️ Navidrome API not configured');
} else {
console.log('✅ Navidrome API initialized');
}
return navidromeApi;
}, []);
useEffect(() => { useEffect(() => {
const savedQueue = localStorage.getItem('navidrome-audioQueue'); const savedQueue = localStorage.getItem('navidrome-audioQueue');
@@ -98,10 +106,14 @@ export const AudioPlayerProvider: React.FC<{ children: React.ReactNode }> = ({ c
if (!api) { if (!api) {
throw new Error('Navidrome API not configured'); throw new Error('Navidrome API not configured');
} }
const streamUrl = api.getStreamUrl(song.id);
console.log('🎵 Creating track with stream URL:', streamUrl);
return { return {
id: song.id, id: song.id,
name: song.title, name: song.title,
url: api.getStreamUrl(song.id), url: streamUrl,
artist: song.artist, artist: song.artist,
album: song.album, album: song.album,
duration: song.duration, duration: song.duration,