feat: 替换播放列表时重新播放一轮

This commit is contained in:
Astrian Zheng 2025-08-22 20:02:50 +10:00
parent 03cd58b944
commit ea8d31a49d
Signed by: Astrian
SSH Key Fingerprint: SHA256:rVnhx3DAKjujCwWE13aDl7uV6+9U1MvydLkNRXJrBiA
2 changed files with 45 additions and 10 deletions

View File

@ -150,8 +150,8 @@ async function playTheAlbum(from: number = 0) {
album: album.value,
})
}
await playQueue.replaceQueue(newQueue)
await playState.togglePlay(true)
playQueue.replaceQueue(newQueue)
playState.togglePlay(true)
}
function shuffle() {

View File

@ -17,6 +17,7 @@ class WebAudioPlayer {
currentSource: AudioBufferSourceNode | null
nextSource: AudioBufferSourceNode | null
reportInterval: ReturnType<typeof setTimeout> | null
isInternalTrackChange: boolean
constructor() {
this.context = new window.AudioContext()
@ -25,6 +26,7 @@ class WebAudioPlayer {
this.currentSource = null
this.nextSource = null
this.reportInterval = null
this.isInternalTrackChange = false
// HTML Audio
this.dummyAudio = new Audio()
@ -146,8 +148,8 @@ class WebAudioPlayer {
if (!playQueue.currentTrack) return
//
if (this.currentSource && playState.actualPlaying) {
debugPlayer("已经在播放中,跳过")
if (this.currentSource && this.reportInterval) {
debugPlayer("已经在播放中,跳过重复播放")
return
}
@ -278,16 +280,32 @@ class WebAudioPlayer {
return
}
// 3.
// 3. watch
this.isInternalTrackChange = true
// 4.
playQueue.continueToNext()
this.currentSource = this.nextSource
this.nextSource = null
// 4.
// 5.
this.currentTrackStartTime = this.context.currentTime
this.reportProgress()
// 6. onended
if (this.currentSource) {
this.currentSource.onended = () => {
debugPlayer("当前歌曲播放结束")
if (!!this.reportInterval) {
debugPlayer("歌曲自然结束")
this.onTrackEnded()
} else {
debugPlayer("用户暂停")
}
}
}
// 5.
// 7.
if (playQueue.nextTrack) {
debugPlayer("处理下下一首歌")
if (this.audioBuffer[playQueue.nextTrack.song.cid]) {
@ -297,6 +315,11 @@ class WebAudioPlayer {
if (playState.actualPlaying) this.scheduleNextTrack()
}
}
// 8.
setTimeout(() => {
this.isInternalTrackChange = false
}, 100)
}
}
@ -315,7 +338,7 @@ watch(() => playQueue.currentTrack, (newTrack, oldTrack) => {
navigator.mediaSession.playbackState = playState.isPlaying ? 'playing' : 'paused'
navigator.mediaSession.metadata = new MediaMetadata({
title: newTrack.song.name,
artist: artistsOrganize(newTrack.song.artistes ?? []),
artist: artistsOrganize(newTrack.song.artistes ?? newTrack.song.artists ?? []),
album: newTrack.album?.name,
artwork: [
{ src: newTrack.album?.coverUrl ?? "", sizes: '500x500', type: 'image/png' },
@ -323,9 +346,9 @@ watch(() => playQueue.currentTrack, (newTrack, oldTrack) => {
})
}
// onTrackEnded
// onTrackEnded
// loadResourceAndPlay
if (!playState.actualPlaying || !oldTrack) {
if (!playerInstance.value?.isInternalTrackChange) {
playerInstance.value?.loadResourceAndPlay()
}
}
@ -340,6 +363,18 @@ watch(() => playState.isPlaying, () => {
playerInstance.value?.play()
}
})
watch(() => playQueue.queue, () => {
debugPlayer("检测到播放列表更新")
//
if (playQueue.queue.length === 0) {
debugPlayer("触发暂停播放")
//
playerInstance.value?.pause()
playState.togglePlay(false)
playState.reportPlayProgress(0)
}
})
</script>
<template>