UNPKG

native-lyrics-tools

Version:

A JavaScript library for parsing and generating various lyric formats.

95 lines (81 loc) 2.52 kB
function parseTime(str) { const match = str.match(/^\[(\d+):(\d+)[.:](\d{1,3})]/); if (!match) throw new Error(`Invalid timestamp: ${str}`); const minutes = parseInt(match[1], 10); const seconds = parseInt(match[2], 10); let milliseconds = match[3].padEnd(3, '0'); // Normalize to 3 digits milliseconds = parseInt(milliseconds, 10); const totalMs = minutes * 60000 + seconds * 1000 + milliseconds; const remaining = str.slice(match[0].length); return { remaining, time: totalMs }; } function parseLine(line) { const timeRegex = /\[\d+:\d+[.:]\d{1,3}]/g; const matches = [...line.matchAll(timeRegex)]; if (matches.length === 0) return []; const times = matches.map(match => parseTime(match[0]).time); const textStart = matches[matches.length - 1].index + matches[matches.length - 1][0].length; const lyricText = line.slice(textStart).trim(); if (!lyricText) return []; return times.map(t => ({ start_time: t, end_time: 0, words: [{ start_time: t, end_time: 0, word: lyricText }] })); } function parseLRC(src) { const result = []; const lines = src.split(/\r?\n/); for (const line of lines) { try { const parsed = parseLine(line); if (parsed.length > 0) { result.push(...parsed); } } catch (e) { continue; } } result.sort((a, b) => a.start_time - b.start_time); let lastEndTime = Number.MAX_SAFE_INTEGER; for (let i = result.length - 1; i >= 0; i--) { const line = result[i]; line.end_time = lastEndTime; if (line.words.length > 0) { line.words[0].end_time = lastEndTime; } lastEndTime = line.start_time; } // Optional: insert timing adjustments with a separate `processLyrics()` if needed return result; } function writeTimestamp(time) { const ms = time % 1000; const sec = Math.floor(time / 1000) % 60; const min = Math.floor(time / 60000); return `[${String(min).padStart(2, '0')}:${String(sec).padStart(2, '0')}.${String(ms).padStart(3, '0')}]`; } function stringifyLRC(lines) { let result = ''; for (const line of lines) { if (!line.words.length) continue; result += writeTimestamp(line.words[0].start_time); for (const word of line.words) { result += word.word; } result += '\n'; } return result; } // Exported ES module API export { parseTime, parseLine, parseLRC, stringifyLRC, writeTimestamp };