mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-23 15:47:23 +08:00
feat: 优化播放检测逻辑
This commit is contained in:
@@ -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('恢复播放失败,请手动点击播放');
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user