Skip to content

Commit 31beaaa

Browse files
committed
🐞 fix: 修复歌曲播放异常阻断
1 parent 6063387 commit 31beaaa

3 files changed

Lines changed: 28 additions & 37 deletions

File tree

src/core/audio-player/AudioElementPlayer.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ export class AudioElementPlayer extends BaseAudioPlayer {
9999
this.doSeek(time);
100100
}
101101

102+
/**
103+
* 停止播放并清理当前音频源
104+
* 彻底移除 src,防止旧链接后续继续触发 canplay 等事件
105+
*/
106+
public stop(): void {
107+
super.stop();
108+
this.audioElement.removeAttribute("src");
109+
this.audioElement.load();
110+
}
111+
102112
/**
103113
* 执行底层 Seek
104114
* @param time 目标时间(秒)

src/core/automix/AutomixManager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1039,7 +1039,7 @@ export class AutomixManager {
10391039
// 提交状态切换
10401040
statusStore.playIndex = targetIndex;
10411041
statusStore.endAutomixFx();
1042-
playerController.setupSongUI(targetSong, audioSource, options.startSeek);
1042+
playerController.setupSongUI(targetSong, options.startSeek);
10431043
playerController.afterPlaySetup(targetSong);
10441044
},
10451045
},

src/core/player/PlayerController.ts

Lines changed: 17 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -185,18 +185,9 @@ class PlayerController {
185185
/**
186186
* 设置歌曲 UI 状态
187187
* @param song - 歌曲
188-
* @param audioSource - 音频源
189188
* @param startSeek - 开始seek时间
190189
*/
191-
public setupSongUI(
192-
song: SongType,
193-
audioSource: {
194-
url: string;
195-
quality: QualityType | undefined;
196-
source: AudioSourceType | undefined;
197-
},
198-
startSeek: number,
199-
) {
190+
public setupSongUI(song: SongType, startSeek: number) {
200191
const musicStore = useMusicStore();
201192
const statusStore = useStatusStore();
202193
const lyricManager = useLyricManager();
@@ -223,7 +214,7 @@ class PlayerController {
223214
});
224215
}
225216
// 更新任务栏歌词窗口的元数据
226-
const { name, artist, album } = getPlayerInfoObj() || {};
217+
const { name, artist, album } = getPlayerInfoObj(song) || {};
227218
const coverUrl = song.coverSize?.s || song.cover || "";
228219
playerIpc.sendTaskbarMetadata({
229220
title: name || "",
@@ -244,10 +235,6 @@ class PlayerController {
244235
}
245236
// 获取歌词
246237
lyricManager.handleLyric(song);
247-
console.log(`🎧 [${song.id}] 最终播放信息:`, audioSource);
248-
// 更新音质和解锁状态
249-
statusStore.songQuality = audioSource.quality;
250-
statusStore.audioSource = audioSource.source;
251238
}
252239

253240
/**
@@ -282,7 +269,7 @@ class PlayerController {
282269
statusStore.playLoading = false;
283270
// 初始化或无歌曲时
284271
if (!statusStore.playStatus && !autoPlay) return;
285-
throw new Error("SONG_NOT_FOUND");
272+
return;
286273
}
287274
// Fuck DJ Mode
288275
if (this.shouldSkipSong(playSongData)) {
@@ -293,15 +280,18 @@ class PlayerController {
293280
}
294281
try {
295282
// 立即停止当前播放 (除非是 Crossfade)
283+
statusStore.playLoading = true;
296284
if (!options.crossfade) {
297285
audioManager.stop();
298286
}
299-
statusStore.playLoading = true;
287+
// 立即更新 UI(歌曲信息、封面、歌词等),无需等待网络请求
288+
this.setupSongUI(playSongData, seek);
300289
const { audioSource, analysis, analysisKind } = await this.prepareAudioSource(
301290
playSongData,
302291
requestToken,
303292
{ analysis: options.crossfade ? "head" : "none" },
304293
);
294+
if (requestToken !== this.currentRequestToken) return;
305295
// Automix 分析应用
306296
const lastAnalysis = this.currentAnalysis;
307297
this.currentAnalysis = analysis;
@@ -322,8 +312,11 @@ class PlayerController {
322312
startSeek = automixParams.startSeek;
323313
initialRate = automixParams.initialRate;
324314
}
325-
// 设置 UI 状态
326-
this.setupSongUI(playSongData, audioSource, startSeek);
315+
if (requestToken !== this.currentRequestToken) return;
316+
// 更新音质和音源信息
317+
console.log(`🎧 [${playSongData.id}] 最终播放信息:`, audioSource);
318+
statusStore.songQuality = audioSource.quality;
319+
statusStore.audioSource = audioSource.source;
327320
// 执行底层播放
328321
await this.loadAndPlay(
329322
audioSource.url,
@@ -335,6 +328,7 @@ class PlayerController {
335328
if (requestToken !== this.currentRequestToken) return;
336329
// 后置处理
337330
await this.afterPlaySetup(playSongData);
331+
statusStore.playLoading = false;
338332
} catch (error) {
339333
if (requestToken === this.currentRequestToken) {
340334
console.error("❌ 播放初始化失败:", error);
@@ -375,6 +369,7 @@ class PlayerController {
375369
audioManager.stop();
376370
// 执行底层播放,保持进度,保持原播放状态
377371
await this.loadAndPlay(audioSource.url, shouldAutoPlay, seek);
372+
statusStore.playLoading = false;
378373
} catch (error) {
379374
console.error("❌ 切换音质失败:", error);
380375
statusStore.playLoading = false;
@@ -414,6 +409,7 @@ class PlayerController {
414409
// 停止当前播放
415410
audioManager.stop();
416411
await this.loadAndPlay(audioSource.url, shouldAutoPlay, seek);
412+
statusStore.playLoading = false;
417413
} catch (error) {
418414
console.error("❌ 切换音频源失败:", error);
419415
statusStore.playLoading = false;
@@ -671,24 +667,8 @@ class PlayerController {
671667
// 加载状态
672668
audioManager.addEventListener("loadstart", () => {
673669
statusStore.playLoading = true;
674-
// Watchdog: 如果 10秒后仍未 canplay/playing/error,强制取消 loading
675-
const token = this.currentRequestToken;
676-
setTimeout(() => {
677-
if (
678-
statusStore.playLoading &&
679-
token === this.currentRequestToken &&
680-
!statusStore.playStatus
681-
) {
682-
console.warn("⚠️ [Watchdog] Loading timeout, resetting state");
683-
statusStore.playLoading = false;
684-
}
685-
}, 10000);
686670
});
687671

688-
// 播放中 (兜底)
689-
audioManager.addEventListener("playing", () => {
690-
if (statusStore.playLoading) statusStore.playLoading = false;
691-
});
692672
// 加载完成
693673
audioManager.addEventListener("canplay", () => {
694674
const playSongData = getPlaySongData();
@@ -868,7 +848,6 @@ class PlayerController {
868848
}
869849
// 用户主动中止
870850
if (errCode === AudioErrorCode.ABORTED || errCode === AudioErrorCode.DOM_ABORT) {
871-
statusStore.playLoading = false;
872851
this.retryInfo.count = 0;
873852
return;
874853
}
@@ -1009,6 +988,8 @@ class PlayerController {
1009988
const songManager = useSongManager();
1010989
// 先暂停当前播放
1011990
const audioManager = useAudioManager();
991+
// 立即显示加载状态
992+
statusStore.playLoading = true;
1012993
audioManager.stop();
1013994
// 私人FM
1014995
if (statusStore.personalFmMode) {

0 commit comments

Comments
 (0)