feat: 先重新手撸了一个无缝播放

如果用户调整了播放进度,需要重新调度音乐播放;同时,上一首下一首等也要看怎么办
在网页上搞这种东西真的很大脑发光……
This commit is contained in:
Astrian Zheng 2025-08-22 11:40:59 +10:00
parent 488854f46b
commit dae6210239
Signed by: Astrian
SSH Key Fingerprint: SHA256:rVnhx3DAKjujCwWE13aDl7uV6+9U1MvydLkNRXJrBiA

View File

@ -13,10 +13,16 @@ class WebAudioPlayer {
context: AudioContext context: AudioContext
audioBuffer: { [key: string]: AudioBuffer} audioBuffer: { [key: string]: AudioBuffer}
dummyAudio: HTMLAudioElement dummyAudio: HTMLAudioElement
currentTrackStartTime: number
currentSource: AudioBufferSourceNode | null
nextSource: AudioBufferSourceNode | null
constructor() { constructor() {
this.context = new window.AudioContext() this.context = new window.AudioContext()
this.audioBuffer = {} this.audioBuffer = {}
this.currentTrackStartTime = 0
this.currentSource = null
this.nextSource = null
// HTML Audio // HTML Audio
this.dummyAudio = new Audio() this.dummyAudio = new Audio()
@ -87,6 +93,7 @@ class WebAudioPlayer {
} }
} }
//
async loadResourceAndPlay() { async loadResourceAndPlay() {
try { try {
debugPlayer("从播放器实例内部获取播放项目:") debugPlayer("从播放器实例内部获取播放项目:")
@ -112,8 +119,12 @@ class WebAudioPlayer {
this.play() this.play()
} }
if (playQueue.nextTrack) if (playQueue.nextTrack) {
await loadBuffer(playQueue.nextTrack) await loadBuffer(playQueue.nextTrack)
this.preloadNextTrack()
} else {
this.nextSource = null
}
if (playQueue.previousTrack) if (playQueue.previousTrack)
await loadBuffer(playQueue.previousTrack) await loadBuffer(playQueue.previousTrack)
@ -125,12 +136,29 @@ class WebAudioPlayer {
} }
// //
async play() { play() {
debugPlayer("开始播放") debugPlayer("开始播放")
const source = this.context.createBufferSource() this.currentSource = this.context.createBufferSource()
source.buffer = this.audioBuffer[playQueue.currentTrack.song.cid] this.currentSource.buffer = this.audioBuffer[playQueue.currentTrack.song.cid]
source.connect(this.context.destination) this.currentSource.connect(this.context.destination)
source.start() this.currentSource.start()
if (!playQueue.nextTrack) return
//
//
this.currentTrackStartTime = this.context.currentTime
}
//
preloadNextTrack() {
this.nextSource = null
const nextTrackStartTime = this.currentTrackStartTime + this.audioBuffer[playQueue.currentTrack.song.cid].duration
debugPlayer(`下一首歌将在 ${nextTrackStartTime} 时间点接入`)
this.nextSource = this.context.createBufferSource()
this.nextSource.buffer = this.audioBuffer[playQueue.nextTrack.song.cid]
this.nextSource.connect(this.context.destination)
this.nextSource.start(nextTrackStartTime)
} }
pause() {} pause() {}