Skip to content

Commit 341c472

Browse files
committed
✨ opt: 补充playback模式下的手动延迟补偿
1 parent 558bd26 commit 341c472

6 files changed

Lines changed: 58 additions & 1 deletion

File tree

src/components/Setting/config/lyric.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,21 @@ export const useLyricSettings = (): SettingConfig => {
368368
}),
369369
defaultValue: 500,
370370
},
371+
{
372+
key: "lyricSyncOffset",
373+
label: "歌词同步微调",
374+
type: "input-number",
375+
description: "手动调整歌词与声音的同步,正值歌词提前,负值歌词延后。",
376+
min: -1000,
377+
max: 1000,
378+
step: 10,
379+
suffix: "ms",
380+
value: computed({
381+
get: () => settingStore.lyricSyncOffset,
382+
set: (v) => (settingStore.lyricSyncOffset = v || 0),
383+
}),
384+
defaultValue: 0,
385+
},
371386
],
372387
},
373388
{

src/core/audio-player/AudioElementPlayer.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,10 @@ export class AudioElementPlayer extends BaseAudioPlayer {
196196
if (this.isInternalSeeking) {
197197
return this.targetSeekTime;
198198
}
199-
return (this.audioElement.currentTime || 0) - this.compensatedLatency;
199+
// 基础时间 - 自动延迟补偿 + 手动同步偏移
200+
return (
201+
(this.audioElement.currentTime || 0) - this.compensatedLatency + this.syncOffset / 1000
202+
);
200203
}
201204

202205
/** 获取是否暂停状态 */

src/core/audio-player/BaseAudioPlayer.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ export abstract class BaseAudioPlayer
6767

6868
protected compensatedLatency = 0;
6969

70+
/** 用户手动设置的歌词同步偏移量 (毫秒) */
71+
protected syncOffset = 0;
72+
7073
protected effectManager: AudioEffectManager | null = null;
7174

7275
/** 初始化状态 */
@@ -487,6 +490,14 @@ export abstract class BaseAudioPlayer
487490
return this.effectManager ? this.effectManager.getFilterGains() : [];
488491
}
489492

493+
/**
494+
* 设置歌词同步偏移
495+
* @param offset 偏移量 (毫秒)
496+
*/
497+
public setSyncOffset(offset: number): void {
498+
this.syncOffset = offset;
499+
}
500+
490501
/** 加载资源 */
491502
public abstract load(url: string): Promise<void>;
492503

src/core/audio-player/IPlaybackEngine.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ export interface IPlaybackEngine {
136136
*/
137137
getRate(): number;
138138

139+
/**
140+
* 设置歌词同步偏移量
141+
* @param offset 偏移量 (毫秒)
142+
*/
143+
setSyncOffset(offset: number): void;
144+
139145
/**
140146
* 设置音频输出设备
141147
* @param deviceId 设备 ID

src/core/player/AudioManager.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,15 @@ class AudioManager extends TypedEventTarget<AudioEventMap> implements IPlaybackE
366366
return this.engine.getRate();
367367
}
368368

369+
/**
370+
* 设置歌词同步偏移量
371+
* @param offset 偏移量 (毫秒)
372+
*/
373+
public setSyncOffset(offset: number): void {
374+
// FFmpeg 和 MPV 引擎可能没有实现此方法
375+
this.engine.setSyncOffset?.(offset);
376+
}
377+
369378
/**
370379
* 设置输出设备
371380
*/
@@ -504,6 +513,16 @@ export const useAudioManager = (): AudioManager => {
504513
settingStore.playbackEngine,
505514
settingStore.audioEngine,
506515
);
516+
517+
// 监听歌词同步偏移量变化
518+
watch(
519+
() => settingStore.lyricSyncOffset,
520+
(offset) => {
521+
win[AUDIO_MANAGER_KEY]?.setSyncOffset(offset);
522+
},
523+
{ immediate: true }, // 立即执行一次以应用初始值
524+
);
525+
507526
console.log(`[AudioManager] 创建新实例, engine: ${win[AUDIO_MANAGER_KEY].engineType}`);
508527
}
509528
return win[AUDIO_MANAGER_KEY];

src/stores/setting.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,8 @@ export interface SettingState {
260260
wordFadeWidth: number;
261261
/** 歌词时延调节步长(毫秒) */
262262
lyricOffsetStep: number;
263+
/** 歌词同步微调(毫秒) */
264+
lyricSyncOffset: number;
263265
/** 启用在线 TTML 歌词 */
264266
enableOnlineTTMLLyric: boolean;
265267
/** 启用 QM 歌词 */
@@ -610,6 +612,7 @@ export const useSettingStore = defineStore("setting", {
610612
hidePassedLines: false,
611613
wordFadeWidth: 0.5,
612614
lyricOffsetStep: 500,
615+
lyricSyncOffset: 0,
613616
enableOnlineTTMLLyric: false,
614617
enableQQMusicLyric: false,
615618
lyricPriority: "auto",

0 commit comments

Comments
 (0)