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, album: album.value,
}) })
} }
await playQueue.replaceQueue(newQueue) playQueue.replaceQueue(newQueue)
await playState.togglePlay(true) playState.togglePlay(true)
} }
function shuffle() { function shuffle() {

View File

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