Pre-buffering next song musicplayer

This commit is contained in:
Filipinos 2025-07-28 19:02:06 +02:00
parent be3b82fe27
commit 9c7c57d41f

View File

@ -9,7 +9,10 @@ export class MusicPlayer {
this.displayedSongs = [];
this.indiceActual = -1;
this.isPlaying = false;
this.audioPlayer = document.getElementById("audioPlayer");
this.preloaderAudio = document.createElement('audio');
this.currentArtist = "";
this.currentAlbumId = null;
this.currentSongId = null;
@ -26,6 +29,7 @@ export class MusicPlayer {
this.isReady = false;
this.isInitializing = false;
this.miniplayerManuallyClosed = false;
this.isPreloading = false;
}
setDB(databaseInstance) {
@ -117,9 +121,19 @@ export class MusicPlayer {
}
});
this.audioPlayer.addEventListener("ended", () => this.handleAudioEnded());
this.audioPlayer.addEventListener("timeupdate", () => this.updateProgressBar());
this.audioPlayer.addEventListener("timeupdate", () => this.handleTimeUpdate());
this.audioPlayer.addEventListener("error", () => this.handleAudioErrorEvent());
this.audioPlayer.addEventListener("volumechange", () => {
this.preloaderAudio.volume = this.audioPlayer.volume;
});
this.preloaderAudio.addEventListener("error", (e) => {
this.isPreloading = false;
});
this.preloaderAudio.addEventListener("canplaythrough", () => {
this.isPreloading = true;
});
const progressBarContainer = document.getElementById('progressBarContainer');
progressBarContainer.addEventListener('click', (event) => this.seek(event));
progressBarContainer.addEventListener('mousemove', (event) => this.updateSeekHover(event));
@ -138,9 +152,9 @@ export class MusicPlayer {
if (this.shuffleMode) {
this.shuffleArray(this.cancionesActuales);
const newIndex = this.cancionesActuales.findIndex(s => s.id === this.displayedSongs[index].id);
this.playSong(this.cancionesActuales[newIndex], newIndex);
this.playSong(newIndex);
} else {
this.playSong(this.cancionesActuales[index], index);
this.playSong(index);
}
}
}
@ -187,7 +201,7 @@ export class MusicPlayer {
return document.querySelector("#tokenSelectorContainer .select-selected span").dataset.value;
}
handleAudioEnded() { this.playNext(); }
handleAudioEnded() { this.playNext(true); }
handleAudioErrorEvent() { this.handleAudioError(_('playbackError')); }
togglePlayerVisibility() {
@ -583,10 +597,59 @@ export class MusicPlayer {
gsap.from(".album-group", { duration: 0.5, opacity: 0, y: 20, stagger: 0.1, ease: "power3.out" });
}
playSong(cancion, index) {
if (!this.isReady || !this.audioPlayer || !cancion || !cancion.url) return;
const songItemElement = document.querySelector(`.song-item[data-index='${index}']`);
_getNextSongIndex() {
if (this.cancionesActuales.length === 0) return -1;
if (this.shuffleMode) {
if (this.cancionesActuales.length <= 1) return 0;
let nextIndex;
do {
nextIndex = Math.floor(Math.random() * this.cancionesActuales.length);
} while (nextIndex === this.indiceActual);
return nextIndex;
}
return (this.indiceActual + 1) % this.cancionesActuales.length;
}
_getPreviousSongIndex() {
if (this.cancionesActuales.length === 0) return -1;
if (this.shuffleMode) {
return this._getNextSongIndex();
}
return (this.indiceActual - 1 + this.cancionesActuales.length) % this.cancionesActuales.length;
}
preloadNextSong() {
this.isPreloading = false;
const nextIndex = this._getNextSongIndex();
if (nextIndex === -1 || nextIndex === this.indiceActual) return;
const nextSong = this.cancionesActuales[nextIndex];
if (nextSong && nextSong.url) {
this.preloaderAudio.innerHTML = '';
const source = document.createElement('source');
source.src = nextSong.url;
source.type = this.getMimeType(nextSong.extension);
this.preloaderAudio.appendChild(source);
this.preloaderAudio.load();
}
}
handleTimeUpdate() {
this.updateProgressBar();
if (this.audioPlayer.duration && this.audioPlayer.currentTime > this.audioPlayer.duration - 15) {
if (!this.isPreloading && this.preloaderAudio.currentSrc === '') {
this.preloadNextSong();
}
}
}
playSong(index, fromNext = false) {
if (!this.isReady || !this.audioPlayer || index < 0 || !this.cancionesActuales[index]) return;
const cancion = this.cancionesActuales[index];
this.indiceActual = index;
const songItemElement = document.querySelector(`.song-item[data-id='${cancion.id}']`);
const playIconElement = songItemElement ? songItemElement.querySelector('.play-icon') : null;
if (playIconElement) {
@ -599,12 +662,6 @@ export class MusicPlayer {
}
document.body.classList.add('miniplayer-active');
this.audioPlayer.innerHTML = '';
const source = document.createElement('source');
source.src = cancion.url;
source.type = this.getMimeType(cancion.extension);
this.audioPlayer.appendChild(source);
const tl = gsap.timeline();
tl.to(['#albumCover', '#trackTitle', '#trackArtist'], { opacity: 0, y: -10, duration: 0.2, ease: "power2.in", stagger: 0.05 })
.add(() => {
@ -614,11 +671,22 @@ export class MusicPlayer {
})
.to(['#albumCover', '#trackTitle', '#trackArtist'], { opacity: 1, y: 0, duration: 0.4, ease: "power2.out", stagger: 0.07 });
if (fromNext && this.isPreloading) {
this.audioPlayer.innerHTML = this.preloaderAudio.innerHTML;
this.preloaderAudio.innerHTML = '';
this.isPreloading = false;
} else {
this.audioPlayer.innerHTML = '';
const source = document.createElement('source');
source.src = cancion.url;
source.type = this.getMimeType(cancion.extension);
this.audioPlayer.appendChild(source);
}
this.audioPlayer.load();
this.audioPlayer.play().then(() => {
this.isPlaying = true;
document.getElementById('playPauseBtn').innerHTML = '<i class="fas fa-pause"></i>';
this.indiceActual = index;
this.currentSongId = cancion.id;
this.currentSongArtistId = cancion.artistId;
this.markCurrentSong();
@ -629,6 +697,7 @@ export class MusicPlayer {
if (!this.miniplayerManuallyClosed) {
document.getElementById('fab-music-player').style.display = 'none';
}
this.preloadNextSong();
}).catch((error) => {
this.handleAudioError(_('playbackError'));
if (playIconElement) {
@ -658,38 +727,20 @@ export class MusicPlayer {
}
}
playNext() {
playNext(fromEnded = false) {
if (!this.isReady || this.cancionesActuales.length === 0) return;
let nextIndex;
if (this.shuffleMode) {
if (this.cancionesActuales.length <= 1) {
nextIndex = 0;
} else {
do {
nextIndex = Math.floor(Math.random() * this.cancionesActuales.length);
} while (nextIndex === this.indiceActual);
}
} else {
nextIndex = (this.indiceActual + 1) % this.cancionesActuales.length;
const nextIndex = this._getNextSongIndex();
if (nextIndex !== -1) {
this.playSong(nextIndex, fromEnded);
}
if (this.cancionesActuales[nextIndex]) this.playSong(this.cancionesActuales[nextIndex], nextIndex);
}
playPrevious() {
if (!this.isReady || this.cancionesActuales.length === 0) return;
let prevIndex;
if (this.shuffleMode) {
if (this.cancionesActuales.length <= 1) {
prevIndex = 0;
} else {
do {
prevIndex = Math.floor(Math.random() * this.cancionesActuales.length);
} while (prevIndex === this.indiceActual);
}
} else {
prevIndex = (this.indiceActual - 1 + this.cancionesActuales.length) % this.cancionesActuales.length;
const prevIndex = this._getPreviousSongIndex();
if (prevIndex !== -1) {
this.playSong(prevIndex);
}
if (this.cancionesActuales[prevIndex]) this.playSong(this.cancionesActuales[prevIndex], prevIndex);
}
toggleShuffle() {
@ -697,6 +748,7 @@ export class MusicPlayer {
this.shuffleMode = !this.shuffleMode;
document.getElementById('shuffleBtn').classList.toggle("active", this.shuffleMode);
showNotification(this.shuffleMode ? _('shuffleOn') : _('shuffleOff'), 'info', 1500);
this.preloadNextSong();
}
markCurrentSong() {