Files
BYW-VoiceHub/app/utils/lyric/parseLrc.ts
T
Henry_Du 4ce4649aaf
Build VoiceHub FPK / build-fpk (push) Failing after 56m5s
Build and Push Docker Image / build-and-push (push) Canceled after 1h9m35s
初次提交
2026-09-06 08:19:02 +08:00

70 lines
1.9 KiB
TypeScript

import type { LyricLine } from '@applemusic-like-lyrics/lyric'
const TIME_TAG_REGEX = /\[(\d{2}):(\d{2})\.(\d{2,3})\]/g
const META_TAG_REGEX = /^\[[a-z]+:/i
export const parseLrc = (lrcContent: string): LyricLine[] => {
if (!lrcContent) return []
const lines = lrcContent.split(/\r?\n/)
const result: LyricLine[] = []
for (const line of lines) {
const trimmedLine = line.trim()
if (!trimmedLine) continue
// 跳过元数据
if (META_TAG_REGEX.test(trimmedLine)) continue
const matches = [...trimmedLine.matchAll(TIME_TAG_REGEX)]
if (matches.length === 0) continue
// 提取歌词文本(移除所有时间标签)
const text = trimmedLine.replace(TIME_TAG_REGEX, '').trim()
// 允许空行(作为间奏),但通常我们忽略完全空的行,除非为了显示间隔
if (!text) continue
// 处理一行多个时间标签的情况(重复歌词)
for (const match of matches) {
const min = parseInt(match[1], 10)
const sec = parseInt(match[2], 10)
// 补齐毫秒
const msStr = match[3].padEnd(3, '0').slice(0, 3)
const ms = parseInt(msStr, 10)
const startTime = min * 60 * 1000 + sec * 1000 + ms
result.push({
startTime,
endTime: 0, // 稍后计算
words: [{ word: text, startTime, endTime: 0, romanWord: '' }],
translatedLyric: '',
romanLyric: '',
isBG: false,
isDuet: false
})
}
}
// 按时间排序
result.sort((a, b) => a.startTime - b.startTime)
// 计算结束时间
for (let i = 0; i < result.length; i++) {
const line = result[i]
const nextLine = result[i + 1]
if (nextLine) {
line.endTime = nextLine.startTime
} else {
line.endTime = line.startTime + 5000 // 最后一行默认 5秒
}
// 更新单词结束时间
if (line.words.length > 0) {
line.words[0].endTime = line.endTime
}
}
return result
}