fix: lyrics sync offset tag + 200ms lookahead

- Parse [offset:N] metadata from LRC files (was silently ignored, caused ~1s drift)
- Apply 200ms lookahead so active line highlights slightly before it's sung

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-04-26 22:38:20 +02:00
1 parent af03061f75
commit 9f68deea94
1 file changed
+9 -1
+9 -1
View File
@@ -474,12 +474,19 @@ export function switchNpTab(tab) {
let _lyricsLines = [];
let _lyricsSongId = null;
const LYRICS_LOOKAHEAD_MS = 200; // highlight line this many ms before its timestamp
function _parseLrc(text) {
let offsetMs = 0;
const lines = [];
for(const raw of text.split('\n')) {
const offM = raw.match(/^\[offset:\s*([+-]?\d+)\s*\]/i);
if(offM) { offsetMs = parseInt(offM[1]); continue; }
const m = raw.match(/^\[(\d+):(\d+(?:\.\d+)?)\](.*)/);
if(m) lines.push({ start: Math.round((parseInt(m[1])*60 + parseFloat(m[2]))*1000), value: m[3].trim() });
}
// [offset:N] shifts all timestamps by N ms (positive = lines appear later)
if(offsetMs) lines.forEach(l => l.start = Math.max(0, l.start + offsetMs));
return lines.sort((a,b) => a.start - b.start).filter(l => l.value);
}
@@ -559,9 +566,10 @@ async function _loadNpLyrics(songId) {
export function updateLyricsHighlight(currentMs) {
if(!_lyricsLines.length || !S.npLyricsMode) return;
const adjusted = currentMs + LYRICS_LOOKAHEAD_MS;
let activeIdx = -1;
for(let i = 0; i < _lyricsLines.length; i++) {
if(_lyricsLines[i].start <= currentMs) activeIdx = i;
if(_lyricsLines[i].start <= adjusted) activeIdx = i;
else break;
}
_lyricsLines.forEach((line, i) => {