diff --git a/src/renderer/hooks/MusicHook.ts b/src/renderer/hooks/MusicHook.ts index b740c31..954005a 100644 --- a/src/renderer/hooks/MusicHook.ts +++ b/src/renderer/hooks/MusicHook.ts @@ -2,11 +2,9 @@ import { cloneDeep } from 'lodash'; import { createDiscreteApi } from 'naive-ui'; import { computed, type ComputedRef, nextTick, onUnmounted, ref, watch } from 'vue'; -import { getBilibiliAudioUrl } from '@/api/bilibili'; import useIndexedDB from '@/hooks/IndexDBHook'; import { audioService } from '@/services/audioService'; import type { usePlayerStore } from '@/store'; -import { getSongUrl } from '@/store/modules/player'; import type { Artist, ILyricText, SongResult } from '@/types/music'; import { isElectron } from '@/utils'; import { getTextColors } from '@/utils/linearColor'; @@ -574,7 +572,12 @@ const setupAudioListeners = () => { }; export const play = () => { - audioService.getCurrentSound()?.play(); + const currentSound = audioService.getCurrentSound(); + if (currentSound) { + currentSound.play(); + // 在播放时也进行状态检测,防止URL已过期导致无声 + getPlayerStore().checkPlaybackState(getPlayerStore().playMusic); + } }; export const pause = () => { @@ -1042,86 +1045,17 @@ audioService.on('url_expired', async (expiredTrack) => { console.log('检测到URL过期事件,准备重新获取URL', expiredTrack.name); try { - const currentPosition = nowTime.value; // 保存当前播放进度 - console.log('保存当前播放进度:', currentPosition); + // 使用 handlePlayMusic 重新播放,它会自动处理 URL 获取和状态跟踪 + // 我们将 isFirstPlay 设为 true 以强制获取新 URL + const trackToPlay = { + ...expiredTrack, + isFirstPlay: true, + playMusicUrl: undefined + }; - // 处理B站视频 - if (expiredTrack.source === 'bilibili' && expiredTrack.bilibiliData) { - console.log('重新获取B站视频URL'); - try { - // 使用API中的函数获取B站音频URL - const newUrl = await getBilibiliAudioUrl( - expiredTrack.bilibiliData.bvid, - expiredTrack.bilibiliData.cid - ); + await getPlayerStore().handlePlayMusic(trackToPlay, getPlayerStore().play); - console.log('成功获取新的B站URL:', newUrl); - - // 更新存储 - (expiredTrack as any).playMusicUrl = newUrl; - getPlayerStore().playMusicUrl = newUrl; - - // 重新播放并设置进度 - const newSound = await audioService.play(newUrl, expiredTrack); - sound.value = newSound as Howl; - - // 恢复播放进度 - if (currentPosition > 0) { - newSound.seek(currentPosition); - nowTime.value = currentPosition; - console.log('恢复播放进度:', currentPosition); - } - - // 如果之前是播放状态,继续播放 - if (getPlayerStore().play) { - newSound.play(); - getPlayerStore().setIsPlay(true); - } - - message.success('已自动恢复播放'); - } catch (error) { - console.error('重新获取B站URL失败:', error); - message.error('重新获取音频地址失败,请手动点击播放'); - } - } else if (expiredTrack.source === 'netease') { - // 处理网易云音乐,重新获取URL - console.log('重新获取网易云音乐URL'); - try { - const newUrl = await getSongUrl(expiredTrack.id, expiredTrack as any); - - if (newUrl) { - console.log('成功获取新的网易云URL:', newUrl); - - // 更新存储 - (expiredTrack as any).playMusicUrl = newUrl; - getPlayerStore().playMusicUrl = newUrl; - - // 重新播放并设置进度 - const newSound = await audioService.play(newUrl, expiredTrack); - sound.value = newSound as Howl; - - // 恢复播放进度 - if (currentPosition > 0) { - newSound.seek(currentPosition); - nowTime.value = currentPosition; - console.log('恢复播放进度:', currentPosition); - } - - // 如果之前是播放状态,继续播放 - if (getPlayerStore().play) { - newSound.play(); - getPlayerStore().setIsPlay(true); - } - - message.success('已自动恢复播放'); - } else { - throw new Error('获取URL失败'); - } - } catch (error) { - console.error('重新获取网易云URL失败:', error); - message.error('重新获取音频地址失败,请手动点击播放'); - } - } + message.success('已自动恢复播放'); } catch (error) { console.error('处理URL过期事件失败:', error); message.error('恢复播放失败,请手动点击播放'); diff --git a/src/renderer/store/modules/playerCore.ts b/src/renderer/store/modules/playerCore.ts index 4ef2cc4..b2c88dc 100644 --- a/src/renderer/store/modules/playerCore.ts +++ b/src/renderer/store/modules/playerCore.ts @@ -103,15 +103,18 @@ export const usePlayerCoreStore = defineStore( /** * 播放状态检测 */ - const checkPlaybackState = (song: SongResult, requestId: string, timeout: number = 4000) => { + const checkPlaybackState = (song: SongResult, requestId?: string, timeout: number = 4000) => { if (checkPlayTime) { clearTimeout(checkPlayTime); } const sound = audioService.getCurrentSound(); if (!sound) return; + // 如果没有提供 requestId,创建一个临时标识 + const actualRequestId = requestId || `check_${Date.now()}`; + const onPlayHandler = () => { - console.log('播放事件触发,歌曲成功开始播放'); + console.log(`[${actualRequestId}] 播放事件触发,歌曲成功开始播放`); audioService.off('play', onPlayHandler); audioService.off('playerror', onPlayErrorHandler); }; @@ -121,13 +124,14 @@ export const usePlayerCoreStore = defineStore( audioService.off('play', onPlayHandler); audioService.off('playerror', onPlayErrorHandler); - // 验证请求是否仍然有效 - if (!playbackRequestManager.isRequestValid(requestId)) { + // 如果有 requestId,验证其有效性 + if (requestId && !playbackRequestManager.isRequestValid(requestId)) { console.log('请求已过期,跳过重试'); return; } if (userPlayIntent.value && play.value) { + console.log('播放失败,尝试刷新URL并重新播放'); playMusic.value.playMusicUrl = undefined; const refreshedSong = { ...song, isFirstPlay: true }; await handlePlayMusic(refreshedSong, true); @@ -138,8 +142,8 @@ export const usePlayerCoreStore = defineStore( audioService.on('playerror', onPlayErrorHandler); checkPlayTime = setTimeout(() => { - // 验证请求是否仍然有效 - if (!playbackRequestManager.isRequestValid(requestId)) { + // 如果有 requestId,验证其有效性 + if (requestId && !playbackRequestManager.isRequestValid(requestId)) { console.log('请求已过期,跳过超时重试'); audioService.off('play', onPlayHandler); audioService.off('playerror', onPlayErrorHandler); diff --git a/src/renderer/store/modules/playlist.ts b/src/renderer/store/modules/playlist.ts index 1bfd9b8..12e7313 100644 --- a/src/renderer/store/modules/playlist.ts +++ b/src/renderer/store/modules/playlist.ts @@ -398,7 +398,12 @@ export const usePlaylistStore = defineStore( console.log( `[nextPlay] 尝试播放: ${nextSong.name}, 索引: ${currentIndex} -> ${nowPlayListIndex}, 单曲重试: ${singleTrackRetryCount}/${SINGLE_TRACK_MAX_RETRIES}, 连续失败: ${consecutiveFailCount.value}/${MAX_CONSECUTIVE_FAILS}` ); - console.log('[nextPlay] Current mode:', playMode.value, 'Playlist length:', playList.value.length); + console.log( + '[nextPlay] Current mode:', + playMode.value, + 'Playlist length:', + playList.value.length + ); // 先尝试播放歌曲 const success = await playerCore.handlePlayMusic(nextSong, true); @@ -408,7 +413,10 @@ export const usePlaylistStore = defineStore( consecutiveFailCount.value = 0; playListIndex.value = nowPlayListIndex; console.log(`[nextPlay] 播放成功,索引已更新为: ${nowPlayListIndex}`); - console.log('[nextPlay] New current song in list:', playList.value[playListIndex.value]?.name); + console.log( + '[nextPlay] New current song in list:', + playList.value[playListIndex.value]?.name + ); sleepTimerStore.handleSongChange(); } else { console.error(`[nextPlay] 播放失败: ${nextSong.name}`); @@ -568,7 +576,8 @@ export const usePlaylistStore = defineStore( const sound = audioService.getCurrentSound(); if (sound) { sound.play(); - // checkPlaybackState 已在 playAudio 中自动调用,无需在这里重复调用 + // 在恢复播放时也进行状态检测,防止URL已过期导致无声 + playerCore.checkPlaybackState(playerCore.playMusic); } } return;