feat: light lyrics slightly ahead of the audio
This commit is contained in:
1 parent
55be743e8a
commit
659096ed60
4 files changed
+15
-4
No files matched your search
@@ -17,6 +17,8 @@ const yrcWordTag = /\((\d+),(\d+),\d+\)/g
|
||||
// 逐字歌词没有空白行,要靠行尾和下一行的间隔判断间奏。间隔太短就算作换气:清除高亮再点亮会闪烁。
|
||||
const interludeGapMs = 3000
|
||||
const maxTranslationGapMs = 500
|
||||
// 字亮起和声音同时发生时,看起来反而慢半拍。
|
||||
export const lyricLeadMs = 100
|
||||
|
||||
export function parseLrc(lrc: string): LyricLine[] {
|
||||
const lines: LyricLine[] = []
|
||||
|
||||
@@ -50,6 +50,15 @@ describe('lyricsStore', () => {
|
||||
expect(lyricsStore.state.index).toBe(1)
|
||||
})
|
||||
|
||||
it('比播放位置提前 100ms 切换到下一行', async () => {
|
||||
const { lyricsStore, frames, play } = await setup()
|
||||
play(nowPlaying('1', { lyric: '[00:01.00]一\n[00:02.00]二' }))
|
||||
frames.emit(1899)
|
||||
expect(lyricsStore.state.index).toBe(0)
|
||||
frames.emit(1900)
|
||||
expect(lyricsStore.state.index).toBe(1)
|
||||
})
|
||||
|
||||
it('同一首歌的新快照不重建歌词行,离开房间后清空', async () => {
|
||||
const { lyricsStore, play } = await setup()
|
||||
play(nowPlaying('1'))
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { LyricLine } from './lrc'
|
||||
import { roomStore } from '@/core/room'
|
||||
import { playerStore } from '@/features/playback'
|
||||
import { Store } from '@/shared/lib/store'
|
||||
import { buildLines, lineIndexAt } from './lrc'
|
||||
import { buildLines, lineIndexAt, lyricLeadMs } from './lrc'
|
||||
|
||||
class LyricsStore extends Store<{ lines: LyricLine[], index: number }> {
|
||||
#track = ''
|
||||
@@ -28,7 +28,7 @@ class LyricsStore extends Store<{ lines: LyricLine[], index: number }> {
|
||||
}
|
||||
|
||||
#sync(positionMs: number): void {
|
||||
this.setState({ index: lineIndexAt(this.state.lines, positionMs) })
|
||||
this.setState({ index: lineIndexAt(this.state.lines, positionMs + lyricLeadMs) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { playerStore } from '@/features/playback'
|
||||
import { performanceStore } from '@/features/settings'
|
||||
import { useStore } from '@/shared/lib/use-store'
|
||||
import { EmptyState } from '@/shared/ui'
|
||||
import { wordEmphasis, wordProgress } from './lrc'
|
||||
import { lyricLeadMs, wordEmphasis, wordProgress } from './lrc'
|
||||
import { lyricsStore } from './lyrics-store'
|
||||
import './lyrics.css'
|
||||
|
||||
@@ -98,7 +98,7 @@ export function Lyrics() {
|
||||
const paintWords = (positionMs: number) => {
|
||||
const smooth = performanceStore.smoothMotion()
|
||||
for (const item of activeWords) {
|
||||
const progress = wordProgress(item.word, positionMs)
|
||||
const progress = wordProgress(item.word, positionMs + lyricLeadMs)
|
||||
// 不需要流畅动效时按字切换,每帧不用重绘。
|
||||
const fill = smooth ? progress : Math.ceil(progress)
|
||||
if (fill !== item.fill) {
|
||||
|
||||
Reference in new issue
Block a user