diff --git a/src/i18n/lang/en-US/player.ts b/src/i18n/lang/en-US/player.ts
index 378ccc5..9efa1fc 100644
--- a/src/i18n/lang/en-US/player.ts
+++ b/src/i18n/lang/en-US/player.ts
@@ -11,6 +11,8 @@ export default {
mute: 'Mute',
unmute: 'Unmute',
songNum: 'Song Number: {num}',
+ addCorrection: 'Add {num} seconds',
+ subtractCorrection: 'Subtract {num} seconds',
playFailed: 'Play Failed, Play Next Song',
playMode: {
sequence: 'Sequence',
diff --git a/src/i18n/lang/zh-CN/player.ts b/src/i18n/lang/zh-CN/player.ts
index 7431b48..073b5c4 100644
--- a/src/i18n/lang/zh-CN/player.ts
+++ b/src/i18n/lang/zh-CN/player.ts
@@ -11,6 +11,8 @@ export default {
mute: '静音',
unmute: '取消静音',
songNum: '歌曲总数:{num}',
+ addCorrection: '提前 {num} 秒',
+ subtractCorrection: '延迟 {num} 秒',
playFailed: '当前歌曲播放失败,播放下一首',
playMode: {
sequence: '顺序播放',
diff --git a/src/renderer/components/lyric/LyricCorrectionControl.vue b/src/renderer/components/lyric/LyricCorrectionControl.vue
new file mode 100644
index 0000000..234bf7a
--- /dev/null
+++ b/src/renderer/components/lyric/LyricCorrectionControl.vue
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+ {{ t('player.subtractCorrection', { num: 0.2 }) }}
+
+
+ {{ props.correctionTime > 0 ? '+' : '' }}{{ props.correctionTime.toFixed(1) }}s
+
+
+
+
+
+
+
+ {{ t('player.addCorrection', { num: 0.2 }) }}
+
+
+
+
+
\ No newline at end of file
diff --git a/src/renderer/hooks/MusicHook.ts b/src/renderer/hooks/MusicHook.ts
index 9b8f1e9..95ac872 100644
--- a/src/renderer/hooks/MusicHook.ts
+++ b/src/renderer/hooks/MusicHook.ts
@@ -19,7 +19,6 @@ export const lrcTimeArray = ref([]); // 歌词时间数组
export const nowTime = ref(0); // 当前播放时间
export const allTime = ref(0); // 总播放时间
export const nowIndex = ref(0); // 当前播放歌词
-export const correctionTime = ref(0.4); // 歌词矫正时间Correction time
export const currentLrcProgress = ref(0); // 来存储当前歌词的进度
export const playMusic = computed(() => playerStore.playMusic as SongResult); // 当前播放歌曲
export const sound = ref(audioService.getCurrentSound());
@@ -482,25 +481,64 @@ export const pause = () => {
}
};
-// 增加矫正时间
-export const addCorrectionTime = (time: number) => (correctionTime.value += time);
+// 歌词矫正时间映射(每首歌独立)
+const CORRECTION_KEY = 'lyric-correction-map';
+const correctionTimeMap = ref>({});
-// 减少矫正时间
-export const reduceCorrectionTime = (time: number) => (correctionTime.value -= time);
+// 初始化 correctionTimeMap
+const loadCorrectionMap = () => {
+ try {
+ const raw = localStorage.getItem(CORRECTION_KEY);
+ correctionTimeMap.value = raw ? JSON.parse(raw) : {};
+ } catch {
+ correctionTimeMap.value = {};
+ }
+};
+const saveCorrectionMap = () => {
+ localStorage.setItem(CORRECTION_KEY, JSON.stringify(correctionTimeMap.value));
+};
+
+loadCorrectionMap();
+
+// 歌词矫正时间,当前歌曲
+export const correctionTime = ref(0);
+
+// 切歌时自动读取矫正时间
+watch(
+ () => playMusic.value?.id,
+ (id) => {
+ if (!id) return;
+ correctionTime.value = correctionTimeMap.value[id] ?? 0;
+ },
+ { immediate: true }
+);
+
+/**
+ * 调整歌词矫正时间(每首歌独立)
+ * @param delta 增加/减少的秒数(正为加,负为减)
+ */
+export const adjustCorrectionTime = (delta: number) => {
+ const id = playMusic.value?.id;
+ if (!id) return;
+ const newVal = Math.max(-10, Math.min(10, (correctionTime.value ?? 0) + delta));
+ correctionTime.value = newVal;
+ correctionTimeMap.value[id] = newVal;
+ saveCorrectionMap();
+};
// 获取当前播放歌词
export const isCurrentLrc = (index: number, time: number): boolean => {
const currentTime = lrcTimeArray.value[index];
const nextTime = lrcTimeArray.value[index + 1];
- const nowTime = time + correctionTime.value;
- const isTrue = nowTime > currentTime && nowTime < nextTime;
- return isTrue;
+ const correctedTime = time + correctionTime.value;
+ return correctedTime > currentTime && correctedTime < nextTime;
};
// 获取当前播放歌词INDEX
export const getLrcIndex = (time: number): number => {
+ const correctedTime = time + correctionTime.value;
for (let i = 0; i < lrcTimeArray.value.length; i++) {
- if (isCurrentLrc(i, time)) {
+ if (isCurrentLrc(i, correctedTime - correctionTime.value)) {
nowIndex.value = i;
return i;
}
@@ -517,15 +555,22 @@ const currentLrcTiming = computed(() => {
// 获取歌词样式
export const getLrcStyle = (index: number) => {
- if (index === nowIndex.value) {
+ const currentTime = nowTime.value + correctionTime.value;
+ const start = lrcTimeArray.value[index];
+ const end = lrcTimeArray.value[index + 1] ?? (start + 1);
+
+ if (currentTime >= start && currentTime < end) {
+ // 当前句,显示进度
+ const progress = ((currentTime - start) / (end - start)) * 100;
return {
- backgroundImage: `linear-gradient(to right, #ffffff ${currentLrcProgress.value}%, #ffffff8a ${currentLrcProgress.value}%)`,
+ backgroundImage: `linear-gradient(to right, #ffffff ${progress}%, #ffffff8a ${progress}%)`,
backgroundClip: 'text',
WebkitBackgroundClip: 'text',
color: 'transparent',
transition: 'background-image 0.1s linear'
};
}
+ // 其它句
return {};
};
diff --git a/src/renderer/layout/components/MusicFull.vue b/src/renderer/layout/components/MusicFull.vue
index 122048d..3788be3 100644
--- a/src/renderer/layout/components/MusicFull.vue
+++ b/src/renderer/layout/components/MusicFull.vue
@@ -135,12 +135,13 @@
{{ t('player.lrc.noLrc') }}
+
+
-
-
@@ -153,6 +154,7 @@ import { useI18n } from 'vue-i18n';
import LyricSettings from '@/components/lyric/LyricSettings.vue';
import MiniPlayBar from '@/components/player/MiniPlayBar.vue';
+import LyricCorrectionControl from '@/components/lyric/LyricCorrectionControl.vue';
import {
artistList,
lrcArray,
@@ -160,7 +162,9 @@ import {
playMusic,
setAudioTime,
textColors,
- useLyricProgress
+ useLyricProgress,
+ correctionTime,
+ adjustCorrectionTime
} from '@/hooks/MusicHook';
import { useArtist } from '@/hooks/useArtist';
import { usePlayerStore } from '@/store/modules/player';
@@ -797,4 +801,12 @@ defineExpose({
color: white;
animation: spin 1s linear infinite;
}
+
+.lyric-correction-btns-mac {
+ /* 仅在 hover 歌词区域时显示 */
+ .music-lrc:hover & {
+ opacity: 1 !important;
+ pointer-events: auto !important;
+ }
+}