Implement quality fallback on playback error (fix for Firefox blob/DASH issues)
This commit is contained in:
parent
6ec7ecb5ea
commit
60d53cf87b
2 changed files with 46 additions and 1 deletions
46
js/events.js
46
js/events.js
|
|
@ -113,10 +113,54 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) {
|
||||||
player.updateMediaSessionPositionState();
|
player.updateMediaSessionPositionState();
|
||||||
});
|
});
|
||||||
|
|
||||||
audioPlayer.addEventListener('error', (e) => {
|
audioPlayer.addEventListener('error', async (e) => {
|
||||||
console.error('Audio playback error:', e);
|
console.error('Audio playback error:', e);
|
||||||
playPauseBtn.innerHTML = SVG_PLAY;
|
playPauseBtn.innerHTML = SVG_PLAY;
|
||||||
|
|
||||||
|
const currentQuality = player.quality;
|
||||||
|
|
||||||
|
// Check if we can fallback to a lower quality
|
||||||
|
if (
|
||||||
|
player.currentTrack &&
|
||||||
|
currentQuality === 'HI_RES_LOSSLESS' &&
|
||||||
|
!player.currentTrack.isLocal &&
|
||||||
|
!player.currentTrack.isTracker &&
|
||||||
|
!player.isFallbackRetry
|
||||||
|
) {
|
||||||
|
console.warn('Playback failed, attempting fallback to LOSSLESS quality...');
|
||||||
|
player.isFallbackRetry = true; // Set flag to prevent infinite loops
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Force getTrack to fetch new URL for LOSSLESS
|
||||||
|
const trackId = player.currentTrack.id;
|
||||||
|
|
||||||
|
// Fetch new stream URL
|
||||||
|
const newStreamUrl = await player.api.getStreamUrl(trackId, 'LOSSLESS');
|
||||||
|
|
||||||
|
if (newStreamUrl) {
|
||||||
|
// Reset player state for standard playback (non-DASH if possible)
|
||||||
|
if (player.dashInitialized) {
|
||||||
|
player.dashPlayer.reset();
|
||||||
|
player.dashInitialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
audioPlayer.src = newStreamUrl;
|
||||||
|
audioPlayer.load();
|
||||||
|
await audioPlayer.play();
|
||||||
|
|
||||||
|
// Reset flag after successful start
|
||||||
|
setTimeout(() => {
|
||||||
|
player.isFallbackRetry = false;
|
||||||
|
}, 5000);
|
||||||
|
return; // Successfully handled
|
||||||
|
}
|
||||||
|
} catch (fallbackError) {
|
||||||
|
console.error('Fallback failed:', fallbackError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
player.isFallbackRetry = false;
|
||||||
|
|
||||||
// Skip to next track on error to prevent queue stalling
|
// Skip to next track on error to prevent queue stalling
|
||||||
if (player.currentTrack) {
|
if (player.currentTrack) {
|
||||||
console.warn('Skipping to next track due to playback error');
|
console.warn('Skipping to next track due to playback error');
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ export class Player {
|
||||||
this.currentTrack = null;
|
this.currentTrack = null;
|
||||||
this.currentRgValues = null;
|
this.currentRgValues = null;
|
||||||
this.userVolume = parseFloat(localStorage.getItem('volume') || '0.7');
|
this.userVolume = parseFloat(localStorage.getItem('volume') || '0.7');
|
||||||
|
this.isFallbackRetry = false;
|
||||||
|
|
||||||
// Sleep timer properties
|
// Sleep timer properties
|
||||||
this.sleepTimer = null;
|
this.sleepTimer = null;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue