mirror of
https://github.com/imsyy/SPlayer.git
synced 2025-11-25 19:37:35 +08:00
🐞 fix: 修复歌词管理引用错误
This commit is contained in:
@@ -13,10 +13,6 @@ import { isEmpty } from "lodash-es";
|
|||||||
// 然后根据配置的歌词排除内容来处理
|
// 然后根据配置的歌词排除内容来处理
|
||||||
// 然后写入 store
|
// 然后写入 store
|
||||||
class LyricManager {
|
class LyricManager {
|
||||||
// Store
|
|
||||||
private musicStore = useMusicStore();
|
|
||||||
private statusStore = useStatusStore();
|
|
||||||
private settingStore = useSettingStore();
|
|
||||||
/**
|
/**
|
||||||
* 在线歌词请求序列
|
* 在线歌词请求序列
|
||||||
* 每次发起新请求递增
|
* 每次发起新请求递增
|
||||||
@@ -32,11 +28,13 @@ class LyricManager {
|
|||||||
* 包括清空歌词数据、重置歌词索引、关闭 TTMLL 歌词等
|
* 包括清空歌词数据、重置歌词索引、关闭 TTMLL 歌词等
|
||||||
*/
|
*/
|
||||||
private resetSongLyric() {
|
private resetSongLyric() {
|
||||||
|
const musicStore = useMusicStore();
|
||||||
|
const statusStore = useStatusStore();
|
||||||
// 重置歌词数据
|
// 重置歌词数据
|
||||||
this.musicStore.setSongLyric({}, true);
|
musicStore.setSongLyric({}, true);
|
||||||
this.statusStore.usingTTMLLyric = false;
|
statusStore.usingTTMLLyric = false;
|
||||||
// 重置歌词索引
|
// 重置歌词索引
|
||||||
this.statusStore.lyricIndex = -1;
|
statusStore.lyricIndex = -1;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 歌词内容对齐
|
* 歌词内容对齐
|
||||||
@@ -101,13 +99,16 @@ class LyricManager {
|
|||||||
* @returns 歌词数据
|
* @returns 歌词数据
|
||||||
*/
|
*/
|
||||||
private async handleOnlineLyric(id: number): Promise<SongLyric> {
|
private async handleOnlineLyric(id: number): Promise<SongLyric> {
|
||||||
|
const musicStore = useMusicStore();
|
||||||
|
const statusStore = useStatusStore();
|
||||||
|
const settingStore = useSettingStore();
|
||||||
|
// 请求序列
|
||||||
const req = this.activeLyricReq;
|
const req = this.activeLyricReq;
|
||||||
const settingStore = this.settingStore;
|
|
||||||
// 请求是否成功
|
// 请求是否成功
|
||||||
let adopted = false;
|
let adopted = false;
|
||||||
let result: SongLyric = { lrcData: [], yrcData: [] };
|
let result: SongLyric = { lrcData: [], yrcData: [] };
|
||||||
// 过期判断
|
// 过期判断
|
||||||
const isStale = () => this.activeLyricReq !== req || this.musicStore.playSong?.id !== id;
|
const isStale = () => this.activeLyricReq !== req || musicStore.playSong?.id !== id;
|
||||||
// 处理 TTML 歌词
|
// 处理 TTML 歌词
|
||||||
const adoptTTML = async () => {
|
const adoptTTML = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -161,7 +162,7 @@ class LyricManager {
|
|||||||
};
|
};
|
||||||
// 统一判断与设置 TTML
|
// 统一判断与设置 TTML
|
||||||
await Promise.allSettled([adoptTTML(), adoptLRC()]);
|
await Promise.allSettled([adoptTTML(), adoptLRC()]);
|
||||||
this.statusStore.usingTTMLLyric = Boolean(
|
statusStore.usingTTMLLyric = Boolean(
|
||||||
settingStore.enableTTMLLyric && result.yrcData?.length && !result.lrcData?.length,
|
settingStore.enableTTMLLyric && result.yrcData?.length && !result.lrcData?.length,
|
||||||
);
|
);
|
||||||
return result;
|
return result;
|
||||||
@@ -173,6 +174,7 @@ class LyricManager {
|
|||||||
*/
|
*/
|
||||||
private async handleLocalLyric(path: string): Promise<SongLyric> {
|
private async handleLocalLyric(path: string): Promise<SongLyric> {
|
||||||
try {
|
try {
|
||||||
|
const statusStore = useStatusStore();
|
||||||
const { lyric, format }: { lyric?: string; format?: "lrc" | "ttml" } =
|
const { lyric, format }: { lyric?: string; format?: "lrc" | "ttml" } =
|
||||||
await window.electron.ipcRenderer.invoke("get-music-lyric", path);
|
await window.electron.ipcRenderer.invoke("get-music-lyric", path);
|
||||||
if (!lyric) return { lrcData: [], yrcData: [] };
|
if (!lyric) return { lrcData: [], yrcData: [] };
|
||||||
@@ -180,13 +182,13 @@ class LyricManager {
|
|||||||
if (format === "ttml") {
|
if (format === "ttml") {
|
||||||
const ttml = parseTTML(lyric);
|
const ttml = parseTTML(lyric);
|
||||||
const lines = ttml?.lines || [];
|
const lines = ttml?.lines || [];
|
||||||
this.statusStore.usingTTMLLyric = true;
|
statusStore.usingTTMLLyric = true;
|
||||||
return { lrcData: [], yrcData: lines };
|
return { lrcData: [], yrcData: lines };
|
||||||
}
|
}
|
||||||
// 解析本地歌词并对其
|
// 解析本地歌词并对其
|
||||||
const lrcLines = parseLrc(lyric);
|
const lrcLines = parseLrc(lyric);
|
||||||
const aligned = this.alignLocalLyrics({ lrcData: lrcLines, yrcData: [] });
|
const aligned = this.alignLocalLyrics({ lrcData: lrcLines, yrcData: [] });
|
||||||
this.statusStore.usingTTMLLyric = false;
|
statusStore.usingTTMLLyric = false;
|
||||||
return aligned;
|
return aligned;
|
||||||
} catch {
|
} catch {
|
||||||
return { lrcData: [], yrcData: [] };
|
return { lrcData: [], yrcData: [] };
|
||||||
@@ -199,16 +201,49 @@ class LyricManager {
|
|||||||
*/
|
*/
|
||||||
private async checkLocalLyricOverride(id: number): Promise<SongLyric> {
|
private async checkLocalLyricOverride(id: number): Promise<SongLyric> {
|
||||||
console.log("检测本地歌词覆盖", id);
|
console.log("检测本地歌词覆盖", id);
|
||||||
const { localLyricPath } = this.settingStore;
|
const statusStore = useStatusStore();
|
||||||
|
const settingStore = useSettingStore();
|
||||||
|
const { localLyricPath } = settingStore;
|
||||||
if (!isElectron || !localLyricPath.length) return { lrcData: [], yrcData: [] };
|
if (!isElectron || !localLyricPath.length) return { lrcData: [], yrcData: [] };
|
||||||
// 从本地遍历
|
// 从本地遍历
|
||||||
|
try {
|
||||||
|
const lyricDirs = Array.isArray(localLyricPath) ? localLyricPath.map((p) => String(p)) : [];
|
||||||
|
// 读取本地歌词
|
||||||
const { lrc, ttml } = await window.electron.ipcRenderer.invoke(
|
const { lrc, ttml } = await window.electron.ipcRenderer.invoke(
|
||||||
"read-local-lyric",
|
"read-local-lyric",
|
||||||
localLyricPath,
|
lyricDirs,
|
||||||
id,
|
id,
|
||||||
);
|
);
|
||||||
this.statusStore.usingTTMLLyric = Boolean(ttml);
|
statusStore.usingTTMLLyric = Boolean(ttml);
|
||||||
return { lrcData: parseLrc(lrc || ""), yrcData: parseTTML(ttml || "").lines || [] };
|
let lrcLines: LyricLine[] = [];
|
||||||
|
let ttmlLines: LyricLine[] = [];
|
||||||
|
// 安全解析 LRC
|
||||||
|
try {
|
||||||
|
const lrcContent = typeof lrc === "string" ? lrc : "";
|
||||||
|
if (lrcContent) {
|
||||||
|
lrcLines = parseLrc(lrcContent);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("parseLrc 本地解析失败:", err);
|
||||||
|
lrcLines = [];
|
||||||
|
}
|
||||||
|
// 安全解析 TTML
|
||||||
|
try {
|
||||||
|
const ttmlContent = typeof ttml === "string" ? ttml : "";
|
||||||
|
if (ttmlContent) {
|
||||||
|
ttmlLines = parseTTML(ttmlContent).lines || [];
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error("parseTTML 本地解析失败:", err);
|
||||||
|
statusStore.usingTTMLLyric = false;
|
||||||
|
ttmlLines = [];
|
||||||
|
}
|
||||||
|
return { lrcData: lrcLines, yrcData: ttmlLines };
|
||||||
|
} catch (error) {
|
||||||
|
console.error("读取本地歌词失败:", error);
|
||||||
|
statusStore.usingTTMLLyric = false;
|
||||||
|
return { lrcData: [], yrcData: [] };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 处理歌词排除
|
* 处理歌词排除
|
||||||
@@ -216,7 +251,8 @@ class LyricManager {
|
|||||||
* @returns 处理后的歌词数据
|
* @returns 处理后的歌词数据
|
||||||
*/
|
*/
|
||||||
private handleLyricExclude(lyricData: SongLyric): SongLyric {
|
private handleLyricExclude(lyricData: SongLyric): SongLyric {
|
||||||
const { enableExcludeLyrics, excludeKeywords, excludeRegexes } = this.settingStore;
|
const settingStore = useSettingStore();
|
||||||
|
const { enableExcludeLyrics, excludeKeywords, excludeRegexes } = settingStore;
|
||||||
// 未开启排除
|
// 未开启排除
|
||||||
if (!enableExcludeLyrics) return lyricData;
|
if (!enableExcludeLyrics) return lyricData;
|
||||||
// 处理正则表达式
|
// 处理正则表达式
|
||||||
@@ -254,17 +290,21 @@ class LyricManager {
|
|||||||
* @param path 本地歌词路径(可选)
|
* @param path 本地歌词路径(可选)
|
||||||
*/
|
*/
|
||||||
public async handleLyric(id: number, path?: string) {
|
public async handleLyric(id: number, path?: string) {
|
||||||
|
const musicStore = useMusicStore();
|
||||||
|
const statusStore = useStatusStore();
|
||||||
try {
|
try {
|
||||||
// 歌词加载状态
|
// 歌词加载状态
|
||||||
this.statusStore.lyricLoading = true;
|
statusStore.lyricLoading = true;
|
||||||
// 重置歌词
|
// 重置歌词
|
||||||
this.resetSongLyric();
|
this.resetSongLyric();
|
||||||
// 标记当前歌词请求(避免旧请求覆盖新请求)
|
// 标记当前歌词请求(避免旧请求覆盖新请求)
|
||||||
this.activeLyricReq = ++this.lyricReqSeq;
|
this.activeLyricReq = ++this.lyricReqSeq;
|
||||||
// 检查歌词覆盖
|
// 检查歌词覆盖
|
||||||
let lyricData = await this.checkLocalLyricOverride(id);
|
let lyricData = await this.checkLocalLyricOverride(id);
|
||||||
|
console.log("本地歌词覆盖", lyricData);
|
||||||
|
|
||||||
// 开始获取歌词
|
// 开始获取歌词
|
||||||
if (isEmpty(lyricData.lrcData) || isEmpty(lyricData.yrcData)) {
|
if (!isEmpty(lyricData.lrcData) || !isEmpty(lyricData.yrcData)) {
|
||||||
// 进行本地歌词对齐
|
// 进行本地歌词对齐
|
||||||
lyricData = this.alignLocalLyrics(lyricData);
|
lyricData = this.alignLocalLyrics(lyricData);
|
||||||
} else if (path) {
|
} else if (path) {
|
||||||
@@ -278,8 +318,8 @@ class LyricManager {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
} finally {
|
} finally {
|
||||||
// 歌词加载状态
|
// 歌词加载状态
|
||||||
if (this.musicStore.playSong?.id === undefined || this.activeLyricReq === this.lyricReqSeq) {
|
if (musicStore.playSong?.id === undefined || this.activeLyricReq === this.lyricReqSeq) {
|
||||||
this.statusStore.lyricLoading = false;
|
statusStore.lyricLoading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
import { isDev, isElectron } from "./env";
|
import { isDev, isElectron } from "./env";
|
||||||
import { getLyricData } from "./player-utils/lyric";
|
import { getLyricData } from "./player-utils/lyric";
|
||||||
import audioContextManager from "@/utils/player-utils/context";
|
import audioContextManager from "@/utils/player-utils/context";
|
||||||
|
import lyricManager from "./lyricManager";
|
||||||
import blob from "./blob";
|
import blob from "./blob";
|
||||||
|
|
||||||
// 播放器核心
|
// 播放器核心
|
||||||
@@ -248,6 +249,8 @@ class Player {
|
|||||||
// 获取歌曲附加信息 - 非电台和本地
|
// 获取歌曲附加信息 - 非电台和本地
|
||||||
if (type !== "radio" && !path) getLyricData(id);
|
if (type !== "radio" && !path) getLyricData(id);
|
||||||
else resetSongLyric();
|
else resetSongLyric();
|
||||||
|
// 获取歌词数据
|
||||||
|
lyricManager.handleLyric(id, path);
|
||||||
// 定时获取状态
|
// 定时获取状态
|
||||||
if (!this.playerInterval) this.handlePlayStatus();
|
if (!this.playerInterval) this.handlePlayStatus();
|
||||||
// 新增播放历史
|
// 新增播放历史
|
||||||
|
|||||||
Reference in New Issue
Block a user