@applemusic-like-lyrics/lyric 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -14
- package/dist/amll-lyric.cjs +717 -218
- package/dist/amll-lyric.cjs.map +1 -1
- package/dist/amll-lyric.d.cts +278 -131
- package/dist/amll-lyric.d.mts +278 -131
- package/dist/amll-lyric.mjs +714 -219
- package/dist/amll-lyric.mjs.map +1 -1
- package/package.json +6 -7
package/dist/amll-lyric.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"amll-lyric.mjs","names":["parseTTMLPacked"],"sources":["../src/utils.ts","../src/formats/ass.ts","../src/formats/eqrc/constants.ts","../src/formats/eqrc/custom-des.ts","../src/formats/eqrc/utils.ts","../src/formats/eqrc/index.ts","../src/formats/eslrc.ts","../src/formats/lys.ts","../src/formats/lqe.ts","../src/formats/lrc.ts","../src/formats/lrca2.ts","../src/formats/lyl.ts","../src/formats/qrc.ts","../src/formats/ttml.ts","../src/formats/yrc.ts","../src/index.ts"],"sourcesContent":["import type { LyricLine, LyricWord } from \"./types\";\n\nexport const createLine = (line: Partial<LyricLine>): LyricLine => ({\n\twords: [],\n\ttranslatedLyric: \"\",\n\tromanLyric: \"\",\n\tisBG: false,\n\tisDuet: false,\n\tstartTime: 0,\n\tendTime: 0,\n\t...line,\n});\n\nexport const createWord = (word: Partial<LyricWord>): LyricWord => ({\n\tstartTime: 0,\n\tendTime: 0,\n\tword: \"\",\n\t...word,\n});\n\nexport const parseTime = (time: string): number =>\n\tMath.round(\n\t\ttime\n\t\t\t.split(\":\")\n\t\t\t.map(Number)\n\t\t\t.reverse()\n\t\t\t.reduce((acc, cur, idx) => acc + cur * 60 ** idx, 0) * 1000,\n\t);\n\nexport const formatTime = (ms: number): string => {\n\tconst min = Math.floor(ms / 60000)\n\t\t.toString()\n\t\t.padStart(2, \"0\");\n\tconst sec = Math.floor((ms % 60000) / 1000)\n\t\t.toString()\n\t\t.padStart(2, \"0\");\n\tconst msPart = Math.round(ms % 1000)\n\t\t.toString()\n\t\t.padStart(3, \"0\");\n\treturn `${min}:${sec}.${msPart}`;\n};\n\nexport const normalizeTimestamp = (ms: number): number => {\n\tif (!Number.isFinite(ms) || ms < 0) return 0;\n\treturn ms;\n};\n\nexport const normalizeDuration = (duration: number): number => {\n\tif (!Number.isFinite(duration) || duration < 0) return 0;\n\treturn duration;\n};\n\nexport const MAX_LRC_TIMESTAMP = 60_039_999; // 999:99.999\n\nexport const clampTimestamp = (\n\tms: number,\n\tmax: number = MAX_LRC_TIMESTAMP,\n): number => Math.min(max, normalizeTimestamp(ms));\n\n/**\n * Returns consecutive pairs from the given iterable.\n *\n * Example: `0, 1, 2, 3` -> `[0, 1], [1, 2], [2, 3]`\n */\nexport function* pairwise<T>(\n\titerable: Iterable<T>,\n): Generator<[T, T], void, unknown> {\n\tlet prev: T | undefined;\n\tlet hasPrev = false;\n\tfor (const curr of iterable) {\n\t\tif (hasPrev) yield [prev as T, curr];\n\t\tprev = curr;\n\t\thasPrev = true;\n\t}\n}\n","/**\n * @fileoverview ASS 字幕格式导出。\n * 注意导出会损失 10ms 以内精度(按厘秒四舍五入)。\n *\n * 格式示例:\n * Dialogue: 0,0:00:12.34, 0:00:15.67, Default, v1,0,0,0,,{\\k20}Hello{\\k15} world\n * Dialogue: 0,0:00:12.34, 0:00:15.67, Default, v1-trans,0,0,0,,你好 世界\n * Dialogue: 0,0:00:12.34, 0:00:15.67, Default, v1-roman,0,0,0,,ni hao shi jie\n */\nimport type { LyricLine } from \"../types\";\nimport { normalizeTimestamp } from \"../utils\";\n\nfunction writeASSTimestamp(ms: number): string {\n\tconst normalized = normalizeTimestamp(ms);\n\tconst milli = Math.round(normalized) % 1000;\n\tconst secTotal = Math.floor(Math.round(normalized) / 1000);\n\tconst sec = secTotal % 60;\n\tconst minTotal = Math.floor(secTotal / 60);\n\tconst hour = Math.floor(minTotal / 60);\n\treturn `${hour}:${String(minTotal % 60).padStart(2, \"0\")}:${String(sec).padStart(2, \"0\")}.${String(Math.floor(milli / 10)).padStart(2, \"0\")}`;\n}\n\nfunction getSpeakerName(line: LyricLine): string {\n\tlet name = line.isDuet ? \"v2\" : \"v1\";\n\tif (line.isBG) name += \"-bg\";\n\treturn name;\n}\n\nfunction writeLyricDialogue(\n\tresult: string[],\n\tstartTime: number,\n\tendTime: number,\n\tname: string,\n\ttext: string,\n) {\n\tresult.push(\n\t\t`Dialogue: 0,${writeASSTimestamp(startTime)}, ${writeASSTimestamp(endTime)}, Default, ${name},0,0,0,,${text}`,\n\t);\n}\n\n/**\n * 将歌词数组转换为 ASS 字幕格式字符串\n * @param lines 歌词数组\n * @returns ASS 字幕格式字符串\n */\nexport function stringifyAss(lines: LyricLine[]): string {\n\tconst result: string[] = [\n\t\t\"[Script Info]\",\n\t\t\"[Events]\",\n\t\t\"Formats: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\",\n\t];\n\n\tfor (const line of lines) {\n\t\tconst timedWords = line.words\n\t\t\t.map((w) => ({\n\t\t\t\t...w,\n\t\t\t\tstartTime: normalizeTimestamp(w.startTime),\n\t\t\t\tendTime: normalizeTimestamp(w.endTime),\n\t\t\t}))\n\t\t\t.filter((w) => w.endTime > w.startTime);\n\t\tconst startTime = Math.min(...timedWords.map((w) => w.startTime));\n\t\tconst endTime = Math.max(...timedWords.map((w) => w.endTime));\n\t\tif (!Number.isFinite(startTime) || !Number.isFinite(endTime)) continue;\n\n\t\tlet lyricText = \"\";\n\t\tlet previousWordEndTime = startTime;\n\t\tfor (const word of line.words) {\n\t\t\tconst wordStart = normalizeTimestamp(word.startTime);\n\t\t\tconst wordEnd = normalizeTimestamp(word.endTime);\n\t\t\tif (wordStart >= wordEnd) {\n\t\t\t\tlyricText += word.word;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (wordStart > previousWordEndTime) {\n\t\t\t\tconst gapDurationCS = Math.floor(\n\t\t\t\t\t(wordStart - previousWordEndTime + 5) / 10,\n\t\t\t\t);\n\t\t\t\tif (gapDurationCS > 0) lyricText += `{\\\\k${gapDurationCS}}`;\n\t\t\t}\n\n\t\t\tconst wordDurationCS = Math.floor((wordEnd - wordStart + 5) / 10);\n\t\t\tif (wordDurationCS > 0) lyricText += `{\\\\k${wordDurationCS}}`;\n\t\t\tlyricText += word.word;\n\t\t\tpreviousWordEndTime = wordEnd;\n\t\t}\n\n\t\tconst speaker = getSpeakerName(line);\n\t\twriteLyricDialogue(result, startTime, endTime, speaker, lyricText);\n\t\tif (line.translatedLyric)\n\t\t\twriteLyricDialogue(\n\t\t\t\tresult,\n\t\t\t\tstartTime,\n\t\t\t\tendTime,\n\t\t\t\t`${speaker}-trans`,\n\t\t\t\tline.translatedLyric,\n\t\t\t);\n\t\tif (line.romanLyric)\n\t\t\twriteLyricDialogue(\n\t\t\t\tresult,\n\t\t\t\tstartTime,\n\t\t\t\tendTime,\n\t\t\t\t`${speaker}-roman`,\n\t\t\t\tline.romanLyric,\n\t\t\t);\n\t}\n\n\treturn `${result.join(\"\\n\")}\\n`;\n}\n","/**\n * @internal\n * @module constants\n * @description\n * 包含了所有 `custom_des` 模块所需的常量数据。\n */\n\n// 解密使用的3个8字节的DES密钥\nexport const KEY_1: Uint8Array = new TextEncoder().encode(\"!@#)(*$%\");\nexport const KEY_2: Uint8Array = new TextEncoder().encode(\"123ZXC!@\");\nexport const KEY_3: Uint8Array = new TextEncoder().encode(\"!@#)(NHL\");\n\n// --- QQ 音乐使用的非标准 S 盒定义 ---\n\nconst SBOX1: number[] = [\n\t14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 0, 15, 7, 4, 14, 2, 13,\n\t1, 10, 6, 12, 11, 9, 5, 3, 8, 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10,\n\t5, 0, 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,\n];\nconst SBOX2: number[] = [\n\t15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 3, 13, 4, 7, 15, 2, 8,\n\t15, 12, 0, 1, 10, 6, 9, 11, 5, 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3,\n\t2, 15, 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,\n];\nconst SBOX3: number[] = [\n\t10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 13, 7, 0, 9, 3, 4, 6,\n\t10, 2, 8, 5, 14, 12, 11, 15, 1, 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10,\n\t14, 7, 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,\n];\nconst SBOX4: number[] = [\n\t7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 13, 8, 11, 5, 6, 15, 0,\n\t3, 4, 7, 2, 12, 1, 10, 14, 9, 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2,\n\t8, 4, 3, 15, 0, 6, 10, 10, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,\n];\nconst SBOX5: number[] = [\n\t2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 14, 11, 2, 12, 4, 7, 13,\n\t1, 5, 0, 15, 10, 3, 9, 8, 6, 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0,\n\t14, 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,\n];\nconst SBOX6: number[] = [\n\t12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 10, 15, 4, 2, 7, 12, 9,\n\t5, 6, 1, 13, 14, 0, 11, 3, 8, 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13,\n\t11, 6, 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,\n];\nconst SBOX7: number[] = [\n\t4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 13, 0, 11, 7, 4, 9, 1,\n\t10, 14, 3, 5, 12, 2, 15, 8, 6, 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5,\n\t9, 2, 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,\n];\nconst SBOX8: number[] = [\n\t13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 1, 15, 13, 8, 10, 3, 7,\n\t4, 12, 5, 6, 11, 0, 14, 9, 2, 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3,\n\t5, 8, 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11,\n];\n\nexport const S_BOXES: number[][] = [\n\tSBOX1,\n\tSBOX2,\n\tSBOX3,\n\tSBOX4,\n\tSBOX5,\n\tSBOX6,\n\tSBOX7,\n\tSBOX8,\n];\n\n// QQ 音乐使用的标准 P 盒置换规则\nexport const P_BOX: number[] = [\n\t16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32,\n\t27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25,\n];\n\n/// QQ 音乐使用的标准扩展置换表。\nexport const E_BOX_TABLE: number[] = [\n\t32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16,\n\t17, 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29,\n\t28, 29, 30, 31, 32, 1,\n];\n\n// 每轮循环左移的位数表\nexport const KEY_RND_SHIFT: number[] = [\n\t1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1,\n];\n\n// 置换选择1 (PC-1) - C部分\nexport const KEY_PERM_C: number[] = [\n\t56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34,\n\t26, 18, 10, 2, 59, 51, 43, 35,\n];\n\n// 置换选择1 (PC-1) - D部分\nexport const KEY_PERM_D: number[] = [\n\t62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36,\n\t28, 20, 12, 4, 27, 19, 11, 3,\n];\n\n// 置换选择2 (PC-2)\nexport const KEY_COMPRESSION: number[] = [\n\t13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26,\n\t19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33,\n\t52, 45, 41, 49, 35, 28, 31,\n];\n","/**\n * @internal\n * @module custom_des\n * @description\n * 本模块包含了为解密 QRC 歌词而移植的、非标准的类 DES 算法的底层实现。\n *\n * <h2>\n * <strong>警告:该 DES 实现并非标准实现!</strong>\n * </h2>\n *\n * 它是结构类似DES的、但完全私有的分组密码算法。\n * 本实现仅用于 QRC 歌词解密,不应用于实际安全目的。\n */\n\nimport {\n\tE_BOX_TABLE,\n\tKEY_COMPRESSION,\n\tKEY_PERM_C,\n\tKEY_PERM_D,\n\tKEY_RND_SHIFT,\n\tP_BOX,\n\tS_BOXES,\n} from \"./constants\";\n\nexport enum Mode {\n\tEncrypt,\n\tDecrypt,\n}\n\nexport type KeySchedule = Int32Array;\n\n/**\n * 从8字节密钥中根据置换表提取位,生成一个 BigInt。\n *\n * 这个函数对应原始C代码中的天书BITNUM宏,模拟 QQ 音乐特有的非标准的字节序处理方式。\n * 其将 8 字节密钥视为两个独立的、小端序的32位整数拼接而成。\n *\n * 例如,要读取第0位(MSB),它实际访问的是 `key[3]` 的最高位。\n * 要读取第31位,它访问的是 `key[0]` 的最低位。\n *\n * @param key 8字节的密钥 Uint8Array\n * @param table 0-based 的位索引置换表\n */\nfunction permuteFromKeyBytes(key: Uint8Array, table: number[]): bigint {\n\tlet output = 0n;\n\tlet currentBitMask = 1n << BigInt(table.length - 1);\n\n\tfor (let i = 0; i < table.length; i++) {\n\t\tconst pos = table[i];\n\n\t\tconst wordIndex = pos >> 5;\n\t\tconst bitInWord = pos & 31;\n\t\tconst byteInWord = bitInWord >> 3;\n\t\tconst bitInByte = bitInWord & 7;\n\t\tconst byteIndex = wordIndex * 4 + 3 - byteInWord;\n\n\t\tconst bit = (key[byteIndex] >> (7 - bitInByte)) & 1;\n\n\t\tif (bit) {\n\t\t\toutput |= currentBitMask;\n\t\t}\n\t\tcurrentBitMask >>= 1n;\n\t}\n\treturn output;\n}\n\n/**\n * 对一个存储在 BigInt 中的28位密钥部分进行循环左移。\n * @param value 包含28位数据的高位的 BigInt\n * @param amount 左移的位数\n */\nfunction rotateLeft28Bit(value: bigint, amount: number): bigint {\n\tconst BITS_28_MASK = 0xfffffff0n;\n\tconst val = value & BITS_28_MASK;\n\tconst shifted = (val << BigInt(amount)) | (val >> BigInt(28 - amount));\n\treturn shifted & BITS_28_MASK;\n}\n\n/**\n * DES 密钥调度算法。\n * 从一个64位的主密钥(实际使用56位,每字节的最低位是奇偶校验位,被忽略)\n * 生成16个48位的轮密钥。\n *\n * @param key 8字节的DES密钥\n * @param mode 加密或解密模式\n */\nexport function keySchedule(key: Uint8Array, mode: Mode): KeySchedule {\n\t// 预先分配连续的内存空间\n\tconst schedule = new Int32Array(32);\n\n\t// 应用 PC-1\n\tconst c0 = permuteFromKeyBytes(key, KEY_PERM_C);\n\tconst d0 = permuteFromKeyBytes(key, KEY_PERM_D);\n\n\t// 将28位的结果左移4位,以匹配 `rotateLeft28Bit` 对高位对齐的期望。\n\tlet c = c0 << 4n;\n\tlet d = d0 << 4n;\n\n\tfor (let i = 0; i < 16; i++) {\n\t\tconst shift = KEY_RND_SHIFT[i];\n\t\tc = rotateLeft28Bit(c, shift);\n\t\td = rotateLeft28Bit(d, shift);\n\n\t\tconst toGen = mode === Mode.Decrypt ? 15 - i : i;\n\n\t\tlet subkey48bit = 0n;\n\t\t// 应用 PC-2\n\t\tfor (let k = 0; k < KEY_COMPRESSION.length; k++) {\n\t\t\tconst pos = KEY_COMPRESSION[k];\n\n\t\t\tconst bitBigInt =\n\t\t\t\tpos < 28\n\t\t\t\t\t? (c >> BigInt(31 - pos)) & 1n\n\t\t\t\t\t: (d >> BigInt(31 - (pos - 27))) & 1n; // QQ 音乐特有的怪癖,该算法的规则就是pos - 27\n\n\t\t\tif (bitBigInt === 1n) {\n\t\t\t\tsubkey48bit |= 1n << BigInt(47 - k);\n\t\t\t}\n\t\t}\n\n\t\t// 提取高 24 位 (由第 5, 4, 3 字节组成)\n\t\tconst b5 = Number((subkey48bit >> 40n) & 0xffn);\n\t\tconst b4 = Number((subkey48bit >> 32n) & 0xffn);\n\t\tconst b3 = Number((subkey48bit >> 24n) & 0xffn);\n\t\tconst high24 = (b5 << 16) | (b4 << 8) | b3;\n\n\t\t// 提取低 24 位 (由第 2, 1, 0 字节组成)\n\t\tconst b2 = Number((subkey48bit >> 16n) & 0xffn);\n\t\tconst b1 = Number((subkey48bit >> 8n) & 0xffn);\n\t\tconst b0 = Number(subkey48bit & 0xffn);\n\t\tconst low24 = (b2 << 16) | (b1 << 8) | b0;\n\n\t\t// 存储到一维数组中\n\t\tschedule[toGen * 2] = high24;\n\t\tschedule[toGen * 2 + 1] = low24;\n\t}\n\n\treturn schedule;\n}\n\n// 初始置换规则。\nconst IP_RULE: number[] = [\n\t34, 42, 50, 58, 2, 10, 18, 26, 36, 44, 52, 60, 4, 12, 20, 28, 38, 46, 54, 62,\n\t6, 14, 22, 30, 40, 48, 56, 64, 8, 16, 24, 32, 33, 41, 49, 57, 1, 9, 17, 25,\n\t35, 43, 51, 59, 3, 11, 19, 27, 37, 45, 53, 61, 5, 13, 21, 29, 39, 47, 55, 63,\n\t7, 15, 23, 31,\n];\n\n// 逆初始置换规则。\nconst INV_IP_RULE: number[] = [\n\t37, 5, 45, 13, 53, 21, 61, 29, 38, 6, 46, 14, 54, 22, 62, 30, 39, 7, 47, 15,\n\t55, 23, 63, 31, 40, 8, 48, 16, 56, 24, 64, 32, 33, 1, 41, 9, 49, 17, 57, 25,\n\t34, 2, 42, 10, 50, 18, 58, 26, 35, 3, 43, 11, 51, 19, 59, 27, 36, 4, 44, 12,\n\t52, 20, 60, 28,\n];\n\nconst IP_LEFT_TABLE = new Int32Array(2048);\nconst IP_RIGHT_TABLE = new Int32Array(2048);\nconst INV_IP_LEFT_TABLE = new Int32Array(2048);\nconst INV_IP_RIGHT_TABLE = new Int32Array(2048);\n\nfunction generatePermutationTables(): void {\n\tconst applyPermutation = (input: bigint, rule: number[]): bigint => {\n\t\tlet output = 0n;\n\t\tfor (let i = 0; i < 64; i++) {\n\t\t\tconst srcBit1Based = rule[i];\n\t\t\tif ((input >> BigInt(64 - srcBit1Based)) & 1n) {\n\t\t\t\toutput |= 1n << BigInt(63 - i);\n\t\t\t}\n\t\t}\n\t\treturn output;\n\t};\n\n\t// 生成 IP 结果查找表\n\tfor (let bytePos = 0; bytePos < 8; bytePos++) {\n\t\tfor (let byteVal = 0; byteVal < 256; byteVal++) {\n\t\t\tconst input = BigInt(byteVal) << BigInt(56 - bytePos * 8);\n\t\t\tconst permuted = applyPermutation(input, IP_RULE);\n\t\t\tconst idx = (bytePos << 8) | byteVal;\n\t\t\tIP_LEFT_TABLE[idx] = Number((permuted >> 32n) & 0xffffffffn);\n\t\t\tIP_RIGHT_TABLE[idx] = Number(permuted & 0xffffffffn);\n\t\t}\n\t}\n\n\t// 生成 InvIP 结果查找表 (一维 TypedArray,分为左右 32 位以避免 BigInt)\n\tfor (let blockPos = 0; blockPos < 8; blockPos++) {\n\t\tfor (let blockVal = 0; blockVal < 256; blockVal++) {\n\t\t\tconst input = BigInt(blockVal) << BigInt(56 - blockPos * 8);\n\t\t\tconst permuted = applyPermutation(input, INV_IP_RULE);\n\t\t\tconst idx = (blockPos << 8) | blockVal;\n\t\t\tINV_IP_LEFT_TABLE[idx] = Number((permuted >> 32n) & 0xffffffffn);\n\t\t\tINV_IP_RIGHT_TABLE[idx] = Number(permuted & 0xffffffffn);\n\t\t}\n\t}\n}\ngeneratePermutationTables();\n\n/**\n * 计算 DES S-盒的查找索引。\n * @param a 一个包含6位数据的 u8\n */\nfunction calculateSboxIndex(a: number): number {\n\treturn (a & 0x20) | ((a & 0x1f) >> 1) | ((a & 0x01) << 4);\n}\n\n/**\n * 对一个 32 位整数应用非标准的 P 盒置换规则。\n * @param input S-盒代换后的 32 位中间结果\n */\nfunction applyQqPboxPermutation(input: number): number {\n\tlet output = 0;\n\tfor (let i = 0; i < 32; i++) {\n\t\tconst sourceBit1Based = P_BOX[i];\n\t\tconst destBitMask = 1 << (31 - i);\n\t\tconst sourceBitMask = 1 << (32 - sourceBit1Based);\n\t\tif ((input & sourceBitMask) !== 0) {\n\t\t\toutput |= destBitMask;\n\t\t}\n\t}\n\treturn output;\n}\n\nconst SP_TABLE = new Int32Array(512);\n\n/**\n * 生成 S-P 盒合并查找表以提高性能。\n */\nfunction generateSpTables(): void {\n\tfor (let sBoxIdx = 0; sBoxIdx < 8; sBoxIdx++) {\n\t\tfor (let sBoxInput = 0; sBoxInput < 64; sBoxInput++) {\n\t\t\tconst sBoxIndex = calculateSboxIndex(sBoxInput);\n\t\t\tconst fourBitOutput = S_BOXES[sBoxIdx][sBoxIndex];\n\t\t\tconst prePBoxVal = fourBitOutput << (28 - sBoxIdx * 4);\n\t\t\tSP_TABLE[(sBoxIdx << 6) | sBoxInput] = applyQqPboxPermutation(prePBoxVal);\n\t\t}\n\t}\n}\ngenerateSpTables();\n\nconst EBOX_HIGH_TABLE = new Int32Array(1024);\nconst EBOX_LOW_TABLE = new Int32Array(1024);\n\nfunction generateEBoxTables(): void {\n\tfor (let chunkIdx = 0; chunkIdx < 4; chunkIdx++) {\n\t\tconst shiftIn32 = (3 - chunkIdx) * 8;\n\n\t\tfor (let byteVal = 0; byteVal < 256; byteVal++) {\n\t\t\tlet high24 = 0;\n\t\t\tlet low24 = 0;\n\t\t\tconst input = byteVal << shiftIn32;\n\n\t\t\tfor (let i = 0; i < 24; i++) {\n\t\t\t\tconst sourceBitPos = E_BOX_TABLE[i];\n\t\t\t\tconst bit = (input >>> (32 - sourceBitPos)) & 1;\n\t\t\t\tif (bit) {\n\t\t\t\t\thigh24 |= 1 << (23 - i);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (let i = 24; i < 48; i++) {\n\t\t\t\tconst sourceBitPos = E_BOX_TABLE[i];\n\t\t\t\tconst bit = (input >>> (32 - sourceBitPos)) & 1;\n\t\t\t\tif (bit) {\n\t\t\t\t\tlow24 |= 1 << (47 - i);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst tableIdx = (chunkIdx << 8) | byteVal;\n\t\t\tEBOX_HIGH_TABLE[tableIdx] = high24;\n\t\t\tEBOX_LOW_TABLE[tableIdx] = low24;\n\t\t}\n\t}\n}\ngenerateEBoxTables();\n\n/**\n * DES 的 F 函数。\n */\nfunction fFunction(state: number, keyHigh24: number, keyLow24: number): number {\n\t// 将 32 位状态拆分为 4 个字节,直接查表并进行按位或拼接\n\tconst b0 = (state >>> 24) & 0xff;\n\tconst b1 = (state >>> 16) & 0xff;\n\tconst b2 = (state >>> 8) & 0xff;\n\tconst b3 = state & 0xff;\n\n\tconst eboxHigh24 =\n\t\tEBOX_HIGH_TABLE[b0] |\n\t\tEBOX_HIGH_TABLE[256 | b1] |\n\t\tEBOX_HIGH_TABLE[512 | b2] |\n\t\tEBOX_HIGH_TABLE[768 | b3];\n\tconst eboxLow24 =\n\t\tEBOX_LOW_TABLE[b0] |\n\t\tEBOX_LOW_TABLE[256 | b1] |\n\t\tEBOX_LOW_TABLE[512 | b2] |\n\t\tEBOX_LOW_TABLE[768 | b3];\n\n\tconst xorHigh24 = eboxHigh24 ^ keyHigh24;\n\tconst xorLow24 = eboxLow24 ^ keyLow24;\n\n\treturn (\n\t\tSP_TABLE[(xorHigh24 >>> 18) & 0x3f] |\n\t\tSP_TABLE[64 | ((xorHigh24 >>> 12) & 0x3f)] |\n\t\tSP_TABLE[128 | ((xorHigh24 >>> 6) & 0x3f)] |\n\t\tSP_TABLE[192 | (xorHigh24 & 0x3f)] |\n\t\tSP_TABLE[256 | ((xorLow24 >>> 18) & 0x3f)] |\n\t\tSP_TABLE[320 | ((xorLow24 >>> 12) & 0x3f)] |\n\t\tSP_TABLE[384 | ((xorLow24 >>> 6) & 0x3f)] |\n\t\tSP_TABLE[448 | (xorLow24 & 0x3f)]\n\t);\n}\n\n/**\n * DES 加密/解密单个64位数据块。\n *\n * @param input 8字节的输入数据块 (明文或密文)。\n * @param output 8字节的可变切片,用于存储输出数据块 (密文或明文)。\n * @param keySchedule 一个包含16个轮密钥的向量的引用,每个轮密钥是6字节。\n */\nexport function desCrypt(\n\tinput: Uint8Array,\n\toutput: Uint8Array,\n\tkeySchedule: KeySchedule,\n): void {\n\tlet left = 0;\n\tlet right = 0;\n\tfor (let i = 0; i < 8; i++) {\n\t\tconst idx = (i << 8) | input[i];\n\t\tleft |= IP_LEFT_TABLE[idx];\n\t\tright |= IP_RIGHT_TABLE[idx];\n\t}\n\n\tfor (let i = 0; i < 15; i++) {\n\t\tconst temp = right;\n\t\tright =\n\t\t\t(left ^ fFunction(right, keySchedule[i * 2], keySchedule[i * 2 + 1])) >>>\n\t\t\t0;\n\t\tleft = temp;\n\t}\n\tleft = (left ^ fFunction(right, keySchedule[30], keySchedule[31])) >>> 0;\n\n\tlet outLeft = 0;\n\tlet outRight = 0;\n\tfor (let i = 0; i < 4; i++) {\n\t\t// 分别计算左侧 32 位和右侧 32 位在 INV_IP 阶段的表现\n\t\tconst idxL = (i << 8) | ((left >>> (24 - i * 8)) & 0xff);\n\t\toutLeft |= INV_IP_LEFT_TABLE[idxL];\n\t\toutRight |= INV_IP_RIGHT_TABLE[idxL];\n\n\t\tconst idxR = ((i + 4) << 8) | ((right >>> (24 - i * 8)) & 0xff);\n\t\toutLeft |= INV_IP_LEFT_TABLE[idxR];\n\t\toutRight |= INV_IP_RIGHT_TABLE[idxR];\n\t}\n\n\t// 使用按位移位进行输出数组写入\n\toutput[0] = (outLeft >>> 24) & 0xff;\n\toutput[1] = (outLeft >>> 16) & 0xff;\n\toutput[2] = (outLeft >>> 8) & 0xff;\n\toutput[3] = outLeft & 0xff;\n\toutput[4] = (outRight >>> 24) & 0xff;\n\toutput[5] = (outRight >>> 16) & 0xff;\n\toutput[6] = (outRight >>> 8) & 0xff;\n\toutput[7] = outRight & 0xff;\n}\n","/// <reference types=\"node\" />\n/**\n * @module utils\n * @description\n *\n * 包含一些工具函数。\n */\n\n/**\n * 将十六进制字符串转换为 Uint8Array。\n */\nexport function hexToUint8Array(hex: string): Uint8Array {\n\tif (typeof Buffer !== \"undefined\") {\n\t\treturn Buffer.from(hex, \"hex\");\n\t}\n\n\tif (hex.length % 2 !== 0) {\n\t\tthrow new Error(\"无效的十六进制字符串: 长度必须是偶数\");\n\t}\n\n\tconst bytes = new Uint8Array(hex.length / 2);\n\tfor (let i = 0; i < hex.length; i += 2) {\n\t\tbytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);\n\t}\n\treturn bytes;\n}\n\n/**\n * 将 Uint8Array 转换为十六进制字符串。\n */\nexport function uint8ArrayToHex(bytes: Uint8Array): string {\n\tif (typeof Buffer !== \"undefined\") {\n\t\treturn Buffer.from(bytes).toString(\"hex\");\n\t}\n\n\treturn Array.from(bytes)\n\t\t.map((b) => b.toString(16).padStart(2, \"0\"))\n\t\t.join(\"\");\n}\n","/**\n * @module qrc-codec\n * @description\n * 此模块是加密与解密 QRC 歌词的核心。\n * 提供了两个主要的公共函数:`decryptQrc` 和 `encryptQrc`。\n *\n * 非标准 3DES 算法实现由 `custom_des` 模块提供。\n *\n * 迁移自 https://github.com/apoint123/qrc-decoder\n */\n\nimport { deflate, inflate } from \"pako\";\nimport { KEY_1, KEY_2, KEY_3 } from \"./constants\";\nimport { desCrypt, type KeySchedule, keySchedule, Mode } from \"./custom-des\";\nimport { hexToUint8Array, uint8ArrayToHex } from \"./utils\";\n\nconst DES_BLOCK_SIZE = 8;\n\n/**\n * 非标准 3DES 编解码器\n */\nclass QqMusicCodec {\n\tprivate readonly encryptSchedule: KeySchedule[];\n\tprivate readonly decryptSchedule: KeySchedule[];\n\n\tconstructor() {\n\t\t// 解密流程 D(K3) -> E(K2) -> D(K1)\n\t\tthis.decryptSchedule = [\n\t\t\tkeySchedule(KEY_3, Mode.Decrypt),\n\t\t\tkeySchedule(KEY_2, Mode.Encrypt),\n\t\t\tkeySchedule(KEY_1, Mode.Decrypt),\n\t\t];\n\n\t\t// 加密流程 E(K1) -> D(K2) -> E(K3)\n\t\tthis.encryptSchedule = [\n\t\t\tkeySchedule(KEY_1, Mode.Encrypt),\n\t\t\tkeySchedule(KEY_2, Mode.Decrypt),\n\t\t\tkeySchedule(KEY_3, Mode.Encrypt),\n\t\t];\n\t}\n\n\t/**\n\t * 解密一个8字节的数据块。\n\t */\n\tpublic decryptBlock(input: Uint8Array, output: Uint8Array): void {\n\t\tconst temp1 = new Uint8Array(8);\n\t\tconst temp2 = new Uint8Array(8);\n\t\tdesCrypt(input, temp1, this.decryptSchedule[0]);\n\t\tdesCrypt(temp1, temp2, this.decryptSchedule[1]);\n\t\tdesCrypt(temp2, output, this.decryptSchedule[2]);\n\t}\n\n\t/**\n\t * 加密一个8字节的数据块。\n\t */\n\tpublic encryptBlock(input: Uint8Array, output: Uint8Array): void {\n\t\tconst temp1 = new Uint8Array(8);\n\t\tconst temp2 = new Uint8Array(8);\n\t\tdesCrypt(input, temp1, this.encryptSchedule[0]);\n\t\tdesCrypt(temp1, temp2, this.encryptSchedule[1]);\n\t\tdesCrypt(temp2, output, this.encryptSchedule[2]);\n\t}\n}\n\nconst CODEC = new QqMusicCodec();\n\n/**\n * 使用零字节对数据进行填充。\n *\n * QQ音乐使用的填充方案是零填充。\n * @param data 需要填充的字节数据\n * @param blockSize 块大小,对于DES来说是8\n */\nfunction zeroPad(data: Uint8Array, blockSize: number): Uint8Array {\n\tconst paddingLen = (blockSize - (data.length % blockSize)) % blockSize;\n\tif (paddingLen === 0) {\n\t\treturn data;\n\t}\n\n\tconst paddedData = new Uint8Array(data.length + paddingLen);\n\tpaddedData.set(data, 0);\n\treturn paddedData;\n}\n\n/**\n * 使用 Zlib 解压缩字节数据。\n * 同时会尝试移除头部的 UTF-8 BOM (0xEF 0xBB 0xBF)。\n */\nfunction decompress(data: Uint8Array): Uint8Array {\n\tconst decompressed = inflate(data);\n\tif (\n\t\tdecompressed.length >= 3 &&\n\t\tdecompressed[0] === 0xef &&\n\t\tdecompressed[1] === 0xbb &&\n\t\tdecompressed[2] === 0xbf\n\t) {\n\t\treturn decompressed.slice(3);\n\t}\n\treturn decompressed;\n}\n\n/**\n * 解密十六进制字符串格式的 Qrc 歌词数据\n * 解密后可去头尾 XML 数据后通过调用 `parseQrc` 解析歌词行\n * @param encryptedHexString 十六进制格式的字符串,代表被加密的歌词数据\n * @returns 被解密出来的歌词字符串,是前后有 XML 混合的 QRC 歌词\n */\nexport function decryptQrcHex(encryptedHexString: string): string {\n\tconst encryptedBytes = hexToUint8Array(encryptedHexString);\n\n\tif (encryptedBytes.length % DES_BLOCK_SIZE !== 0) {\n\t\tthrow new Error(`加密数据长度不是${DES_BLOCK_SIZE}的倍数`);\n\t}\n\n\tconst decryptedData = new Uint8Array(encryptedBytes.length);\n\n\tfor (let i = 0; i < encryptedBytes.length; i += DES_BLOCK_SIZE) {\n\t\tconst chunk = encryptedBytes.subarray(i, i + DES_BLOCK_SIZE);\n\t\tconst outChunk = decryptedData.subarray(i, i + DES_BLOCK_SIZE);\n\t\tCODEC.decryptBlock(chunk, outChunk);\n\t}\n\n\tconst decompressedBytes = decompress(decryptedData);\n\n\treturn new TextDecoder(\"utf-8\").decode(decompressedBytes);\n}\n\n/**\n * 对明文执行加密操作。\n * @param plaintext 明文字符串\n * @returns 十六进制格式的字符串,代表被加密的歌词数据\n */\nexport function encryptQrcHex(plaintext: string): string {\n\tconst textBytes = new TextEncoder().encode(plaintext);\n\n\tconst compressedData = deflate(textBytes);\n\n\tconst paddedData = zeroPad(compressedData, DES_BLOCK_SIZE);\n\n\tconst encryptedData = new Uint8Array(paddedData.length);\n\n\tfor (let i = 0; i < paddedData.length; i += DES_BLOCK_SIZE) {\n\t\tconst chunk = paddedData.subarray(i, i + DES_BLOCK_SIZE);\n\t\tconst outChunk = encryptedData.subarray(i, i + DES_BLOCK_SIZE);\n\t\tCODEC.encryptBlock(chunk, outChunk);\n\t}\n\n\treturn uint8ArrayToHex(encryptedData);\n}\n","/**\n * @fileoverview ESLyric 逐词歌词格式解析与生成。\n * 每行以行首时间戳开头,后续每个单词后都跟一个结束时间戳。\n *\n * 格式示例:\n * [00:10.82]Test[00:10.97] Word[00:12.62]\n * [00:12.62]Next[00:13.20] line[00:14.10]\n */\nimport type { LyricLine, LyricWord } from \"../types\";\nimport {\n\tclampTimestamp,\n\tcreateLine,\n\tcreateWord,\n\tformatTime,\n\tparseTime,\n} from \"../utils\";\n\nconst TIME_REGEX = /^\\[((?:\\d+:)*\\d+(?:\\.\\d+)?)\\]/;\n\nfunction parseTimestampPrefix(\n\tsrc: string,\n): { time: number; length: number } | null {\n\tconst match = src.match(TIME_REGEX);\n\tif (!match) return null;\n\tconst [raw, timeStr] = match;\n\treturn { time: parseTime(timeStr), length: raw.length };\n}\n\nfunction parseEslrcLine(rawLine: string): LyricLine | null {\n\tlet src = rawLine.trim();\n\tconst first = parseTimestampPrefix(src);\n\tif (!first) return null;\n\tsrc = src.slice(first.length);\n\tlet startTime = first.time;\n\tif (!src.trim()) return null;\n\n\tconst words: LyricWord[] = [];\n\twhile (src.trim().length > 0) {\n\t\tconst nextTimePos = src.indexOf(\"[\");\n\t\tif (nextTimePos <= 0) return null;\n\n\t\tconst word = src.slice(0, nextTimePos);\n\t\tconst nextTime = parseTimestampPrefix(src.slice(nextTimePos));\n\t\tif (!nextTime) return null;\n\n\t\twords.push(\n\t\t\tcreateWord({\n\t\t\t\tword,\n\t\t\t\tstartTime,\n\t\t\t\tendTime: nextTime.time,\n\t\t\t}),\n\t\t);\n\t\tsrc = src.slice(nextTimePos + nextTime.length);\n\t\tstartTime = nextTime.time;\n\t}\n\n\treturn createLine({ words });\n}\n\n/**\n * 解析 ESLyric 逐词歌词格式字符串\n * @param eslrc 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseEslrc(eslrc: string): LyricLine[] {\n\tconst result: LyricLine[] = [];\n\tfor (const rawLine of eslrc.split(/\\r?\\n/)) {\n\t\tconst line = parseEslrcLine(rawLine);\n\t\tif (line) result.push(line);\n\t}\n\n\tresult.sort(\n\t\t(a, b) =>\n\t\t\t(a.words[0]?.startTime ?? Number.MAX_SAFE_INTEGER) -\n\t\t\t(b.words[0]?.startTime ?? Number.MAX_SAFE_INTEGER),\n\t);\n\n\tfor (const line of result) {\n\t\tfor (const word of line.words) {\n\t\t\tword.startTime = clampTimestamp(word.startTime);\n\t\t\tword.endTime = clampTimestamp(word.endTime);\n\t\t}\n\t\tline.startTime = clampTimestamp(line.words[0]?.startTime ?? 0);\n\t\tline.endTime = clampTimestamp(\n\t\t\tline.words[line.words.length - 1]?.endTime ?? 0,\n\t\t);\n\t}\n\n\treturn result;\n}\n\n/**\n * 将歌词数组转换为 ESLyric 逐词歌词格式字符串\n * @param lines 歌词数组\n * @returns ESLyric 逐词歌词格式字符串\n */\nexport function stringifyEslrc(lines: LyricLine[]): string {\n\treturn lines\n\t\t.map((line) => {\n\t\t\tif (!line.words.length) return \"\";\n\t\t\treturn `[${formatTime(clampTimestamp(line.words[0].startTime))}]${line.words\n\t\t\t\t.map(\n\t\t\t\t\t(word) => `${word.word}[${formatTime(clampTimestamp(word.endTime))}]`,\n\t\t\t\t)\n\t\t\t\t.join(\"\")}`;\n\t\t})\n\t\t.filter(Boolean)\n\t\t.join(\"\\n\");\n}\n","/**\n * @fileoverview Lyricify Syllable(LYS)格式解析与生成。\n * 支持词级时间戳、背景人声与对唱属性。每行以属性位 `[prop]` 开头,后续为 `文本(start,duration)` 序列。\n *\n * 属性位说明:\n * 0: 未设置\n * 1: 左对齐\n * 2: 右对齐(对唱)\n * 3: 非背景,未设置对齐\n * 4: 非背景,左对齐\n * 5: 非背景,右对齐(对唱)\n * 6: 背景,未设置对齐\n * 7: 背景,左对齐\n * 8: 背景,右对齐(对唱)\n *\n * 格式示例:\n * [0]Lately (358,1336)I've (1694,487)been, (2181,673)I've (2854,268)been (3122,280)losing (3402,345)sleep(3747,1186)\n * [0]Dreaming (5245,696)about (5941,471)the (6412,306)things (6718,458)that (7176,292)we (7468,511)could (7979,393)be(8372,737)\n */\nimport type { LyricLine, LyricWord } from \"../types\";\nimport {\n\tcreateLine,\n\tcreateWord,\n\tnormalizeDuration,\n\tnormalizeTimestamp,\n} from \"../utils\";\n\n/**\n * 解析 LYS 格式中的属性值\n * @param prop 属性值\n * @returns 对唱与背景标志位\n */\nfunction parseProp(prop: number): {\n\tisDuet: boolean | undefined;\n\tisBG: boolean | undefined;\n} {\n\tif (prop < 0 || prop > 8) prop = 0;\n\treturn {\n\t\tisDuet: prop % 3 === 0 ? undefined : prop % 3 === 2,\n\t\tisBG: prop <= 2 ? undefined : prop >= 6,\n\t};\n}\n\n/**\n * 解析 LYS 格式的歌词字符串\n * @param lys 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseLys(lys: string): LyricLine[] {\n\tconst lines = lys\n\t\t.split(/\\r?\\n/)\n\t\t.map((l) => l.trim())\n\t\t.filter((l) => l.length > 0);\n\tconst lyricLines: LyricLine[] = [];\n\tconst propRegex = /^\\[(\\d+)\\]/;\n\tconst wordRegex = /(.*?)\\((\\d+),(\\d+)\\)/g;\n\n\tfor (const lineStr of lines) {\n\t\tconst propMatch = lineStr.match(propRegex);\n\t\tif (!propMatch) continue;\n\n\t\tconst [, propStr] = propMatch;\n\t\tconst content = lineStr.slice(propMatch[0].length);\n\t\tconst words: LyricWord[] = [];\n\t\tconst props = parseProp(Number(propStr));\n\n\t\tfor (const match of content.matchAll(wordRegex)) {\n\t\t\tconst [, rawWord, startStr, durStr] = match;\n\t\t\tconst startTime = Number(startStr);\n\t\t\tconst duration = Number(durStr);\n\t\t\tconst endTime = startTime + duration;\n\t\t\tconst wordText = rawWord;\n\t\t\twords.push(createWord({ word: wordText, startTime, endTime }));\n\t\t}\n\n\t\tconst lineStartTime = words[0]?.startTime ?? 0;\n\t\tconst lineEndTime = words[words.length - 1]?.endTime ?? 0;\n\t\tif (!words.length) continue;\n\n\t\tif (props.isBG === undefined)\n\t\t\tprops.isBG =\n\t\t\t\twords.length > 0 &&\n\t\t\t\t/^[((]/.test(words[0].word) &&\n\t\t\t\t/[))]$/.test(words[words.length - 1].word);\n\n\t\tif (props.isBG && words.length) {\n\t\t\twords[0].word = words[0].word.replace(/^[((]/, \"\");\n\t\t\twords[words.length - 1].word = words[words.length - 1].word.replace(\n\t\t\t\t/[))]$/,\n\t\t\t\t\"\",\n\t\t\t);\n\t\t}\n\n\t\tlyricLines.push(\n\t\t\tcreateLine({\n\t\t\t\tstartTime: lineStartTime,\n\t\t\t\tendTime: lineEndTime,\n\t\t\t\tisDuet: !!props.isDuet,\n\t\t\t\tisBG: props.isBG,\n\t\t\t\twords,\n\t\t\t}),\n\t\t);\n\t}\n\treturn lyricLines;\n}\n\nfunction makeProp(line: LyricLine): number {\n\tlet prop = 0;\n\tprop += line.isDuet ? 2 : 1;\n\tprop += line.isBG ? 6 : 3;\n\treturn prop;\n}\n\n/**\n * 将歌词数组转换为 LYS 格式的字符串\n * @param lines 歌词数组\n * @returns LYS 格式的字符串\n */\nexport function stringifyLys(lines: LyricLine[]): string {\n\treturn lines\n\t\t.map((line) => {\n\t\t\tconst prop = makeProp(line);\n\t\t\tconst printWords: {\n\t\t\t\tstartTime: number;\n\t\t\t\tduration: number;\n\t\t\t\tword: string;\n\t\t\t}[] = [];\n\t\t\tline.words.forEach((w) => {\n\t\t\t\tif (w.word.trim() || !printWords.length)\n\t\t\t\t\tprintWords.push({\n\t\t\t\t\t\tword: w.word,\n\t\t\t\t\t\tstartTime: normalizeTimestamp(w.startTime),\n\t\t\t\t\t\tduration: normalizeDuration(\n\t\t\t\t\t\t\tnormalizeTimestamp(w.endTime) - normalizeTimestamp(w.startTime),\n\t\t\t\t\t\t),\n\t\t\t\t\t});\n\t\t\t\telse printWords[printWords.length - 1].word += w.word;\n\t\t\t});\n\t\t\tconst wordsStr = printWords\n\t\t\t\t.map((w) => `${w.word}(${w.startTime},${w.duration})`)\n\t\t\t\t.join(\"\");\n\t\t\treturn `[${prop}]${wordsStr}`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n","/**\n * @fileoverview Lyricify Quick Export(LQE)格式解析与生成。\n * 该格式本质是组合格式:`lyrics` 部分使用 LYS;`translation`/`pronunciation` 部分使用 LRC。\n *\n * 格式示例:\n * [Lyricify Quick Export]\n * [version:1.0]\n *\n * [lyrics: format@Lyricify Syllable]\n * [4]A(365,350)ni(715,307)ro(1022,312)dham (1334,419)a(3203,337)nut(3540,350)pā(3890,306)dam(4196,382)\n *\n * [translation: format@LRC]\n * [00:00.365]不生亦不灭\n *\n * [pronunciation: format@LRC, language@romaji]\n * [00:00.365]阿难罗昙 阿耨钵昙\n */\nimport type { LyricLine } from \"../types\";\nimport { formatTime, parseTime } from \"../utils\";\nimport { parseLys, stringifyLys } from \"./lys\";\n\ntype AttrType = \"translatedLyric\" | \"romanLyric\";\n\ninterface HeaderMatch {\n\tindex: number;\n\ttype: \"lyric\" | \"translation\" | \"romanization\" | \"unknown\";\n}\n\nfunction parseAttr(\n\tattr: AttrType,\n\theaderMatches: HeaderMatch[],\n\trawLines: string[],\n\tlines: LyricLine[],\n): void {\n\tconst headerIndex = headerMatches.findIndex((item) => {\n\t\tif (attr === \"translatedLyric\") return item.type === \"translation\";\n\t\treturn item.type === \"romanization\";\n\t});\n\tif (headerIndex === -1) return;\n\n\tconst timeRegex = /^\\[((?:\\d+:)*\\d+(?:\\.\\d+)?)\\](.*)$/;\n\tconst attrLines = rawLines\n\t\t.slice(\n\t\t\theaderMatches[headerIndex].index + 1,\n\t\t\theaderMatches[headerIndex + 1].index,\n\t\t)\n\t\t.map((line) => line.trim())\n\t\t.filter((line) => line.length > 0)\n\t\t.map((line) => {\n\t\t\tconst match = line.match(timeRegex);\n\t\t\tif (!match) return null;\n\t\t\tconst [, timeStr, text] = match;\n\t\t\tconst time = parseTime(timeStr);\n\t\t\tif (Number.isNaN(time)) return null;\n\t\t\treturn { time, text };\n\t\t})\n\t\t.filter((item): item is { time: number; text: string } => item !== null);\n\n\tlet attrLineIndex = 0;\n\tfor (const line of lines) {\n\t\tif (attrLines[attrLineIndex]?.time !== line.startTime) continue;\n\t\tline[attr] = attrLines[attrLineIndex].text;\n\t\tattrLineIndex++;\n\t}\n}\n\n/**\n * 解析 LQE 格式的歌词字符串\n * @param lqe 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseLqe(lqe: string): LyricLine[] {\n\tconst lines = lqe\n\t\t.split(/\\r?\\n/)\n\t\t.map((line) => line.trim())\n\t\t.filter((line) => line.length > 0);\n\n\tconst headerRegex = /^\\[([a-zA-Z]+):.+\\]$/;\n\tconst headerMatches: HeaderMatch[] = [];\n\tlines.forEach((line, index) => {\n\t\tconst match = line.match(headerRegex);\n\t\tif (!match) return;\n\t\tconst [, type] = match;\n\t\tif (type === \"lyrics\") headerMatches.push({ index, type: \"lyric\" });\n\t\telse if (type === \"translation\")\n\t\t\theaderMatches.push({ index, type: \"translation\" });\n\t\telse if (type === \"pronunciation\")\n\t\t\theaderMatches.push({ index, type: \"romanization\" });\n\t\telse headerMatches.push({ index, type: \"unknown\" });\n\t});\n\theaderMatches.push({ index: lines.length, type: \"unknown\" });\n\n\tconst lyricHeaderIndex = headerMatches.findIndex(\n\t\t(item) => item.type === \"lyric\",\n\t);\n\tif (lyricHeaderIndex === -1) return [];\n\n\tconst lyricLines = lines.slice(\n\t\theaderMatches[lyricHeaderIndex].index + 1,\n\t\theaderMatches[lyricHeaderIndex + 1].index,\n\t);\n\tconst parsedLines = parseLys(lyricLines.join(\"\\n\"));\n\n\tparseAttr(\"translatedLyric\", headerMatches, lines, parsedLines);\n\tparseAttr(\"romanLyric\", headerMatches, lines, parsedLines);\n\n\treturn parsedLines;\n}\n\nfunction stringifyAttr(lines: LyricLine[], attr: AttrType): string | null {\n\tconst header =\n\t\tattr === \"translatedLyric\"\n\t\t\t? \"[translation: format@LRC]\"\n\t\t\t: \"[pronunciation: format@LRC, language@romaji]\";\n\tconst contentLines = lines\n\t\t.map((line) => {\n\t\t\tconst value = line[attr];\n\t\t\tif (!value) return null;\n\t\t\treturn `[${formatTime(line.startTime)}]${value}`;\n\t\t})\n\t\t.filter((line): line is string => line !== null);\n\tif (contentLines.length === 0) return null;\n\treturn [header, ...contentLines].join(\"\\n\");\n}\n\n/**\n * 将歌词数组转换为 LQE 格式的字符串\n * @param lines 歌词数组\n * @returns LQE 格式的字符串\n */\nexport function stringifyLqe(lines: LyricLine[]): string {\n\tconst header = \"[Lyricify Quick Export]\\n[version:1.0]\";\n\tconst lyricSection = `[lyrics: format@Lyricify Syllable]\\n${stringifyLys(lines)}`;\n\tconst translationSection = stringifyAttr(lines, \"translatedLyric\");\n\tconst romanizationSection = stringifyAttr(lines, \"romanLyric\");\n\tconst body = [lyricSection, translationSection, romanizationSection]\n\t\t.filter((section): section is string => section !== null)\n\t\t.join(\"\\n\\n\\n\");\n\treturn [header, body].join(\"\\n\\n\");\n}\n","/**\n * @fileoverview 基础 LRC 格式解析与生成。\n * 该格式只支持行级时间戳,不支持词级/音节级时间戳;若需要词级时间戳请使用 LRC A2 等扩展。\n *\n * 格式示例:\n * [01:56.439]Life goes on, through tides of time\n * [02:01.079]Get in the line, to dream alive\n * [02:06.103][02:08.916][02:11.135]On the journey\n */\nimport type { LyricLine } from \"../types\";\nimport {\n\tcreateLine,\n\tcreateWord,\n\tformatTime,\n\tMAX_LRC_TIMESTAMP,\n\tnormalizeTimestamp,\n\tpairwise,\n\tparseTime,\n} from \"../utils\";\n\n/**\n * 解析 LyRiC 格式的歌词字符串\n * @param lrc 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseLrc(lrc: string): LyricLine[] {\n\tconst tagRegex = /^\\[([a-z]+):([^\\]]+)\\]$/;\n\tconst timeRegex = /^\\[((?:\\d+:)*\\d+(?:\\.\\d+)?)\\](.*)$/;\n\tconst bgRegex = /^[((](.+)[))]$/;\n\tconst lines = lrc\n\t\t.split(/\\r?\\n/)\n\t\t.map((l) => l.trim())\n\t\t.filter((l) => l.length > 0);\n\tconst lyricLines: LyricLine[] = [];\n\tfor (let lineStr of lines) {\n\t\tif (tagRegex.test(lineStr)) continue;\n\t\tconst timeStamps: number[] = [];\n\t\twhile (true) {\n\t\t\tconst match = lineStr.match(timeRegex);\n\t\t\tif (!match) break;\n\t\t\tconst [, timeStr, text] = match;\n\t\t\tconst timeStamp = parseTime(timeStr);\n\t\t\tif (Number.isNaN(timeStamp)) break;\n\t\t\ttimeStamps.push(timeStamp);\n\t\t\tlineStr = text;\n\t\t}\n\t\tif (timeStamps.length === 0) continue;\n\t\tlineStr = lineStr.trim();\n\t\tconst backgroundMatch = lineStr.match(bgRegex);\n\t\tconst isBG = Boolean(backgroundMatch);\n\t\tif (backgroundMatch) lineStr = backgroundMatch[1];\n\t\tfor (const t of timeStamps)\n\t\t\tlyricLines.push(\n\t\t\t\tcreateLine({\n\t\t\t\t\tstartTime: t,\n\t\t\t\t\tendTime: MAX_LRC_TIMESTAMP,\n\t\t\t\t\twords: [createWord({ word: lineStr, startTime: t, endTime: t })],\n\t\t\t\t\tisBG,\n\t\t\t\t}),\n\t\t\t);\n\t}\n\tlyricLines.sort((a, b) => a.startTime - b.startTime);\n\tfor (const [prev, curr] of pairwise(lyricLines))\n\t\tprev.endTime = prev.words[0].endTime = curr.startTime;\n\treturn lyricLines.filter((line) => line.words[0].word);\n}\n\n/**\n * 将歌词数组转换为 LyRiC 格式的字符串\n * @param lines 歌词数组\n * @returns LyRiC 格式的字符串\n */\nexport function stringifyLrc(lines: LyricLine[]): string {\n\treturn lines\n\t\t.map((line) => {\n\t\t\tconst text = line.words.map((w) => w.word).join(\"\");\n\t\t\tconst printText = line.isBG ? `(${text})` : text;\n\t\t\treturn `[${formatTime(normalizeTimestamp(line.startTime))}]${printText}`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n","/**\n * @fileoverview LRC A2(增强 LRC)格式解析与生成。\n * 在普通 LRC 行级时间戳基础上,支持词级/音节级时间戳;同一行内时间需连续,词时间由左右时间戳界定。\n *\n * 格式示例:\n * [02:38.850]<02:38.850>Words <02:39.030>are <02:39.120>made <02:39.360>of <02:39.420>plastic<02:40.080>\n * [02:40.080]<02:40.080>Come <02:40.290>back <02:40.470>like <02:40.680>elastic<02:41.370>\n */\nimport type { LyricLine, LyricWord } from \"../types\";\nimport {\n\tcreateLine,\n\tcreateWord,\n\tformatTime,\n\tnormalizeTimestamp,\n\tparseTime,\n} from \"../utils\";\n\n/**\n * 解析 LRC A2 格式的歌词字符串\n * @param lrc 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseLrcA2(lrc: string): LyricLine[] {\n\tconst lines = lrc\n\t\t.split(/\\r?\\n/)\n\t\t.map((l) => l.trim())\n\t\t.filter((l) => l.length > 0);\n\tconst lyricLines: LyricLine[] = [];\n\tconst lineTimeStampRegex = /^\\[((?:\\d+:)*\\d+(?:\\.\\d+)?)\\]/;\n\tconst wordTimestampRegex = /<((?:\\d+:)*\\d+(?:\\.\\d+)?)>/;\n\tconst wordTimestampPrefixRegex = /^<((?:\\d+:)*\\d+(?:\\.\\d+)?)>/;\n\tfor (let lineStr of lines) {\n\t\tconst tagMatch = lineStr.match(/^\\[([a-z]):(.+)\\]$/i);\n\t\tif (tagMatch) continue;\n\t\tconst lineTimeStampmatch = lineStr.match(lineTimeStampRegex);\n\t\tif (!lineTimeStampmatch) continue;\n\t\tconst [lineTimeStamp, lineTimeStr] = lineTimeStampmatch;\n\t\tconst lineStartTime = parseTime(lineTimeStr);\n\t\tif (Number.isNaN(lineStartTime)) continue;\n\t\tlineStr = lineStr.slice(lineTimeStamp.length).trim();\n\t\tif (!lineStr) continue;\n\n\t\tconst lineItems: (number | string)[] = [];\n\t\twhile (lineStr.length) {\n\t\t\tconst prefixedTimeStampMatch = lineStr.match(wordTimestampPrefixRegex);\n\t\t\tif (prefixedTimeStampMatch) {\n\t\t\t\tconst [wordTimeStamp, wordTimeStr] = prefixedTimeStampMatch;\n\t\t\t\tconst parsedWordTime = parseTime(wordTimeStr);\n\t\t\t\tif (!Number.isNaN(parsedWordTime)) lineItems.push(parsedWordTime);\n\t\t\t\tlineStr = lineStr.slice(wordTimeStamp.length);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst nextWordTimeStampIndex = lineStr.search(wordTimestampRegex);\n\t\t\tconst text =\n\t\t\t\tnextWordTimeStampIndex === -1\n\t\t\t\t\t? lineStr\n\t\t\t\t\t: lineStr.slice(0, nextWordTimeStampIndex);\n\t\t\tlineItems.push(text);\n\t\t\tlineStr = lineStr.slice(text.length);\n\t\t}\n\n\t\tconst words: LyricWord[] = [];\n\t\tlineItems.forEach((item, index) => {\n\t\t\tif (typeof item === \"number\") return;\n\t\t\tconst startTime = lineItems[index - 1] ?? lineStartTime;\n\t\t\tconst endTime = lineItems[index + 1] ?? startTime;\n\t\t\tif (typeof startTime !== \"number\" || typeof endTime !== \"number\") return;\n\t\t\tif (item.startsWith(\" \") && words[words.length - 1]?.word.trim())\n\t\t\t\twords.push(createWord({ word: \" \" }));\n\t\t\twords.push(createWord({ word: item.trim(), startTime, endTime }));\n\t\t\tif (item.endsWith(\" \")) words.push(createWord({ word: \" \" }));\n\t\t});\n\n\t\tconst lineEndTime = words[words.length - 1]?.endTime ?? lineStartTime;\n\t\tlyricLines.push(\n\t\t\tcreateLine({\n\t\t\t\tstartTime: lineStartTime,\n\t\t\t\tendTime: lineEndTime,\n\t\t\t\twords,\n\t\t\t}),\n\t\t);\n\t}\n\treturn lyricLines;\n}\n\n/**\n * 将歌词数组转换为 LRC A2 格式的字符串\n * @param lines 歌词数组\n * @returns LRC A2 格式的字符串\n */\nexport function stringifyLrcA2(lines: LyricLine[]): string {\n\treturn lines\n\t\t.map((line) => {\n\t\t\tconst normalizedLineStartTime = normalizeTimestamp(line.startTime);\n\t\t\tif (line.words.length === 0)\n\t\t\t\treturn `[${formatTime(normalizedLineStartTime)}]`;\n\t\t\tconst normalizedWords: {\n\t\t\t\tword: string;\n\t\t\t\tstartTime: number;\n\t\t\t\tendTime: number;\n\t\t\t}[] = [];\n\t\t\tline.words.forEach((w) => {\n\t\t\t\tif (!w.word.trim() && normalizedWords.length) {\n\t\t\t\t\tnormalizedWords[normalizedWords.length - 1].word += w.word;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tnormalizedWords.push({\n\t\t\t\t\tword: w.word,\n\t\t\t\t\tstartTime: normalizeTimestamp(w.startTime),\n\t\t\t\t\tendTime: normalizeTimestamp(w.endTime),\n\t\t\t\t});\n\t\t\t});\n\t\t\tconst lineItems: (number | string)[] = normalizedWords.flatMap((w) => [\n\t\t\t\tw.startTime,\n\t\t\t\tw.word,\n\t\t\t]);\n\t\t\tlineItems.push(normalizedWords[normalizedWords.length - 1].endTime);\n\t\t\treturn (\n\t\t\t\t`[${formatTime(normalizedLineStartTime)}]` +\n\t\t\t\tlineItems\n\t\t\t\t\t.map((item) =>\n\t\t\t\t\t\ttypeof item === \"number\" ? `<${formatTime(item)}>` : item,\n\t\t\t\t\t)\n\t\t\t\t\t.join(\"\")\n\t\t\t);\n\t\t})\n\t\t.join(\"\\n\");\n}\n","/**\n * @fileoverview Lyricify Lines(LYL)格式解析与生成。\n * 该格式为行级结构,每行使用 `[start,end]` 表示时间区间。\n *\n * 格式示例:\n * [type:LyricifyLines]\n * [54260,57380]Stop and stare\n * [57380,62840]I think I'm moving but I go nowhere\n */\nimport type { LyricLine } from \"../types\";\nimport { createLine, createWord, normalizeTimestamp } from \"../utils\";\n\n/**\n * 解析 LYL 格式的歌词字符串\n * @param lyl 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseLyl(lyl: string): LyricLine[] {\n\tconst lines = lyl\n\t\t.split(/\\r?\\n/)\n\t\t.map((l) => l.trim())\n\t\t.filter((l) => l.length > 0);\n\tconst lyricLines: LyricLine[] = [];\n\tconst timeRegex = /^\\[(\\d+),(\\d+)\\](.*)$/;\n\tconst bgRegex = /^[((](.+)[))]$/;\n\n\tfor (const lineStr of lines) {\n\t\tif (lineStr === \"[type:LyricifyLines]\") continue;\n\n\t\tconst timeMatch = lineStr.match(timeRegex);\n\t\tif (!timeMatch) continue;\n\n\t\tconst [, startStr, endStr, text] = timeMatch;\n\t\tconst startTime = Number(startStr);\n\t\tconst endTime = Number(endStr);\n\n\t\tconst backgroundMatch = text.match(bgRegex);\n\t\tconst isBG = Boolean(backgroundMatch);\n\t\tconst textContent = (backgroundMatch ? backgroundMatch[1] : text).trim();\n\t\tif (!textContent) continue;\n\n\t\tlyricLines.push(\n\t\t\tcreateLine({\n\t\t\t\tstartTime,\n\t\t\t\tendTime,\n\t\t\t\tisBG,\n\t\t\t\twords: [createWord({ word: textContent, startTime, endTime })],\n\t\t\t}),\n\t\t);\n\t}\n\n\treturn lyricLines;\n}\n\n/**\n * 将歌词数组转换为 LYL 格式的字符串\n * @param lines 歌词数组\n * @returns LYL 格式的字符串\n */\nexport function stringifyLyl(lines: LyricLine[]): string {\n\tconst header = \"[type:LyricifyLines]\";\n\tconst body = lines.map((line) => {\n\t\tconst text = line.words.map((w) => w.word).join(\"\");\n\t\tconst printText = line.isBG ? `(${text})` : text;\n\t\treturn `[${normalizeTimestamp(line.startTime)},${normalizeTimestamp(line.endTime)}]${printText}`;\n\t});\n\treturn [header, ...body].join(\"\\n\");\n}\n","/**\n * @fileoverview QRC(QQ 音乐逐词歌词)格式解析与生成。\n * 行开头为 [startTime,duration],每个词为 word(startTime,duration)\n *\n * 格式示例:\n * [190871,1984]For (190871,361)the (191232,172)first (191404,376)time(191780,1075)\n * [193459,4198]What's (193459,412)past (193871,574)is (194445,506)past(194951,2706)\n */\nimport type { LyricLine, LyricWord } from \"../types\";\nimport {\n\tcreateLine,\n\tcreateWord,\n\tnormalizeDuration,\n\tnormalizeTimestamp,\n} from \"../utils\";\n\n/**\n * 解析 QRC 格式的歌词字符串\n * @param qrc 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseQrc(qrc: string): LyricLine[] {\n\tconst wordPattern = /(.*?)\\((\\d+),(\\d+)\\)/g;\n\tconst linePattern = /^\\[(\\d+),(\\d+)\\]/;\n\n\tconst lines = qrc\n\t\t.split(/\\r?\\n/)\n\t\t.map((l) => l.trim())\n\t\t.filter((l) => l.length > 0);\n\n\treturn lines\n\t\t.map((lineStr) => {\n\t\t\tconst lineMatch = lineStr.match(linePattern);\n\t\t\tif (!lineMatch) return null;\n\t\t\tconst [linePrefix, lineStartStr, lineDurStr] = lineMatch;\n\n\t\t\tconst lineStart = Number(lineStartStr);\n\t\t\tconst lineDuration = Number(lineDurStr);\n\n\t\t\tconst words: LyricWord[] = [];\n\t\t\tconst lineContent = lineStr.slice(linePrefix.length).trim();\n\t\t\tif (!lineContent) return null;\n\n\t\t\tfor (const wordMatch of lineContent.matchAll(wordPattern)) {\n\t\t\t\tconst [, wordText, wordStartStr, wordDurStr] = wordMatch;\n\t\t\t\tconst wordStart = Number(wordStartStr);\n\t\t\t\tconst wordDur = Number(wordDurStr);\n\n\t\t\t\twords.push(\n\t\t\t\t\tcreateWord({\n\t\t\t\t\t\tword: wordText,\n\t\t\t\t\t\tstartTime: wordStart,\n\t\t\t\t\t\tendTime: wordStart + wordDur,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst isBG =\n\t\t\t\twords.length > 0 &&\n\t\t\t\t/^[((]/.test(words[0].word) &&\n\t\t\t\t/[))]$/.test(words[words.length - 1].word);\n\n\t\t\tif (isBG) {\n\t\t\t\twords[0].word = words[0].word.replace(/^[((]/, \"\");\n\t\t\t\twords[words.length - 1].word = words[words.length - 1].word.replace(\n\t\t\t\t\t/[))]$/,\n\t\t\t\t\t\"\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createLine({\n\t\t\t\tstartTime: lineStart,\n\t\t\t\tendTime: lineStart + lineDuration,\n\t\t\t\twords,\n\t\t\t\tisBG,\n\t\t\t});\n\t\t})\n\t\t.filter((line) => line !== null);\n}\n\n/**\n * 将歌词数组转换为 QRC 格式的字符串\n * @param lines 歌词数组\n * @returns QRC 格式的字符串\n */\nexport function stringifyQrc(lines: LyricLine[]): string {\n\treturn lines\n\t\t.map((line) => {\n\t\t\tconst lineStart = normalizeTimestamp(line.startTime);\n\t\t\tconst lineEnd = normalizeTimestamp(line.endTime);\n\t\t\tconst lineDuration = normalizeDuration(lineEnd - lineStart);\n\n\t\t\tconst lineWords: string[] = [];\n\t\t\tfor (const [\n\t\t\t\tindex,\n\t\t\t\t{ word, startTime, endTime },\n\t\t\t] of line.words.entries()) {\n\t\t\t\tif (!word.trim() && lineWords.length) {\n\t\t\t\t\tlineWords[lineWords.length - 1] += word;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlet printedWord = word;\n\t\t\t\tif (line.isBG) {\n\t\t\t\t\tif (index === 0) printedWord = `(${printedWord}`;\n\t\t\t\t\tif (index === line.words.length - 1) printedWord += \")\";\n\t\t\t\t}\n\t\t\t\tconst normalizedWordStart = normalizeTimestamp(startTime);\n\t\t\t\tconst normalizedWordEnd = normalizeTimestamp(endTime);\n\t\t\t\tconst wordDuration = normalizeDuration(\n\t\t\t\t\tnormalizedWordEnd - normalizedWordStart,\n\t\t\t\t);\n\t\t\t\tlineWords.push(\n\t\t\t\t\t`${printedWord}(${normalizedWordStart},${wordDuration})`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn `[${lineStart},${lineDuration}]${lineWords.join(\"\")}`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n","import {\n\texportTTML,\n\tparseTTML as parseTTMLPacked,\n} from \"@applemusic-like-lyrics/ttml\";\nimport type { TTMLLyric } from \"../types\";\n\n/**\n * 解析 TTML 格式(包含 AMLL 特有属性信息)的歌词字符串\n * @param ttmlText 歌词字符串\n * @returns 成功解析出来的 TTML 歌词对象\n */\nexport function parseTTML(ttmlText: string): TTMLLyric {\n\treturn parseTTMLPacked(ttmlText);\n}\n\n/**\n * 将歌词数组转换为 TTML 格式(包含 AMLL 特有属性信息)的歌词字符串\n * @param ttmlLyric TTML 歌词对象\n */\nexport function stringifyTTML(ttmlLyric: TTMLLyric): string {\n\treturn exportTTML(ttmlLyric);\n}\n","/**\n * @fileoverview YRC(网易云音乐逐词歌词)格式解析与生成。\n * 行开头为 [startTime,duration],每个词为 (startTime,duration,0)word\n *\n * 格式示例:\n * [190871,1984](190871,361,0)For (191232,172,0)the (191404,376,0)first (191780,1075,0)time\n * [193459,4198](193459,412,0)What's (193871,574,0)past (194445,506,0)is (194951,2706,0)past\n */\nimport type { LyricLine, LyricWord } from \"../types\";\nimport {\n\tcreateLine,\n\tcreateWord,\n\tnormalizeDuration,\n\tnormalizeTimestamp,\n} from \"../utils\";\n\nconst beginParenPattern = /^[((]/;\nconst endParenPattern = /[))]$/;\nfunction checkIsBG(words: LyricWord[]): boolean {\n\treturn (\n\t\twords.length > 0 &&\n\t\tbeginParenPattern.test(words[0].word) &&\n\t\tendParenPattern.test(words[words.length - 1].word)\n\t);\n}\nfunction trimBGParentheses(words: LyricWord[]): void {\n\twords[0].word = words[0].word.slice(1);\n\twords[words.length - 1].word = words[words.length - 1].word.slice(0, -1);\n}\n\n/**\n * 解析 YRC 格式的歌词字符串\n * @param yrc 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseYrc(yrc: string): LyricLine[] {\n\tconst wordPattern = /^(.*?)\\((\\d+),(\\d+),0\\)/;\n\tconst linePattern = /^\\[(\\d+),(\\d+)\\]/;\n\n\tconst lines = yrc\n\t\t.split(/\\r?\\n/)\n\t\t.map((l) => l.trim())\n\t\t.filter((l) => l.length > 0);\n\n\treturn lines\n\t\t.map((lineStr) => {\n\t\t\tconst lineMatch = lineStr.match(linePattern);\n\t\t\tif (!lineMatch) return null;\n\t\t\tconst [linePrefix, lineStartStr, lineDurStr] = lineMatch;\n\t\t\tconst lineStart = Number(lineStartStr);\n\t\t\tconst lineDuration = Number(lineDurStr);\n\n\t\t\tconst words: LyricWord[] = [];\n\t\t\tlet lineContent = lineStr.slice(linePrefix.length).trim();\n\t\t\tif (!lineContent) return null;\n\n\t\t\tlet lastStart = -1;\n\t\t\tlet lastEnd = -1;\n\t\t\twhile (true) {\n\t\t\t\tconst wordMatch = lineContent.match(wordPattern);\n\t\t\t\tif (!wordMatch) break;\n\t\t\t\tconst [fullMatch, lastText, wordStartStr, wordDurStr] = wordMatch;\n\t\t\t\tif (lastText && lastStart !== -1)\n\t\t\t\t\twords.push(\n\t\t\t\t\t\tcreateWord({\n\t\t\t\t\t\t\tword: lastText,\n\t\t\t\t\t\t\tstartTime: lastStart,\n\t\t\t\t\t\t\tendTime: lastEnd,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\tconst wordStart = Number(wordStartStr);\n\t\t\t\tconst wordDur = Number(wordDurStr);\n\t\t\t\tconst wordEnd = wordStart + wordDur;\n\t\t\t\t[lastStart, lastEnd] = [wordStart, wordEnd];\n\t\t\t\tlineContent = lineContent.slice(fullMatch.length);\n\t\t\t}\n\t\t\tif (lastStart !== -1 && lineContent)\n\t\t\t\twords.push(\n\t\t\t\t\tcreateWord({\n\t\t\t\t\t\tword: lineContent,\n\t\t\t\t\t\tstartTime: lastStart,\n\t\t\t\t\t\tendTime: lastEnd,\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\tconst isBG = checkIsBG(words);\n\t\t\tif (isBG) trimBGParentheses(words);\n\t\t\treturn createLine({\n\t\t\t\tstartTime: lineStart,\n\t\t\t\tendTime: lineStart + lineDuration,\n\t\t\t\twords,\n\t\t\t\tisBG,\n\t\t\t});\n\t\t})\n\t\t.filter((line): line is LyricLine => line !== null);\n}\n\nfunction makeParenthesesFull(text: string): string {\n\treturn text.replace(/\\(/g, \"(\").replace(/\\)/g, \")\");\n}\n\n/**\n * 将歌词数组转换为 YRC 格式的字符串\n * @param lines 歌词数组\n * @returns YRC 格式的字符串\n */\nexport function stringifyYrc(lines: LyricLine[]): string {\n\treturn lines\n\t\t.map((line) => {\n\t\t\tconst lineStart = normalizeTimestamp(line.startTime);\n\t\t\tconst lineEnd = normalizeTimestamp(line.endTime);\n\t\t\tconst lineDuration = normalizeDuration(lineEnd - lineStart);\n\n\t\t\tconst lineWords: string[] = [];\n\t\t\tfor (const [\n\t\t\t\tindex,\n\t\t\t\t{ word, startTime, endTime },\n\t\t\t] of line.words.entries()) {\n\t\t\t\tif (!word.trim() && lineWords.length) {\n\t\t\t\t\tlineWords[lineWords.length - 1] += word;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlet printedWord = makeParenthesesFull(word);\n\t\t\t\tif (line.isBG) {\n\t\t\t\t\tif (index === 0) printedWord = `(${printedWord}`;\n\t\t\t\t\tif (index === line.words.length - 1) printedWord += \")\";\n\t\t\t\t}\n\t\t\t\tconst normalizedWordStart = normalizeTimestamp(startTime);\n\t\t\t\tconst normalizedWordEnd = normalizeTimestamp(endTime);\n\t\t\t\tconst wordDuration = normalizeDuration(\n\t\t\t\t\tnormalizedWordEnd - normalizedWordStart,\n\t\t\t\t);\n\t\t\t\tlineWords.push(\n\t\t\t\t\t`(${normalizedWordStart},${wordDuration},0)${printedWord}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn `[${lineStart},${lineDuration}]${lineWords.join(\"\")}`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n","export { stringifyAss } from \"./formats/ass\";\nexport { decryptQrcHex, encryptQrcHex } from \"./formats/eqrc\";\nexport { parseEslrc, stringifyEslrc } from \"./formats/eslrc\";\nexport { parseLqe, stringifyLqe } from \"./formats/lqe\";\nexport { parseLrc, stringifyLrc } from \"./formats/lrc\";\nexport { parseLrcA2, stringifyLrcA2 } from \"./formats/lrca2\";\nexport { parseLyl, stringifyLyl } from \"./formats/lyl\";\nexport { parseLys, stringifyLys } from \"./formats/lys\";\nexport { parseQrc, stringifyQrc } from \"./formats/qrc\";\nexport { parseTTML, stringifyTTML } from \"./formats/ttml\";\nexport { parseYrc, stringifyYrc } from \"./formats/yrc\";\n\nimport { stringifyLrcA2 } from \"./formats/lrca2\";\n\n/**\n * {@link stringifyLrcA2} 的别名。\n *\n * @deprecated 此为兼容旧版本拼写错误的接口,请改用 `stringifyLrcA2`。此接口将在未来版本中移除。\n */\nexport function stringifylrcA2(\n\t...args: Parameters<typeof stringifyLrcA2>\n): ReturnType<typeof stringifyLrcA2> {\n\treturn stringifyLrcA2(...args);\n}\n\nexport type { LyricLine, LyricWord, TTMLLyric } from \"./types\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"amll-lyric.mjs","names":["parseTTMLPacked"],"sources":["../src/utils.ts","../src/formats/ass.ts","../src/formats/eqrc/constants.ts","../src/formats/eqrc/custom-des.ts","../src/formats/eqrc/utils.ts","../src/formats/eqrc/index.ts","../src/formats/lys.ts","../src/formats/lqe.ts","../src/formats/lrc/helpers.ts","../src/formats/lrc/metadata.ts","../src/formats/lrc/types.ts","../src/formats/lrc/generator.ts","../src/formats/lrc/parser.ts","../src/formats/lrc/index.ts","../src/formats/lyl.ts","../src/formats/qrc.ts","../src/formats/ttml.ts","../src/formats/yrc.ts","../src/index.ts"],"sourcesContent":["import type { LyricLine, LyricWord } from \"./types\";\n\nexport const createLine = (line: Partial<LyricLine>): LyricLine => ({\n\twords: [],\n\ttranslatedLyric: \"\",\n\tromanLyric: \"\",\n\tisBG: false,\n\tisDuet: false,\n\tstartTime: 0,\n\tendTime: 0,\n\t...line,\n});\n\nexport const createWord = (word: Partial<LyricWord>): LyricWord => ({\n\tstartTime: 0,\n\tendTime: 0,\n\tword: \"\",\n\t...word,\n});\n\nexport const parseTime = (time: string): number =>\n\tMath.round(\n\t\ttime\n\t\t\t.split(\":\")\n\t\t\t.map(Number)\n\t\t\t.reverse()\n\t\t\t.reduce((acc, cur, idx) => acc + cur * 60 ** idx, 0) * 1000,\n\t);\n\n/**\n * 将一个时间戳的分、秒、毫秒三段文本转换为毫秒。\n *\n * 毫秒段可以省略,省略时按 `0` 计;\n * 毫秒不足三位时视为在后位省略了 `0`,即 `.1` 为 100 毫秒、`.02` 为 20 毫秒;\n * 超过三位的部分直接截断。\n */\nexport const parseTimestampParts = (\n\tminStr: string,\n\tsecStr: string,\n\tmsStr = \"\",\n): number =>\n\tparseInt(minStr, 10) * 60000 +\n\tparseInt(secStr, 10) * 1000 +\n\tparseInt(`${msStr}000`.slice(0, 3), 10);\n\nexport const formatTime = (ms: number): string => {\n\tconst min = Math.floor(ms / 60000)\n\t\t.toString()\n\t\t.padStart(2, \"0\");\n\tconst sec = Math.floor((ms % 60000) / 1000)\n\t\t.toString()\n\t\t.padStart(2, \"0\");\n\t// 截断而非进位,否则毫秒带小数时会溢出成四位数\n\tconst msPart = Math.floor(ms % 1000)\n\t\t.toString()\n\t\t.padStart(3, \"0\");\n\treturn `${min}:${sec}.${msPart}`;\n};\n\nexport const normalizeTimestamp = (ms: number): number => {\n\tif (!Number.isFinite(ms) || ms < 0) return 0;\n\treturn ms;\n};\n\nexport const normalizeDuration = (duration: number): number => {\n\tif (!Number.isFinite(duration) || duration < 0) return 0;\n\treturn duration;\n};\n\n/**\n * LRC 家族时间戳可表示的最大值,即 `999:59.999`\n *\n * 时间戳的分钟为 1 至 3 位、秒为 1 至 2 位、毫秒为 1 至 6 位,\n * 因此能写出来又读得回来的最大时间就到这里\n */\nexport const MAX_LRC_TIMESTAMP: number = parseTimestampParts(\n\t\"999\",\n\t\"59\",\n\t\"999\",\n);\n\n/**\n * 将时间钳制到 LRC 家族可表示的范围内\n * @param ms 时间,单位为毫秒\n * @returns 钳制后的时间\n */\nexport const clampTimestamp = (ms: number): number =>\n\tMath.min(MAX_LRC_TIMESTAMP, normalizeTimestamp(ms));\n\nexport type DeepRequired<T> = T extends object\n\t? { [P in keyof T]-?: DeepRequired<NonNullable<T[P]>> }\n\t: T;\n","/**\n * @fileoverview ASS 字幕格式导出。\n * 注意导出会损失 10ms 以内精度(按厘秒四舍五入)。\n *\n * 格式示例:\n * Dialogue: 0,0:00:12.34, 0:00:15.67, Default, v1,0,0,0,,{\\k20}Hello{\\k15} world\n * Dialogue: 0,0:00:12.34, 0:00:15.67, Default, v1-trans,0,0,0,,你好 世界\n * Dialogue: 0,0:00:12.34, 0:00:15.67, Default, v1-roman,0,0,0,,ni hao shi jie\n */\nimport type { LyricLine } from \"../types\";\nimport { normalizeTimestamp } from \"../utils\";\n\nfunction writeASSTimestamp(ms: number): string {\n\tconst normalized = normalizeTimestamp(ms);\n\tconst milli = Math.round(normalized) % 1000;\n\tconst secTotal = Math.floor(Math.round(normalized) / 1000);\n\tconst sec = secTotal % 60;\n\tconst minTotal = Math.floor(secTotal / 60);\n\tconst hour = Math.floor(minTotal / 60);\n\treturn `${hour}:${String(minTotal % 60).padStart(2, \"0\")}:${String(sec).padStart(2, \"0\")}.${String(Math.floor(milli / 10)).padStart(2, \"0\")}`;\n}\n\nfunction getSpeakerName(line: LyricLine): string {\n\tlet name = line.isDuet ? \"v2\" : \"v1\";\n\tif (line.isBG) name += \"-bg\";\n\treturn name;\n}\n\nfunction writeLyricDialogue(\n\tresult: string[],\n\tstartTime: number,\n\tendTime: number,\n\tname: string,\n\ttext: string,\n) {\n\tresult.push(\n\t\t`Dialogue: 0,${writeASSTimestamp(startTime)}, ${writeASSTimestamp(endTime)}, Default, ${name},0,0,0,,${text}`,\n\t);\n}\n\n/**\n * 将歌词数组转换为 ASS 字幕格式字符串\n * @param lines 歌词数组\n * @returns ASS 字幕格式字符串\n */\nexport function stringifyAss(lines: LyricLine[]): string {\n\tconst result: string[] = [\n\t\t\"[Script Info]\",\n\t\t\"[Events]\",\n\t\t\"Formats: Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\",\n\t];\n\n\tfor (const line of lines) {\n\t\tconst timedWords = line.words\n\t\t\t.map((w) => ({\n\t\t\t\t...w,\n\t\t\t\tstartTime: normalizeTimestamp(w.startTime),\n\t\t\t\tendTime: normalizeTimestamp(w.endTime),\n\t\t\t}))\n\t\t\t.filter((w) => w.endTime > w.startTime);\n\t\tconst startTime = Math.min(...timedWords.map((w) => w.startTime));\n\t\tconst endTime = Math.max(...timedWords.map((w) => w.endTime));\n\t\tif (!Number.isFinite(startTime) || !Number.isFinite(endTime)) continue;\n\n\t\tlet lyricText = \"\";\n\t\tlet previousWordEndTime = startTime;\n\t\tfor (const word of line.words) {\n\t\t\tconst wordStart = normalizeTimestamp(word.startTime);\n\t\t\tconst wordEnd = normalizeTimestamp(word.endTime);\n\t\t\tif (wordStart >= wordEnd) {\n\t\t\t\tlyricText += word.word;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (wordStart > previousWordEndTime) {\n\t\t\t\tconst gapDurationCS = Math.floor(\n\t\t\t\t\t(wordStart - previousWordEndTime + 5) / 10,\n\t\t\t\t);\n\t\t\t\tif (gapDurationCS > 0) lyricText += `{\\\\k${gapDurationCS}}`;\n\t\t\t}\n\n\t\t\tconst wordDurationCS = Math.floor((wordEnd - wordStart + 5) / 10);\n\t\t\tif (wordDurationCS > 0) lyricText += `{\\\\k${wordDurationCS}}`;\n\t\t\tlyricText += word.word;\n\t\t\tpreviousWordEndTime = wordEnd;\n\t\t}\n\n\t\tconst speaker = getSpeakerName(line);\n\t\twriteLyricDialogue(result, startTime, endTime, speaker, lyricText);\n\t\tif (line.translatedLyric)\n\t\t\twriteLyricDialogue(\n\t\t\t\tresult,\n\t\t\t\tstartTime,\n\t\t\t\tendTime,\n\t\t\t\t`${speaker}-trans`,\n\t\t\t\tline.translatedLyric,\n\t\t\t);\n\t\tif (line.romanLyric)\n\t\t\twriteLyricDialogue(\n\t\t\t\tresult,\n\t\t\t\tstartTime,\n\t\t\t\tendTime,\n\t\t\t\t`${speaker}-roman`,\n\t\t\t\tline.romanLyric,\n\t\t\t);\n\t}\n\n\treturn `${result.join(\"\\n\")}\\n`;\n}\n","/**\n * @internal\n * @module constants\n * @description\n * 包含了所有 `custom_des` 模块所需的常量数据。\n */\n\n// 解密使用的3个8字节的DES密钥\nexport const KEY_1: Uint8Array = new TextEncoder().encode(\"!@#)(*$%\");\nexport const KEY_2: Uint8Array = new TextEncoder().encode(\"123ZXC!@\");\nexport const KEY_3: Uint8Array = new TextEncoder().encode(\"!@#)(NHL\");\n\n// --- QQ 音乐使用的非标准 S 盒定义 ---\n\nconst SBOX1: number[] = [\n\t14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 0, 15, 7, 4, 14, 2, 13,\n\t1, 10, 6, 12, 11, 9, 5, 3, 8, 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10,\n\t5, 0, 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,\n];\nconst SBOX2: number[] = [\n\t15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 3, 13, 4, 7, 15, 2, 8,\n\t15, 12, 0, 1, 10, 6, 9, 11, 5, 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3,\n\t2, 15, 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,\n];\nconst SBOX3: number[] = [\n\t10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 13, 7, 0, 9, 3, 4, 6,\n\t10, 2, 8, 5, 14, 12, 11, 15, 1, 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10,\n\t14, 7, 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,\n];\nconst SBOX4: number[] = [\n\t7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 13, 8, 11, 5, 6, 15, 0,\n\t3, 4, 7, 2, 12, 1, 10, 14, 9, 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2,\n\t8, 4, 3, 15, 0, 6, 10, 10, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,\n];\nconst SBOX5: number[] = [\n\t2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 14, 11, 2, 12, 4, 7, 13,\n\t1, 5, 0, 15, 10, 3, 9, 8, 6, 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0,\n\t14, 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,\n];\nconst SBOX6: number[] = [\n\t12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 10, 15, 4, 2, 7, 12, 9,\n\t5, 6, 1, 13, 14, 0, 11, 3, 8, 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13,\n\t11, 6, 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,\n];\nconst SBOX7: number[] = [\n\t4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 13, 0, 11, 7, 4, 9, 1,\n\t10, 14, 3, 5, 12, 2, 15, 8, 6, 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5,\n\t9, 2, 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,\n];\nconst SBOX8: number[] = [\n\t13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 1, 15, 13, 8, 10, 3, 7,\n\t4, 12, 5, 6, 11, 0, 14, 9, 2, 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3,\n\t5, 8, 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11,\n];\n\nexport const S_BOXES: number[][] = [\n\tSBOX1,\n\tSBOX2,\n\tSBOX3,\n\tSBOX4,\n\tSBOX5,\n\tSBOX6,\n\tSBOX7,\n\tSBOX8,\n];\n\n// QQ 音乐使用的标准 P 盒置换规则\nexport const P_BOX: number[] = [\n\t16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, 2, 8, 24, 14, 32,\n\t27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25,\n];\n\n/// QQ 音乐使用的标准扩展置换表。\nexport const E_BOX_TABLE: number[] = [\n\t32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16,\n\t17, 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 24, 25, 26, 27, 28, 29,\n\t28, 29, 30, 31, 32, 1,\n];\n\n// 每轮循环左移的位数表\nexport const KEY_RND_SHIFT: number[] = [\n\t1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1,\n];\n\n// 置换选择1 (PC-1) - C部分\nexport const KEY_PERM_C: number[] = [\n\t56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34,\n\t26, 18, 10, 2, 59, 51, 43, 35,\n];\n\n// 置换选择1 (PC-1) - D部分\nexport const KEY_PERM_D: number[] = [\n\t62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36,\n\t28, 20, 12, 4, 27, 19, 11, 3,\n];\n\n// 置换选择2 (PC-2)\nexport const KEY_COMPRESSION: number[] = [\n\t13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26,\n\t19, 12, 1, 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33,\n\t52, 45, 41, 49, 35, 28, 31,\n];\n","/**\n * @internal\n * @module custom_des\n * @description\n * 本模块包含了为解密 QRC 歌词而移植的、非标准的类 DES 算法的底层实现。\n *\n * <h2>\n * <strong>警告:该 DES 实现并非标准实现!</strong>\n * </h2>\n *\n * 它是结构类似DES的、但完全私有的分组密码算法。\n * 本实现仅用于 QRC 歌词解密,不应用于实际安全目的。\n */\n\nimport {\n\tE_BOX_TABLE,\n\tKEY_COMPRESSION,\n\tKEY_PERM_C,\n\tKEY_PERM_D,\n\tKEY_RND_SHIFT,\n\tP_BOX,\n\tS_BOXES,\n} from \"./constants\";\n\nexport enum Mode {\n\tEncrypt,\n\tDecrypt,\n}\n\nexport type KeySchedule = Int32Array;\n\n/**\n * 从8字节密钥中根据置换表提取位,生成一个 BigInt。\n *\n * 这个函数对应原始C代码中的天书BITNUM宏,模拟 QQ 音乐特有的非标准的字节序处理方式。\n * 其将 8 字节密钥视为两个独立的、小端序的32位整数拼接而成。\n *\n * 例如,要读取第0位(MSB),它实际访问的是 `key[3]` 的最高位。\n * 要读取第31位,它访问的是 `key[0]` 的最低位。\n *\n * @param key 8字节的密钥 Uint8Array\n * @param table 0-based 的位索引置换表\n */\nfunction permuteFromKeyBytes(key: Uint8Array, table: number[]): bigint {\n\tlet output = 0n;\n\tlet currentBitMask = 1n << BigInt(table.length - 1);\n\n\tfor (let i = 0; i < table.length; i++) {\n\t\tconst pos = table[i];\n\n\t\tconst wordIndex = pos >> 5;\n\t\tconst bitInWord = pos & 31;\n\t\tconst byteInWord = bitInWord >> 3;\n\t\tconst bitInByte = bitInWord & 7;\n\t\tconst byteIndex = wordIndex * 4 + 3 - byteInWord;\n\n\t\tconst bit = (key[byteIndex] >> (7 - bitInByte)) & 1;\n\n\t\tif (bit) {\n\t\t\toutput |= currentBitMask;\n\t\t}\n\t\tcurrentBitMask >>= 1n;\n\t}\n\treturn output;\n}\n\n/**\n * 对一个存储在 BigInt 中的28位密钥部分进行循环左移。\n * @param value 包含28位数据的高位的 BigInt\n * @param amount 左移的位数\n */\nfunction rotateLeft28Bit(value: bigint, amount: number): bigint {\n\tconst BITS_28_MASK = 0xfffffff0n;\n\tconst val = value & BITS_28_MASK;\n\tconst shifted = (val << BigInt(amount)) | (val >> BigInt(28 - amount));\n\treturn shifted & BITS_28_MASK;\n}\n\n/**\n * DES 密钥调度算法。\n * 从一个64位的主密钥(实际使用56位,每字节的最低位是奇偶校验位,被忽略)\n * 生成16个48位的轮密钥。\n *\n * @param key 8字节的DES密钥\n * @param mode 加密或解密模式\n */\nexport function keySchedule(key: Uint8Array, mode: Mode): KeySchedule {\n\t// 预先分配连续的内存空间\n\tconst schedule = new Int32Array(32);\n\n\t// 应用 PC-1\n\tconst c0 = permuteFromKeyBytes(key, KEY_PERM_C);\n\tconst d0 = permuteFromKeyBytes(key, KEY_PERM_D);\n\n\t// 将28位的结果左移4位,以匹配 `rotateLeft28Bit` 对高位对齐的期望。\n\tlet c = c0 << 4n;\n\tlet d = d0 << 4n;\n\n\tfor (let i = 0; i < 16; i++) {\n\t\tconst shift = KEY_RND_SHIFT[i];\n\t\tc = rotateLeft28Bit(c, shift);\n\t\td = rotateLeft28Bit(d, shift);\n\n\t\tconst toGen = mode === Mode.Decrypt ? 15 - i : i;\n\n\t\tlet subkey48bit = 0n;\n\t\t// 应用 PC-2\n\t\tfor (let k = 0; k < KEY_COMPRESSION.length; k++) {\n\t\t\tconst pos = KEY_COMPRESSION[k];\n\n\t\t\tconst bitBigInt =\n\t\t\t\tpos < 28\n\t\t\t\t\t? (c >> BigInt(31 - pos)) & 1n\n\t\t\t\t\t: (d >> BigInt(31 - (pos - 27))) & 1n; // QQ 音乐特有的怪癖,该算法的规则就是pos - 27\n\n\t\t\tif (bitBigInt === 1n) {\n\t\t\t\tsubkey48bit |= 1n << BigInt(47 - k);\n\t\t\t}\n\t\t}\n\n\t\t// 提取高 24 位 (由第 5, 4, 3 字节组成)\n\t\tconst b5 = Number((subkey48bit >> 40n) & 0xffn);\n\t\tconst b4 = Number((subkey48bit >> 32n) & 0xffn);\n\t\tconst b3 = Number((subkey48bit >> 24n) & 0xffn);\n\t\tconst high24 = (b5 << 16) | (b4 << 8) | b3;\n\n\t\t// 提取低 24 位 (由第 2, 1, 0 字节组成)\n\t\tconst b2 = Number((subkey48bit >> 16n) & 0xffn);\n\t\tconst b1 = Number((subkey48bit >> 8n) & 0xffn);\n\t\tconst b0 = Number(subkey48bit & 0xffn);\n\t\tconst low24 = (b2 << 16) | (b1 << 8) | b0;\n\n\t\t// 存储到一维数组中\n\t\tschedule[toGen * 2] = high24;\n\t\tschedule[toGen * 2 + 1] = low24;\n\t}\n\n\treturn schedule;\n}\n\n// 初始置换规则。\nconst IP_RULE: number[] = [\n\t34, 42, 50, 58, 2, 10, 18, 26, 36, 44, 52, 60, 4, 12, 20, 28, 38, 46, 54, 62,\n\t6, 14, 22, 30, 40, 48, 56, 64, 8, 16, 24, 32, 33, 41, 49, 57, 1, 9, 17, 25,\n\t35, 43, 51, 59, 3, 11, 19, 27, 37, 45, 53, 61, 5, 13, 21, 29, 39, 47, 55, 63,\n\t7, 15, 23, 31,\n];\n\n// 逆初始置换规则。\nconst INV_IP_RULE: number[] = [\n\t37, 5, 45, 13, 53, 21, 61, 29, 38, 6, 46, 14, 54, 22, 62, 30, 39, 7, 47, 15,\n\t55, 23, 63, 31, 40, 8, 48, 16, 56, 24, 64, 32, 33, 1, 41, 9, 49, 17, 57, 25,\n\t34, 2, 42, 10, 50, 18, 58, 26, 35, 3, 43, 11, 51, 19, 59, 27, 36, 4, 44, 12,\n\t52, 20, 60, 28,\n];\n\nconst IP_LEFT_TABLE = new Int32Array(2048);\nconst IP_RIGHT_TABLE = new Int32Array(2048);\nconst INV_IP_LEFT_TABLE = new Int32Array(2048);\nconst INV_IP_RIGHT_TABLE = new Int32Array(2048);\n\nfunction generatePermutationTables(): void {\n\tconst applyPermutation = (input: bigint, rule: number[]): bigint => {\n\t\tlet output = 0n;\n\t\tfor (let i = 0; i < 64; i++) {\n\t\t\tconst srcBit1Based = rule[i];\n\t\t\tif ((input >> BigInt(64 - srcBit1Based)) & 1n) {\n\t\t\t\toutput |= 1n << BigInt(63 - i);\n\t\t\t}\n\t\t}\n\t\treturn output;\n\t};\n\n\t// 生成 IP 结果查找表\n\tfor (let bytePos = 0; bytePos < 8; bytePos++) {\n\t\tfor (let byteVal = 0; byteVal < 256; byteVal++) {\n\t\t\tconst input = BigInt(byteVal) << BigInt(56 - bytePos * 8);\n\t\t\tconst permuted = applyPermutation(input, IP_RULE);\n\t\t\tconst idx = (bytePos << 8) | byteVal;\n\t\t\tIP_LEFT_TABLE[idx] = Number((permuted >> 32n) & 0xffffffffn);\n\t\t\tIP_RIGHT_TABLE[idx] = Number(permuted & 0xffffffffn);\n\t\t}\n\t}\n\n\t// 生成 InvIP 结果查找表 (一维 TypedArray,分为左右 32 位以避免 BigInt)\n\tfor (let blockPos = 0; blockPos < 8; blockPos++) {\n\t\tfor (let blockVal = 0; blockVal < 256; blockVal++) {\n\t\t\tconst input = BigInt(blockVal) << BigInt(56 - blockPos * 8);\n\t\t\tconst permuted = applyPermutation(input, INV_IP_RULE);\n\t\t\tconst idx = (blockPos << 8) | blockVal;\n\t\t\tINV_IP_LEFT_TABLE[idx] = Number((permuted >> 32n) & 0xffffffffn);\n\t\t\tINV_IP_RIGHT_TABLE[idx] = Number(permuted & 0xffffffffn);\n\t\t}\n\t}\n}\ngeneratePermutationTables();\n\n/**\n * 计算 DES S-盒的查找索引。\n * @param a 一个包含6位数据的 u8\n */\nfunction calculateSboxIndex(a: number): number {\n\treturn (a & 0x20) | ((a & 0x1f) >> 1) | ((a & 0x01) << 4);\n}\n\n/**\n * 对一个 32 位整数应用非标准的 P 盒置换规则。\n * @param input S-盒代换后的 32 位中间结果\n */\nfunction applyQqPboxPermutation(input: number): number {\n\tlet output = 0;\n\tfor (let i = 0; i < 32; i++) {\n\t\tconst sourceBit1Based = P_BOX[i];\n\t\tconst destBitMask = 1 << (31 - i);\n\t\tconst sourceBitMask = 1 << (32 - sourceBit1Based);\n\t\tif ((input & sourceBitMask) !== 0) {\n\t\t\toutput |= destBitMask;\n\t\t}\n\t}\n\treturn output;\n}\n\nconst SP_TABLE = new Int32Array(512);\n\n/**\n * 生成 S-P 盒合并查找表以提高性能。\n */\nfunction generateSpTables(): void {\n\tfor (let sBoxIdx = 0; sBoxIdx < 8; sBoxIdx++) {\n\t\tfor (let sBoxInput = 0; sBoxInput < 64; sBoxInput++) {\n\t\t\tconst sBoxIndex = calculateSboxIndex(sBoxInput);\n\t\t\tconst fourBitOutput = S_BOXES[sBoxIdx][sBoxIndex];\n\t\t\tconst prePBoxVal = fourBitOutput << (28 - sBoxIdx * 4);\n\t\t\tSP_TABLE[(sBoxIdx << 6) | sBoxInput] = applyQqPboxPermutation(prePBoxVal);\n\t\t}\n\t}\n}\ngenerateSpTables();\n\nconst EBOX_HIGH_TABLE = new Int32Array(1024);\nconst EBOX_LOW_TABLE = new Int32Array(1024);\n\nfunction generateEBoxTables(): void {\n\tfor (let chunkIdx = 0; chunkIdx < 4; chunkIdx++) {\n\t\tconst shiftIn32 = (3 - chunkIdx) * 8;\n\n\t\tfor (let byteVal = 0; byteVal < 256; byteVal++) {\n\t\t\tlet high24 = 0;\n\t\t\tlet low24 = 0;\n\t\t\tconst input = byteVal << shiftIn32;\n\n\t\t\tfor (let i = 0; i < 24; i++) {\n\t\t\t\tconst sourceBitPos = E_BOX_TABLE[i];\n\t\t\t\tconst bit = (input >>> (32 - sourceBitPos)) & 1;\n\t\t\t\tif (bit) {\n\t\t\t\t\thigh24 |= 1 << (23 - i);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (let i = 24; i < 48; i++) {\n\t\t\t\tconst sourceBitPos = E_BOX_TABLE[i];\n\t\t\t\tconst bit = (input >>> (32 - sourceBitPos)) & 1;\n\t\t\t\tif (bit) {\n\t\t\t\t\tlow24 |= 1 << (47 - i);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst tableIdx = (chunkIdx << 8) | byteVal;\n\t\t\tEBOX_HIGH_TABLE[tableIdx] = high24;\n\t\t\tEBOX_LOW_TABLE[tableIdx] = low24;\n\t\t}\n\t}\n}\ngenerateEBoxTables();\n\n/**\n * DES 的 F 函数。\n */\nfunction fFunction(state: number, keyHigh24: number, keyLow24: number): number {\n\t// 将 32 位状态拆分为 4 个字节,直接查表并进行按位或拼接\n\tconst b0 = (state >>> 24) & 0xff;\n\tconst b1 = (state >>> 16) & 0xff;\n\tconst b2 = (state >>> 8) & 0xff;\n\tconst b3 = state & 0xff;\n\n\tconst eboxHigh24 =\n\t\tEBOX_HIGH_TABLE[b0] |\n\t\tEBOX_HIGH_TABLE[256 | b1] |\n\t\tEBOX_HIGH_TABLE[512 | b2] |\n\t\tEBOX_HIGH_TABLE[768 | b3];\n\tconst eboxLow24 =\n\t\tEBOX_LOW_TABLE[b0] |\n\t\tEBOX_LOW_TABLE[256 | b1] |\n\t\tEBOX_LOW_TABLE[512 | b2] |\n\t\tEBOX_LOW_TABLE[768 | b3];\n\n\tconst xorHigh24 = eboxHigh24 ^ keyHigh24;\n\tconst xorLow24 = eboxLow24 ^ keyLow24;\n\n\treturn (\n\t\tSP_TABLE[(xorHigh24 >>> 18) & 0x3f] |\n\t\tSP_TABLE[64 | ((xorHigh24 >>> 12) & 0x3f)] |\n\t\tSP_TABLE[128 | ((xorHigh24 >>> 6) & 0x3f)] |\n\t\tSP_TABLE[192 | (xorHigh24 & 0x3f)] |\n\t\tSP_TABLE[256 | ((xorLow24 >>> 18) & 0x3f)] |\n\t\tSP_TABLE[320 | ((xorLow24 >>> 12) & 0x3f)] |\n\t\tSP_TABLE[384 | ((xorLow24 >>> 6) & 0x3f)] |\n\t\tSP_TABLE[448 | (xorLow24 & 0x3f)]\n\t);\n}\n\n/**\n * DES 加密/解密单个64位数据块。\n *\n * @param input 8字节的输入数据块 (明文或密文)。\n * @param output 8字节的可变切片,用于存储输出数据块 (密文或明文)。\n * @param keySchedule 一个包含16个轮密钥的向量的引用,每个轮密钥是6字节。\n */\nexport function desCrypt(\n\tinput: Uint8Array,\n\toutput: Uint8Array,\n\tkeySchedule: KeySchedule,\n): void {\n\tlet left = 0;\n\tlet right = 0;\n\tfor (let i = 0; i < 8; i++) {\n\t\tconst idx = (i << 8) | input[i];\n\t\tleft |= IP_LEFT_TABLE[idx];\n\t\tright |= IP_RIGHT_TABLE[idx];\n\t}\n\n\tfor (let i = 0; i < 15; i++) {\n\t\tconst temp = right;\n\t\tright =\n\t\t\t(left ^ fFunction(right, keySchedule[i * 2], keySchedule[i * 2 + 1])) >>>\n\t\t\t0;\n\t\tleft = temp;\n\t}\n\tleft = (left ^ fFunction(right, keySchedule[30], keySchedule[31])) >>> 0;\n\n\tlet outLeft = 0;\n\tlet outRight = 0;\n\tfor (let i = 0; i < 4; i++) {\n\t\t// 分别计算左侧 32 位和右侧 32 位在 INV_IP 阶段的表现\n\t\tconst idxL = (i << 8) | ((left >>> (24 - i * 8)) & 0xff);\n\t\toutLeft |= INV_IP_LEFT_TABLE[idxL];\n\t\toutRight |= INV_IP_RIGHT_TABLE[idxL];\n\n\t\tconst idxR = ((i + 4) << 8) | ((right >>> (24 - i * 8)) & 0xff);\n\t\toutLeft |= INV_IP_LEFT_TABLE[idxR];\n\t\toutRight |= INV_IP_RIGHT_TABLE[idxR];\n\t}\n\n\t// 使用按位移位进行输出数组写入\n\toutput[0] = (outLeft >>> 24) & 0xff;\n\toutput[1] = (outLeft >>> 16) & 0xff;\n\toutput[2] = (outLeft >>> 8) & 0xff;\n\toutput[3] = outLeft & 0xff;\n\toutput[4] = (outRight >>> 24) & 0xff;\n\toutput[5] = (outRight >>> 16) & 0xff;\n\toutput[6] = (outRight >>> 8) & 0xff;\n\toutput[7] = outRight & 0xff;\n}\n","/// <reference types=\"node\" />\n/**\n * @module utils\n * @description\n *\n * 包含一些工具函数。\n */\n\n/**\n * 将十六进制字符串转换为 Uint8Array。\n */\nexport function hexToUint8Array(hex: string): Uint8Array {\n\tif (typeof Buffer !== \"undefined\") {\n\t\treturn Buffer.from(hex, \"hex\");\n\t}\n\n\tif (hex.length % 2 !== 0) {\n\t\tthrow new Error(\"无效的十六进制字符串: 长度必须是偶数\");\n\t}\n\n\tconst bytes = new Uint8Array(hex.length / 2);\n\tfor (let i = 0; i < hex.length; i += 2) {\n\t\tbytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);\n\t}\n\treturn bytes;\n}\n\n/**\n * 将 Uint8Array 转换为十六进制字符串。\n */\nexport function uint8ArrayToHex(bytes: Uint8Array): string {\n\tif (typeof Buffer !== \"undefined\") {\n\t\treturn Buffer.from(bytes).toString(\"hex\");\n\t}\n\n\treturn Array.from(bytes)\n\t\t.map((b) => b.toString(16).padStart(2, \"0\"))\n\t\t.join(\"\");\n}\n","/**\n * @module qrc-codec\n * @description\n * 此模块是加密与解密 QRC 歌词的核心。\n * 提供了两个主要的公共函数:`decryptQrc` 和 `encryptQrc`。\n *\n * 非标准 3DES 算法实现由 `custom_des` 模块提供。\n *\n * 迁移自 https://github.com/apoint123/qrc-decoder\n */\n\nimport { deflate, inflate } from \"pako\";\nimport { KEY_1, KEY_2, KEY_3 } from \"./constants\";\nimport { desCrypt, type KeySchedule, keySchedule, Mode } from \"./custom-des\";\nimport { hexToUint8Array, uint8ArrayToHex } from \"./utils\";\n\nconst DES_BLOCK_SIZE = 8;\n\n/**\n * 非标准 3DES 编解码器\n */\nclass QqMusicCodec {\n\tprivate readonly encryptSchedule: KeySchedule[];\n\tprivate readonly decryptSchedule: KeySchedule[];\n\n\tconstructor() {\n\t\t// 解密流程 D(K3) -> E(K2) -> D(K1)\n\t\tthis.decryptSchedule = [\n\t\t\tkeySchedule(KEY_3, Mode.Decrypt),\n\t\t\tkeySchedule(KEY_2, Mode.Encrypt),\n\t\t\tkeySchedule(KEY_1, Mode.Decrypt),\n\t\t];\n\n\t\t// 加密流程 E(K1) -> D(K2) -> E(K3)\n\t\tthis.encryptSchedule = [\n\t\t\tkeySchedule(KEY_1, Mode.Encrypt),\n\t\t\tkeySchedule(KEY_2, Mode.Decrypt),\n\t\t\tkeySchedule(KEY_3, Mode.Encrypt),\n\t\t];\n\t}\n\n\t/**\n\t * 解密一个8字节的数据块。\n\t */\n\tpublic decryptBlock(input: Uint8Array, output: Uint8Array): void {\n\t\tconst temp1 = new Uint8Array(8);\n\t\tconst temp2 = new Uint8Array(8);\n\t\tdesCrypt(input, temp1, this.decryptSchedule[0]);\n\t\tdesCrypt(temp1, temp2, this.decryptSchedule[1]);\n\t\tdesCrypt(temp2, output, this.decryptSchedule[2]);\n\t}\n\n\t/**\n\t * 加密一个8字节的数据块。\n\t */\n\tpublic encryptBlock(input: Uint8Array, output: Uint8Array): void {\n\t\tconst temp1 = new Uint8Array(8);\n\t\tconst temp2 = new Uint8Array(8);\n\t\tdesCrypt(input, temp1, this.encryptSchedule[0]);\n\t\tdesCrypt(temp1, temp2, this.encryptSchedule[1]);\n\t\tdesCrypt(temp2, output, this.encryptSchedule[2]);\n\t}\n}\n\nconst CODEC = new QqMusicCodec();\n\n/**\n * 使用零字节对数据进行填充。\n *\n * QQ音乐使用的填充方案是零填充。\n * @param data 需要填充的字节数据\n * @param blockSize 块大小,对于DES来说是8\n */\nfunction zeroPad(data: Uint8Array, blockSize: number): Uint8Array {\n\tconst paddingLen = (blockSize - (data.length % blockSize)) % blockSize;\n\tif (paddingLen === 0) {\n\t\treturn data;\n\t}\n\n\tconst paddedData = new Uint8Array(data.length + paddingLen);\n\tpaddedData.set(data, 0);\n\treturn paddedData;\n}\n\n/**\n * 使用 Zlib 解压缩字节数据。\n * 同时会尝试移除头部的 UTF-8 BOM (0xEF 0xBB 0xBF)。\n */\nfunction decompress(data: Uint8Array): Uint8Array {\n\tconst decompressed = inflate(data);\n\tif (\n\t\tdecompressed.length >= 3 &&\n\t\tdecompressed[0] === 0xef &&\n\t\tdecompressed[1] === 0xbb &&\n\t\tdecompressed[2] === 0xbf\n\t) {\n\t\treturn decompressed.slice(3);\n\t}\n\treturn decompressed;\n}\n\n/**\n * 解密十六进制字符串格式的 Qrc 歌词数据\n * 解密后可去头尾 XML 数据后通过调用 `parseQrc` 解析歌词行\n * @param encryptedHexString 十六进制格式的字符串,代表被加密的歌词数据\n * @returns 被解密出来的歌词字符串,是前后有 XML 混合的 QRC 歌词\n */\nexport function decryptQrcHex(encryptedHexString: string): string {\n\tconst encryptedBytes = hexToUint8Array(encryptedHexString);\n\n\tif (encryptedBytes.length % DES_BLOCK_SIZE !== 0) {\n\t\tthrow new Error(`加密数据长度不是${DES_BLOCK_SIZE}的倍数`);\n\t}\n\n\tconst decryptedData = new Uint8Array(encryptedBytes.length);\n\n\tfor (let i = 0; i < encryptedBytes.length; i += DES_BLOCK_SIZE) {\n\t\tconst chunk = encryptedBytes.subarray(i, i + DES_BLOCK_SIZE);\n\t\tconst outChunk = decryptedData.subarray(i, i + DES_BLOCK_SIZE);\n\t\tCODEC.decryptBlock(chunk, outChunk);\n\t}\n\n\tconst decompressedBytes = decompress(decryptedData);\n\n\treturn new TextDecoder(\"utf-8\").decode(decompressedBytes);\n}\n\n/**\n * 对明文执行加密操作。\n * @param plaintext 明文字符串\n * @returns 十六进制格式的字符串,代表被加密的歌词数据\n */\nexport function encryptQrcHex(plaintext: string): string {\n\tconst textBytes = new TextEncoder().encode(plaintext);\n\n\tconst compressedData = deflate(textBytes);\n\n\tconst paddedData = zeroPad(compressedData, DES_BLOCK_SIZE);\n\n\tconst encryptedData = new Uint8Array(paddedData.length);\n\n\tfor (let i = 0; i < paddedData.length; i += DES_BLOCK_SIZE) {\n\t\tconst chunk = paddedData.subarray(i, i + DES_BLOCK_SIZE);\n\t\tconst outChunk = encryptedData.subarray(i, i + DES_BLOCK_SIZE);\n\t\tCODEC.encryptBlock(chunk, outChunk);\n\t}\n\n\treturn uint8ArrayToHex(encryptedData);\n}\n","/**\n * @fileoverview Lyricify Syllable(LYS)格式解析与生成。\n * 支持词级时间戳、背景人声与对唱属性。每行以属性位 `[prop]` 开头,后续为 `文本(start,duration)` 序列。\n *\n * 属性位说明:\n * 0: 未设置\n * 1: 左对齐\n * 2: 右对齐(对唱)\n * 3: 非背景,未设置对齐\n * 4: 非背景,左对齐\n * 5: 非背景,右对齐(对唱)\n * 6: 背景,未设置对齐\n * 7: 背景,左对齐\n * 8: 背景,右对齐(对唱)\n *\n * 格式示例:\n * [0]Lately (358,1336)I've (1694,487)been, (2181,673)I've (2854,268)been (3122,280)losing (3402,345)sleep(3747,1186)\n * [0]Dreaming (5245,696)about (5941,471)the (6412,306)things (6718,458)that (7176,292)we (7468,511)could (7979,393)be(8372,737)\n */\nimport type { LyricLine, LyricWord } from \"../types\";\nimport {\n\tcreateLine,\n\tcreateWord,\n\tnormalizeDuration,\n\tnormalizeTimestamp,\n} from \"../utils\";\n\n/**\n * 解析 LYS 格式中的属性值\n * @param prop 属性值\n * @returns 对唱与背景标志位\n */\nfunction parseProp(prop: number): {\n\tisDuet: boolean | undefined;\n\tisBG: boolean | undefined;\n} {\n\tif (prop < 0 || prop > 8) prop = 0;\n\treturn {\n\t\tisDuet: prop % 3 === 0 ? undefined : prop % 3 === 2,\n\t\tisBG: prop <= 2 ? undefined : prop >= 6,\n\t};\n}\n\n/**\n * 解析 LYS 格式的歌词字符串\n * @param lys 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseLys(lys: string): LyricLine[] {\n\tconst lines = lys\n\t\t.split(/\\r?\\n/)\n\t\t.map((l) => l.trim())\n\t\t.filter((l) => l.length > 0);\n\tconst lyricLines: LyricLine[] = [];\n\tconst propRegex = /^\\[(\\d+)\\]/;\n\tconst wordRegex = /(.*?)\\((\\d+),(\\d+)\\)/g;\n\n\tfor (const lineStr of lines) {\n\t\tconst propMatch = lineStr.match(propRegex);\n\t\tif (!propMatch) continue;\n\n\t\tconst [, propStr] = propMatch;\n\t\tconst content = lineStr.slice(propMatch[0].length);\n\t\tconst words: LyricWord[] = [];\n\t\tconst props = parseProp(Number(propStr));\n\n\t\tfor (const match of content.matchAll(wordRegex)) {\n\t\t\tconst [, rawWord, startStr, durStr] = match;\n\t\t\tconst startTime = Number(startStr);\n\t\t\tconst duration = Number(durStr);\n\t\t\tconst endTime = startTime + duration;\n\t\t\tconst wordText = rawWord;\n\t\t\twords.push(createWord({ word: wordText, startTime, endTime }));\n\t\t}\n\n\t\tconst lineStartTime = words[0]?.startTime ?? 0;\n\t\tconst lineEndTime = words[words.length - 1]?.endTime ?? 0;\n\t\tif (!words.length) continue;\n\n\t\tif (props.isBG === undefined)\n\t\t\tprops.isBG =\n\t\t\t\twords.length > 0 &&\n\t\t\t\t/^[((]/.test(words[0].word) &&\n\t\t\t\t/[))]$/.test(words[words.length - 1].word);\n\n\t\tif (props.isBG && words.length) {\n\t\t\twords[0].word = words[0].word.replace(/^[((]/, \"\");\n\t\t\twords[words.length - 1].word = words[words.length - 1].word.replace(\n\t\t\t\t/[))]$/,\n\t\t\t\t\"\",\n\t\t\t);\n\t\t}\n\n\t\tlyricLines.push(\n\t\t\tcreateLine({\n\t\t\t\tstartTime: lineStartTime,\n\t\t\t\tendTime: lineEndTime,\n\t\t\t\tisDuet: !!props.isDuet,\n\t\t\t\tisBG: props.isBG,\n\t\t\t\twords,\n\t\t\t}),\n\t\t);\n\t}\n\treturn lyricLines;\n}\n\nfunction makeProp(line: LyricLine): number {\n\tlet prop = 0;\n\tprop += line.isDuet ? 2 : 1;\n\tprop += line.isBG ? 6 : 3;\n\treturn prop;\n}\n\n/**\n * 将歌词数组转换为 LYS 格式的字符串\n * @param lines 歌词数组\n * @returns LYS 格式的字符串\n */\nexport function stringifyLys(lines: LyricLine[]): string {\n\treturn lines\n\t\t.map((line) => {\n\t\t\tconst prop = makeProp(line);\n\t\t\tconst printWords: {\n\t\t\t\tstartTime: number;\n\t\t\t\tduration: number;\n\t\t\t\tword: string;\n\t\t\t}[] = [];\n\t\t\tline.words.forEach((w) => {\n\t\t\t\tif (w.word.trim() || !printWords.length)\n\t\t\t\t\tprintWords.push({\n\t\t\t\t\t\tword: w.word,\n\t\t\t\t\t\tstartTime: normalizeTimestamp(w.startTime),\n\t\t\t\t\t\tduration: normalizeDuration(\n\t\t\t\t\t\t\tnormalizeTimestamp(w.endTime) - normalizeTimestamp(w.startTime),\n\t\t\t\t\t\t),\n\t\t\t\t\t});\n\t\t\t\telse printWords[printWords.length - 1].word += w.word;\n\t\t\t});\n\t\t\tconst wordsStr = printWords\n\t\t\t\t.map((w) => `${w.word}(${w.startTime},${w.duration})`)\n\t\t\t\t.join(\"\");\n\t\t\treturn `[${prop}]${wordsStr}`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n","/**\n * @fileoverview Lyricify Quick Export(LQE)格式解析与生成。\n * 该格式本质是组合格式:`lyrics` 部分使用 LYS;`translation`/`pronunciation` 部分使用 LRC。\n *\n * 格式示例:\n * [Lyricify Quick Export]\n * [version:1.0]\n *\n * [lyrics: format@Lyricify Syllable]\n * [4]A(365,350)ni(715,307)ro(1022,312)dham (1334,419)a(3203,337)nut(3540,350)pā(3890,306)dam(4196,382)\n *\n * [translation: format@LRC]\n * [00:00.365]不生亦不灭\n *\n * [pronunciation: format@LRC, language@romaji]\n * [00:00.365]阿难罗昙 阿耨钵昙\n */\nimport type { LyricLine } from \"../types\";\nimport { formatTime, parseTime } from \"../utils\";\nimport { parseLys, stringifyLys } from \"./lys\";\n\ntype AttrType = \"translatedLyric\" | \"romanLyric\";\n\ninterface HeaderMatch {\n\tindex: number;\n\ttype: \"lyric\" | \"translation\" | \"romanization\" | \"unknown\";\n}\n\nfunction parseAttr(\n\tattr: AttrType,\n\theaderMatches: HeaderMatch[],\n\trawLines: string[],\n\tlines: LyricLine[],\n): void {\n\tconst headerIndex = headerMatches.findIndex((item) => {\n\t\tif (attr === \"translatedLyric\") return item.type === \"translation\";\n\t\treturn item.type === \"romanization\";\n\t});\n\tif (headerIndex === -1) return;\n\n\tconst timeRegex = /^\\[((?:\\d+:)*\\d+(?:\\.\\d+)?)\\](.*)$/;\n\tconst attrLines = rawLines\n\t\t.slice(\n\t\t\theaderMatches[headerIndex].index + 1,\n\t\t\theaderMatches[headerIndex + 1].index,\n\t\t)\n\t\t.map((line) => line.trim())\n\t\t.filter((line) => line.length > 0)\n\t\t.map((line) => {\n\t\t\tconst match = line.match(timeRegex);\n\t\t\tif (!match) return null;\n\t\t\tconst [, timeStr, text] = match;\n\t\t\tconst time = parseTime(timeStr);\n\t\t\tif (Number.isNaN(time)) return null;\n\t\t\treturn { time, text };\n\t\t})\n\t\t.filter((item): item is { time: number; text: string } => item !== null);\n\n\tlet attrLineIndex = 0;\n\tfor (const line of lines) {\n\t\tif (attrLines[attrLineIndex]?.time !== line.startTime) continue;\n\t\tline[attr] = attrLines[attrLineIndex].text;\n\t\tattrLineIndex++;\n\t}\n}\n\n/**\n * 解析 LQE 格式的歌词字符串\n * @param lqe 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseLqe(lqe: string): LyricLine[] {\n\tconst lines = lqe\n\t\t.split(/\\r?\\n/)\n\t\t.map((line) => line.trim())\n\t\t.filter((line) => line.length > 0);\n\n\tconst headerRegex = /^\\[([a-zA-Z]+):.+\\]$/;\n\tconst headerMatches: HeaderMatch[] = [];\n\tlines.forEach((line, index) => {\n\t\tconst match = line.match(headerRegex);\n\t\tif (!match) return;\n\t\tconst [, type] = match;\n\t\tif (type === \"lyrics\") headerMatches.push({ index, type: \"lyric\" });\n\t\telse if (type === \"translation\")\n\t\t\theaderMatches.push({ index, type: \"translation\" });\n\t\telse if (type === \"pronunciation\")\n\t\t\theaderMatches.push({ index, type: \"romanization\" });\n\t\telse headerMatches.push({ index, type: \"unknown\" });\n\t});\n\theaderMatches.push({ index: lines.length, type: \"unknown\" });\n\n\tconst lyricHeaderIndex = headerMatches.findIndex(\n\t\t(item) => item.type === \"lyric\",\n\t);\n\tif (lyricHeaderIndex === -1) return [];\n\n\tconst lyricLines = lines.slice(\n\t\theaderMatches[lyricHeaderIndex].index + 1,\n\t\theaderMatches[lyricHeaderIndex + 1].index,\n\t);\n\tconst parsedLines = parseLys(lyricLines.join(\"\\n\"));\n\n\tparseAttr(\"translatedLyric\", headerMatches, lines, parsedLines);\n\tparseAttr(\"romanLyric\", headerMatches, lines, parsedLines);\n\n\treturn parsedLines;\n}\n\nfunction stringifyAttr(lines: LyricLine[], attr: AttrType): string | null {\n\tconst header =\n\t\tattr === \"translatedLyric\"\n\t\t\t? \"[translation: format@LRC]\"\n\t\t\t: \"[pronunciation: format@LRC, language@romaji]\";\n\tconst contentLines = lines\n\t\t.map((line) => {\n\t\t\tconst value = line[attr];\n\t\t\tif (!value) return null;\n\t\t\treturn `[${formatTime(line.startTime)}]${value}`;\n\t\t})\n\t\t.filter((line): line is string => line !== null);\n\tif (contentLines.length === 0) return null;\n\treturn [header, ...contentLines].join(\"\\n\");\n}\n\n/**\n * 将歌词数组转换为 LQE 格式的字符串\n * @param lines 歌词数组\n * @returns LQE 格式的字符串\n */\nexport function stringifyLqe(lines: LyricLine[]): string {\n\tconst header = \"[Lyricify Quick Export]\\n[version:1.0]\";\n\tconst lyricSection = `[lyrics: format@Lyricify Syllable]\\n${stringifyLys(lines)}`;\n\tconst translationSection = stringifyAttr(lines, \"translatedLyric\");\n\tconst romanizationSection = stringifyAttr(lines, \"romanLyric\");\n\tconst body = [lyricSection, translationSection, romanizationSection]\n\t\t.filter((section): section is string => section !== null)\n\t\t.join(\"\\n\\n\\n\");\n\treturn [header, body].join(\"\\n\\n\");\n}\n","import type { LyricLine, LyricWord } from \"../../types\";\nimport { normalizeTimestamp } from \"../../utils\";\n\n/**\n * 复制一行歌词并归一化其中所有的时间\n * @param line 一行歌词\n * @returns 归一化后的副本\n */\nexport function normalizeLine(line: LyricLine): LyricLine {\n\treturn {\n\t\t...line,\n\t\tstartTime: normalizeTimestamp(line.startTime),\n\t\tendTime: normalizeTimestamp(line.endTime),\n\t\twords: line.words.map((word) => ({\n\t\t\t...word,\n\t\t\tstartTime: normalizeTimestamp(word.startTime),\n\t\t\tendTime: normalizeTimestamp(word.endTime),\n\t\t})),\n\t};\n}\n\n/**\n * 将一组音节拼接为完整文本\n * @param words 音节数组\n * @returns 拼接后的文本\n */\nexport function joinWords(words: LyricWord[]): string {\n\treturn words.map((word) => word.word).join(\"\");\n}\n\n/**\n * 判断一行歌词是否有文本内容\n * @param line 一行歌词\n * @returns 是否有文本内容\n */\nexport function hasText(line: LyricLine): boolean {\n\treturn joinWords(line.words).trim() !== \"\";\n}\n\n/**\n * 判断一组音节是否为逐字歌词\n *\n * 逐行歌词只有一个音节,且该音节与歌词同时开始,\n * 因此可以直接由音节推导出来,无需额外的标记\n * @param words 音节数组\n * @param startTime 歌词行的开始时间\n * @returns 是否为逐字歌词\n */\nexport function isWordSyncLyric(\n\twords: LyricWord[],\n\tstartTime: number,\n): boolean {\n\tif (words.length === 0) return false;\n\tif (words.length > 1) return true;\n\treturn words[0].startTime !== startTime;\n}\n\nconst BG_PAREN_BEGIN = /^[((]/;\nconst BG_PAREN_END = /[))]$/;\n\n/**\n * 判断一段歌词文本是否为背景人声\n *\n * 只有整段文本都被圆括号包裹时才算数,半角与全角括号都接受。\n * 括号内没有内容的不算,避免把 `()` 这样的写法当作背景人声\n * @param text 一段歌词文本\n * @returns 是否为背景人声\n */\nexport function isBackgroundVocalText(text: string): boolean {\n\treturn (\n\t\ttext.length > 2 && BG_PAREN_BEGIN.test(text) && BG_PAREN_END.test(text)\n\t);\n}\n\n/**\n * 去掉背景人声最外层的圆括号\n * @param words 音节数组,会被就地修改\n */\nexport function trimBackgroundVocalParentheses(words: LyricWord[]): void {\n\tif (words.length === 0) return;\n\twords[0].word = words[0].word.slice(1);\n\tconst lastWord = words[words.length - 1];\n\tlastWord.word = lastWord.word.slice(0, -1);\n}\n","import type { LrcMetadata } from \"./types\";\n\nconst LRC_METADATA_REGEX = /^\\[\\s*(?<key>[a-zA-Z]+)\\s*:\\s*(?<value>.*?)\\s*\\]$/;\n\n/**\n * 解析一行 LRC 元数据,如 `[ti:标题]`\n * @param line 已去除首尾空白的单行文本\n * @returns 元数据键值对,若不是元数据行则为 `null`\n */\nexport function parseLrcMetadataLine(line: string): LrcMetadata | null {\n\tconst match = line.match(LRC_METADATA_REGEX);\n\tif (!match?.groups) return null;\n\n\tconst key = match.groups.key.toLowerCase();\n\tconst value = match.groups.value.trim();\n\tif (!value) return null;\n\n\treturn [[key, [value]]];\n}\n\n/**\n * 将元数据合并进目标元数据表\n *\n * 同名键的取值会按顺序合并并去重\n * @param target 目标元数据表,会被就地修改\n * @param source 待合并的元数据表\n */\nexport function mergeMetadata(target: LrcMetadata, source: LrcMetadata): void {\n\tfor (const [key, values] of source) {\n\t\tconst existing = target.find(([targetKey]) => targetKey === key);\n\t\tif (!existing) {\n\t\t\ttarget.push([key, [...values]]);\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const value of values) {\n\t\t\tif (!existing[1].includes(value)) existing[1].push(value);\n\t\t}\n\t}\n}\n\n/**\n * 将元数据表生成为 LRC 元数据行\n * @param metadata 元数据表\n * @returns 元数据行数组,没有可输出的元数据时为空数组\n */\nexport function generateLrcMetadataLines(metadata: LrcMetadata): string[] {\n\tconst lines: string[] = [];\n\tfor (const [key, values] of metadata) {\n\t\tconst printableValues = values.filter((value) => value.trim() !== \"\");\n\t\tif (!key.trim() || printableValues.length === 0) continue;\n\t\tlines.push(`[${key}:${printableValues.join(\"/\")}]`);\n\t}\n\treturn lines;\n}\n","/**\n * @fileoverview LRC 家族用到的内部类型,以及各歌词模式的行为表\n */\n\n/**\n * 元数据表,以 `[键, 值数组]` 的形式存储,键为 LRC 的原始标签名\n */\nexport type LrcMetadata = [string, string[]][];\n\n/**\n * 歌词模式\n * - `\"plain\"`: 普通 LRC,不含逐字信息\n * - `\"enhanced\"`: 增强型 LRC\n * - `\"spl\"`: Salt Player Lyrics,为前两者的超集\n */\nexport type LrcMode = \"plain\" | \"enhanced\" | \"spl\";\n\n/**\n * 一种歌词模式在解析与生成时的行为\n */\nexport interface LrcModeFeatures {\n\t/**\n\t * 是否保留并输出逐字时间戳\n\t *\n\t * 关闭时解析会把逐字信息并成覆盖整行的单个音节,生成也不写出行内时间戳。\n\t * 输出逐字时间戳的模式自带行末时间戳,因此也不需要另起一行输出结束时间\n\t */\n\twordLevel: boolean;\n\t/**\n\t * 是否允许把辅助行内联进主歌词行\n\t *\n\t * 只有不写出行内时间戳的模式才有空间容纳圆括号包裹的辅助文本\n\t */\n\tinlineAuxiliary: boolean;\n}\n\n/**\n * 各歌词模式的行为,由解析器与生成器共用\n */\nexport const LRC_MODE_FEATURES: Record<LrcMode, LrcModeFeatures> = {\n\tplain: { wordLevel: false, inlineAuxiliary: true },\n\tenhanced: { wordLevel: true, inlineAuxiliary: false },\n\tspl: { wordLevel: true, inlineAuxiliary: false },\n};\n","import type { LyricLine, LyricParseResult } from \"../../types\";\nimport { clampTimestamp, type DeepRequired, formatTime } from \"../../utils\";\nimport { hasText, isWordSyncLyric, joinWords, normalizeLine } from \"./helpers\";\nimport { generateLrcMetadataLines } from \"./metadata\";\nimport { LRC_MODE_FEATURES, type LrcMode, type LrcModeFeatures } from \"./types\";\n\n/**\n * 普通 LRC 显式结束时间戳的输出配置\n *\n * 逐字歌词的结束时间戳由最后一个音节携带,不受此配置影响\n */\nexport interface LrcEndTimestampOptions {\n\t/**\n\t * 输出策略\n\t * - `\"none\"`: 不输出\n\t * - `\"always\"`: 总是输出\n\t * - `\"interval\"`: 与下一行的间隔不小于 `intervalGap` 时输出\n\t * @default \"none\"\n\t */\n\tmode?: \"none\" | \"always\" | \"interval\";\n\t/**\n\t * 触发间隔,单位毫秒,仅在 `mode` 为 `\"interval\"` 时有效\n\t * @default 5000\n\t */\n\tintervalGap?: number;\n}\n\n/**\n * 单种辅助行(翻译、音译或背景人声)的输出配置\n */\nexport interface LrcAuxiliaryLineOptions {\n\t/**\n\t * 是否输出该辅助行\n\t * @default true\n\t */\n\tenabled?: boolean;\n\t/**\n\t * 是否内联到主歌词行,仅在普通 LRC 模式下有效\n\t *\n\t * translation、romanization 与 backgroundVocal 中最多只有一个可以内联\n\t *\n\t * 内联时辅助文本会以半角圆括号 `(text)` 包裹\n\t */\n\tinline?: boolean;\n}\n\n/**\n * 辅助行的输出配置\n */\nexport interface LrcAuxiliaryLinesOptions {\n\t/**\n\t * 辅助行的输出顺序\n\t * @default \"translation-first\"\n\t */\n\torder?: \"translation-first\" | \"romanization-first\";\n\t/**\n\t * 翻译行设置\n\t */\n\ttranslation?: LrcAuxiliaryLineOptions;\n\t/**\n\t * 音译行设置\n\t */\n\tromanization?: LrcAuxiliaryLineOptions;\n\t/**\n\t * 背景人声设置\n\t */\n\tbackgroundVocal?: LrcAuxiliaryLineOptions;\n}\n\n/**\n * 生成 LRC 家族歌词的配置\n */\nexport interface StringifyLrcLikeOptions {\n\t/**\n\t * 生成模式,详见 {@link LrcMode}\n\t * @default \"plain\"\n\t */\n\tmode?: LrcMode;\n\n\t/**\n\t * 逐字时间戳的括号类型,仅在 `enhanced` 和 `spl` 模式下有效\n\t * - `\"angle\"`: 使用 `<mm:ss.ms>`\n\t * - `\"square\"`: 使用 `[mm:ss.ms]`\n\t * @default \"angle\"\n\t */\n\tinlineBracket?: \"angle\" | \"square\";\n\n\t/**\n\t * 辅助行(翻译、音译、背景人声)的输出配置\n\t */\n\tauxiliaryLines?: LrcAuxiliaryLinesOptions;\n\n\t/**\n\t * 普通 LRC 的显式结束时间戳输出配置\n\t */\n\tendTimestamp?: LrcEndTimestampOptions;\n}\n\n/**\n * 展开单种辅助行的默认配置\n */\nfunction resolveAuxiliaryLineOptions(\n\toptions: LrcAuxiliaryLineOptions | undefined,\n): DeepRequired<LrcAuxiliaryLineOptions> {\n\treturn {\n\t\tenabled: options?.enabled ?? true,\n\t\tinline: options?.inline ?? false,\n\t};\n}\n\nexport class LrcGenerator {\n\tprivate options: DeepRequired<StringifyLrcLikeOptions>;\n\tprivate features: LrcModeFeatures;\n\n\tconstructor(options?: StringifyLrcLikeOptions) {\n\t\tthis.options = {\n\t\t\tmode: options?.mode ?? \"plain\",\n\t\t\tinlineBracket: options?.inlineBracket ?? \"angle\",\n\t\t\tauxiliaryLines: {\n\t\t\t\torder: options?.auxiliaryLines?.order ?? \"translation-first\",\n\t\t\t\ttranslation: resolveAuxiliaryLineOptions(\n\t\t\t\t\toptions?.auxiliaryLines?.translation,\n\t\t\t\t),\n\t\t\t\tromanization: resolveAuxiliaryLineOptions(\n\t\t\t\t\toptions?.auxiliaryLines?.romanization,\n\t\t\t\t),\n\t\t\t\tbackgroundVocal: resolveAuxiliaryLineOptions(\n\t\t\t\t\toptions?.auxiliaryLines?.backgroundVocal,\n\t\t\t\t),\n\t\t\t},\n\t\t\tendTimestamp: {\n\t\t\t\tmode: options?.endTimestamp?.mode ?? \"none\",\n\t\t\t\tintervalGap: options?.endTimestamp?.intervalGap ?? 5000,\n\t\t\t},\n\t\t};\n\t\tthis.features = LRC_MODE_FEATURES[this.options.mode];\n\t}\n\n\t/**\n\t * 行首时间戳是否改用首个音节的开始时间\n\t *\n\t * 生成方括号时间戳时,按常见实现省略行首时间戳,只在行首写入首个音节的开始时间,\n\t * 生成尖括号时则写入行时间戳\n\t */\n\tprivate get usesFirstWordStartTime(): boolean {\n\t\treturn this.options.inlineBracket === \"square\";\n\t}\n\n\t/**\n\t * 生成 LRC 家族歌词\n\t * @param input 歌词行,或带元数据的解析结果\n\t * @returns 歌词文本\n\t */\n\tpublic generate(input: LyricParseResult | LyricLine[]): string {\n\t\tconst metadata = Array.isArray(input) ? [] : input.metadata;\n\t\tconst sourceLines = Array.isArray(input) ? input : input.lines;\n\n\t\tconst outputLines: string[] = [];\n\n\t\tconst metaLines = generateLrcMetadataLines(metadata);\n\t\tif (metaLines.length > 0) {\n\t\t\toutputLines.push(...metaLines);\n\t\t}\n\n\t\t// 归一化时间,并略去没有文本的歌词行\n\t\tconst lines = sourceLines.map(normalizeLine).filter(hasText);\n\t\t// 有宿主的背景人声行随主歌词行一起渲染,剩下的仍以括号包裹的独立歌词行写出,\n\t\t// 否则解析出来的背景人声行写回去就丢了标记\n\t\tconst backgroundVocals = new Set<LyricLine>();\n\t\tfor (const [index, line] of lines.entries()) {\n\t\t\tif (line.isBG) continue;\n\t\t\tconst nextLine = lines[index + 1];\n\t\t\tconst backgroundVocal = nextLine?.isBG ? nextLine : undefined;\n\t\t\tif (backgroundVocal) backgroundVocals.add(backgroundVocal);\n\t\t}\n\n\t\tfor (const [index, line] of lines.entries()) {\n\t\t\tif (backgroundVocals.has(line)) continue;\n\t\t\tconst nextLine = lines[index + 1];\n\t\t\tconst backgroundVocal =\n\t\t\t\t!line.isBG && nextLine?.isBG ? nextLine : undefined;\n\t\t\tlet nextMainLine: LyricLine | undefined;\n\t\t\tfor (let nextIndex = index + 1; nextIndex < lines.length; nextIndex++) {\n\t\t\t\tif (!lines[nextIndex].isBG) {\n\t\t\t\t\tnextMainLine = lines[nextIndex];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.processSingleLine(line, backgroundVocal, nextMainLine, outputLines);\n\t\t}\n\n\t\treturn outputLines.join(\"\\n\");\n\t}\n\n\tprivate processSingleLine(\n\t\tline: LyricLine,\n\t\tbackgroundVocal: LyricLine | undefined,\n\t\tnextLine: LyricLine | undefined,\n\t\toutputLines: string[],\n\t): void {\n\t\tconst { auxiliaryLines: auxConfig } = this.options;\n\t\tconst { inlineAuxiliary } = this.features;\n\n\t\t// 内联仅在能容纳圆括号的模式下有效;三者中最多只有一个可以内联\n\t\tconst transInline = inlineAuxiliary && auxConfig.translation.inline;\n\t\tconst romaInline =\n\t\t\tinlineAuxiliary && !transInline && auxConfig.romanization.inline;\n\t\tconst bgvInline =\n\t\t\tinlineAuxiliary &&\n\t\t\t!transInline &&\n\t\t\t!romaInline &&\n\t\t\tauxConfig.backgroundVocal.inline;\n\n\t\tconst lineTimeTag = this.formatTimeTag(line.startTime, \"square\");\n\n\t\tlet transText = auxConfig.translation.enabled ? line.translatedLyric : \"\";\n\t\tlet romaText = auxConfig.romanization.enabled ? line.romanLyric : \"\";\n\t\tlet bgLine = auxConfig.backgroundVocal.enabled\n\t\t\t? backgroundVocal\n\t\t\t: undefined;\n\n\t\tlet mainLineText = joinWords(line.words);\n\n\t\t// 能容纳圆括号的模式可以内联翻译、音译和背景人声\n\t\tif (inlineAuxiliary) {\n\t\t\tconst applyInline = (text: string) => {\n\t\t\t\tmainLineText += `${mainLineText ? \" \" : \"\"}(${text})`;\n\t\t\t};\n\n\t\t\tif (transInline && transText) {\n\t\t\t\tapplyInline(transText);\n\t\t\t\ttransText = \"\";\n\t\t\t} else if (romaInline && romaText) {\n\t\t\t\tapplyInline(romaText);\n\t\t\t\tromaText = \"\";\n\t\t\t} else if (bgvInline && bgLine) {\n\t\t\t\t// 内联背景人声到主歌词里\n\t\t\t\tmainLineText += `${mainLineText ? \" \" : \"\"}(${joinWords(bgLine.words)})`;\n\n\t\t\t\t// 背景人声自带的翻译与音译同样使用括号内联到主歌词的翻译与音译里\n\t\t\t\tif (auxConfig.translation.enabled && bgLine.translatedLyric) {\n\t\t\t\t\ttransText = transText\n\t\t\t\t\t\t? `${transText} (${bgLine.translatedLyric})`\n\t\t\t\t\t\t: `(${bgLine.translatedLyric})`;\n\t\t\t\t}\n\t\t\t\tif (auxConfig.romanization.enabled && bgLine.romanLyric) {\n\t\t\t\t\tromaText = romaText\n\t\t\t\t\t\t? `${romaText} (${bgLine.romanLyric})`\n\t\t\t\t\t\t: `(${bgLine.romanLyric})`;\n\t\t\t\t}\n\n\t\t\t\tbgLine = undefined;\n\t\t\t}\n\t\t}\n\n\t\toutputLines.push(this.renderBaseItem(line, mainLineText, line.isBG));\n\n\t\tif (bgLine) {\n\t\t\toutputLines.push(\n\t\t\t\tthis.renderBaseItem(bgLine, joinWords(bgLine.words), true),\n\t\t\t);\n\t\t}\n\n\t\tconst auxTexts =\n\t\t\tauxConfig.order === \"translation-first\"\n\t\t\t\t? [transText, romaText]\n\t\t\t\t: [romaText, transText];\n\n\t\tfor (const auxText of auxTexts) {\n\t\t\tif (auxText) outputLines.push(`${lineTimeTag}${auxText}`);\n\t\t}\n\n\t\tthis.processEndTimestamp(line, nextLine, outputLines);\n\t}\n\n\t/**\n\t * 渲染一行歌词,`lineText` 是已经处理过内联的整行文本\n\t */\n\tprivate renderBaseItem(\n\t\titem: LyricLine,\n\t\tlineText: string,\n\t\tisBgv: boolean,\n\t): string {\n\t\tconst { inlineBracket } = this.options;\n\t\tconst { wordLevel } = this.features;\n\n\t\tif (wordLevel && isWordSyncLyric(item.words, item.startTime)) {\n\t\t\t// 逐字歌词\n\t\t\tconst words = item.words;\n\t\t\t// 方括号写法不写行时间戳,行首时间戳直接取首个音节的开始时间\n\t\t\tconst leadingTimestamp = this.usesFirstWordStartTime\n\t\t\t\t? words[0].startTime\n\t\t\t\t: item.startTime;\n\t\t\tlet output = this.formatTimeTag(leadingTimestamp, \"square\");\n\n\t\t\tfor (let i = 0; i < words.length; i++) {\n\t\t\t\tconst word = words[i];\n\t\t\t\t// 方括号写法的行首时间戳已经就是首个音节的开始时间,不重复写出\n\t\t\t\tif (i > 0 || !this.usesFirstWordStartTime) {\n\t\t\t\t\toutput += this.formatTimeTag(word.startTime, inlineBracket);\n\t\t\t\t}\n\n\t\t\t\tlet wordText = word.word;\n\t\t\t\tif (isBgv) {\n\t\t\t\t\tif (i === 0) wordText = `(${wordText}`;\n\t\t\t\t\tif (i === words.length - 1) wordText = `${wordText})`;\n\t\t\t\t}\n\t\t\t\toutput += wordText;\n\n\t\t\t\t// 始终给最后一个词添加结束时间戳\n\t\t\t\tif (i === words.length - 1) {\n\t\t\t\t\toutput += this.formatTimeTag(word.endTime, inlineBracket);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn output;\n\t\t}\n\n\t\t// 逐行歌词\n\t\t// 包含普通 LRC 模式,或增强型 LRC 与 SPL 下没有逐字信息时\n\t\tconst timeTag = this.formatTimeTag(item.startTime, \"square\");\n\t\tconst textToUse = isBgv ? `(${lineText})` : lineText;\n\t\tlet output = `${timeTag}${textToUse}`;\n\n\t\t// 增强型 LRC 与 SPL 在没有逐字信息时,也要追加显式行结束时间\n\t\tif (wordLevel) {\n\t\t\toutput += this.formatTimeTag(item.endTime, \"square\");\n\t\t}\n\n\t\treturn output;\n\t}\n\n\tprivate processEndTimestamp(\n\t\tline: LyricLine,\n\t\tnextLine: LyricLine | undefined,\n\t\toutputLines: string[],\n\t): void {\n\t\tconst { mode: endTsMode, intervalGap: endTsGap } =\n\t\t\tthis.options.endTimestamp;\n\n\t\t// 写出逐字时间戳的模式自带行末时间戳,无需另起一行\n\t\tif (this.features.wordLevel || endTsMode === \"none\") return;\n\n\t\tconst gap = nextLine ? nextLine.startTime - line.endTime : Infinity;\n\n\t\tif (\n\t\t\tendTsMode === \"always\" ||\n\t\t\t(endTsMode === \"interval\" && gap >= endTsGap)\n\t\t) {\n\t\t\toutputLines.push(this.formatTimeTag(line.endTime, \"square\"));\n\t\t}\n\t}\n\n\t/**\n\t * 将毫秒渲染为时间戳\n\t *\n\t * 传入的时间都已由 {@link normalizeLine} 归一化过,这里再钳制到时间戳可表示的最大值,\n\t * 保证写出来的时间戳都能被解析回来\n\t */\n\tprivate formatTimeTag(\n\t\tms: number,\n\t\tbracket: \"angle\" | \"square\" = \"square\",\n\t): string {\n\t\tconst content = formatTime(clampTimestamp(ms));\n\t\treturn bracket === \"angle\" ? `<${content}>` : `[${content}]`;\n\t}\n}\n","import type { LyricLine, LyricParseResult, LyricWord } from \"../../types\";\nimport {\n\tcreateLine,\n\tcreateWord,\n\tMAX_LRC_TIMESTAMP,\n\tparseTimestampParts,\n} from \"../../utils\";\nimport {\n\tisBackgroundVocalText,\n\tisWordSyncLyric,\n\tjoinWords,\n\ttrimBackgroundVocalParentheses,\n} from \"./helpers\";\nimport { mergeMetadata, parseLrcMetadataLine } from \"./metadata\";\nimport { LRC_MODE_FEATURES, type LrcMetadata, type LrcMode } from \"./types\";\n\ntype TokenType = \"time\" | \"text\";\n\ninterface BaseToken {\n\ttype: TokenType;\n}\n\n/**\n * 一个时间戳被解析后的内容,如 `<05:21.22>`\n */\ninterface TimeToken extends BaseToken {\n\ttype: \"time\";\n\tval: number;\n}\n\n/**\n * 一段文本被解析后的内容\n */\ninterface TextToken extends BaseToken {\n\ttype: \"text\";\n\tval: string;\n}\n\ntype Token = TimeToken | TextToken;\n\ninterface LineFeature {\n\tfirstTextIndex: number;\n\tisWordSync: boolean;\n\t/** 该行是否为背景人声行,即整行文本都被圆括号包裹 */\n\tisBG: boolean;\n\t/** 该行所有文本原样拼接的结果,背景人声行保留最外层的圆括号 */\n\ttext: string;\n}\n\n/**\n * 解析过程中累积的行状态\n */\ninterface ParseState {\n\t/**\n\t * 上一(组)主歌词行\n\t */\n\tlastMainLines: LyricLine[];\n\t/**\n\t * 已经出现过的主歌词行,按开始时间索引到其中最早的那一条\n\t *\n\t * 带时间戳的翻译行不必紧挨着主歌词行,只需时间戳相同且位于其后,\n\t * 因此需要这份全局索引而不能只看 `lastMainLines`。\n\t * 同一时间已有多条主歌词行时以最早的那条为准——在前的一句才是主歌词文本\n\t */\n\tmainLinesByStartTime: Map<number, LyricLine>;\n\t/**\n\t * 每一行待展开的翻译\n\t *\n\t * 翻译要等结束时间推导出来之后才能展开成独立歌词行\n\t */\n\ttranslations: Map<LyricLine, string[]>;\n}\n\nexport interface ParseLrcLikeOptions {\n\t/**\n\t * 解析模式,详见 {@link LrcMode}\n\t * @default \"spl\"\n\t */\n\tmode?: LrcMode;\n}\n\n/**\n * 注释行的行首标记\n *\n * `#` 是 LRC 生态中常见的注释写法,`//` 则是 SPL 标准在示例里标注说明的写法,\n * 两者都没有被写进格式规范,这里一并按整行丢弃处理\n */\nconst COMMENT_PREFIXES = [\"#\", \"//\"];\n\nexport class LrcParser {\n\tprivate readonly mode: LrcMode;\n\n\t/**\n\t * 匹配行内所有的逐字时间戳\n\t *\n\t * 例如 `<05:21.22>` 或 `[05:23.22]`,`[00:13]` 这样省略毫秒段的写法同样算数,省略时视作 `0`。\n\t * 秒与毫秒之间本应使用半角句号,这里也接受半角冒号,以兼容不规范的既有歌词文件\n\t */\n\tprivate static readonly WORD_TIMESTAMP_REGEX =\n\t\t/(?:\\[|<)(?<min>\\d{1,3}):(?<sec>\\d{1,2})(?:[:.](?<ms>\\d{1,6}))?(?:\\]|>)/g;\n\n\tconstructor(options?: ParseLrcLikeOptions) {\n\t\tthis.mode = options?.mode ?? \"spl\";\n\t}\n\n\t/**\n\t * 解析 LRC 家族歌词\n\t * @param text 歌词文本\n\t * @returns 解析结果\n\t */\n\tpublic parse(text: string): LyricParseResult {\n\t\tconst metadata: LrcMetadata = [];\n\t\tconst allParsedLines: LyricLine[] = [];\n\t\tconst state: ParseState = {\n\t\t\tlastMainLines: [],\n\t\t\tmainLinesByStartTime: new Map(),\n\t\t\ttranslations: new Map(),\n\t\t};\n\n\t\tfor (const rawLine of text.split(/\\r?\\n/)) {\n\t\t\tconst trimmedLine = rawLine.trim();\n\t\t\tif (!trimmedLine) continue;\n\n\t\t\t// 注释行整行丢弃,只有开头为注释标记才丢弃,避免影响行中间带注释标记的歌词\n\t\t\tif (COMMENT_PREFIXES.some((prefix) => trimmedLine.startsWith(prefix))) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst parsedMeta = parseLrcMetadataLine(trimmedLine);\n\t\t\tif (parsedMeta) {\n\t\t\t\tmergeMetadata(metadata, parsedMeta);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst tokens = this.tokenizeLine(trimmedLine);\n\n\t\t\t// 无时间戳的隐式翻译行\n\t\t\tif (tokens.every((t) => t.type === \"text\")) {\n\t\t\t\tthis.appendTranslation(trimmedLine, [], state);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst features = this.getLineFeatures(tokens);\n\n\t\t\t// 只有时间戳、没有文本的行标记的是上一(组)歌词行的结束时间,本身不构成歌词行\n\t\t\tif (features.text.trim() === \"\") {\n\t\t\t\tthis.appendExplicitEndTime(tokens, state.lastMainLines);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst newLines = features.isWordSync\n\t\t\t\t? this.parseWordSyncLine(tokens, features, state)\n\t\t\t\t: this.parsePlainLines(tokens, features, state);\n\n\t\t\tif (newLines.length > 0) {\n\t\t\t\tthis.applyBackgroundVocal(newLines, features.isBG);\n\t\t\t\tallParsedLines.push(...newLines);\n\t\t\t\tstate.lastMainLines = newLines;\n\t\t\t\tfor (const line of newLines) {\n\t\t\t\t\tif (!state.mainLinesByStartTime.has(line.startTime)) {\n\t\t\t\t\t\tstate.mainLinesByStartTime.set(line.startTime, line);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tmetadata,\n\t\t\tlines: this.expandTranslations(\n\t\t\t\tthis.finalizeLyricLines(allParsedLines),\n\t\t\t\tstate.translations,\n\t\t\t),\n\t\t};\n\t}\n\n\t/**\n\t * 语法分析器\n\t */\n\tprivate tokenizeLine(line: string): Token[] {\n\t\tconst tokens: Token[] = [];\n\t\tlet lastIndex = 0;\n\n\t\tfor (const match of line.matchAll(LrcParser.WORD_TIMESTAMP_REGEX)) {\n\t\t\tif (!match.groups) continue;\n\n\t\t\tconst matchIndex = match.index ?? 0;\n\t\t\tconst textBefore = line.substring(lastIndex, matchIndex);\n\n\t\t\t// 时间戳前面的文本\n\t\t\tif (textBefore) {\n\t\t\t\ttokens.push({ type: \"text\", val: textBefore });\n\t\t\t}\n\n\t\t\tconst time = parseTimestampParts(\n\t\t\t\tmatch.groups.min,\n\t\t\t\tmatch.groups.sec,\n\t\t\t\tmatch.groups.ms,\n\t\t\t);\n\t\t\ttokens.push({ type: \"time\", val: time });\n\n\t\t\tlastIndex = matchIndex + match[0].length;\n\t\t}\n\n\t\t// 最后一部分隐式结束时间戳的文本\n\t\tconst textAfter = line.substring(lastIndex);\n\t\tif (textAfter) {\n\t\t\ttokens.push({ type: \"text\", val: textAfter });\n\t\t}\n\n\t\treturn tokens;\n\t}\n\n\tprivate getLineFeatures(tokens: Token[]): LineFeature {\n\t\tconst firstTextIndex = tokens.findIndex((t) => t.type === \"text\");\n\t\tlet isWordSync = false;\n\t\t// 检查文本后面是否还跟着时间戳以判断是否为逐字歌词\n\t\t// 必须要有行首时间戳才能是合法的歌词行\n\t\tif (firstTextIndex > 0) {\n\t\t\tfor (let i = firstTextIndex + 1; i < tokens.length; i++) {\n\t\t\t\tif (tokens[i].type === \"time\") {\n\t\t\t\t\tisWordSync = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst text = tokens\n\t\t\t.filter((t) => t.type === \"text\")\n\t\t\t.map((t) => t.val)\n\t\t\t.join(\"\");\n\n\t\treturn {\n\t\t\tfirstTextIndex,\n\t\t\tisWordSync,\n\t\t\tisBG: isBackgroundVocalText(text),\n\t\t\ttext,\n\t\t};\n\t}\n\n\t/**\n\t * 把整行被圆括号包裹的歌词行标记为背景人声,并去掉最外层的括号\n\t *\n\t * 与 YRC、QRC 的做法一致,只按整行是否被括号包裹判断。\n\t * 多个背景人声行各自独立处理,不做归并或配对\n\t * @param lines 已解析出来的歌词行\n\t * @param isBG 该行是否为背景人声行\n\t */\n\tprivate applyBackgroundVocal(lines: LyricLine[], isBG: boolean): void {\n\t\tif (!isBG) return;\n\t\tfor (const line of lines) {\n\t\t\tline.isBG = true;\n\t\t\ttrimBackgroundVocalParentheses(line.words);\n\t\t}\n\t}\n\n\t/**\n\t * 尝试将一段文本记录为已出现过的某(组)歌词行的翻译\n\t *\n\t * 时间信息必须一致才会认为是翻译,否则视为独立的歌词行\n\t * @returns 是否成功记录为翻译\n\t */\n\tprivate appendTranslation(\n\t\ttext: string,\n\t\tbaseTimes: number[],\n\t\tstate: ParseState,\n\t): boolean {\n\t\tif (text.trim() === \"\") return false;\n\n\t\t// 无时间戳的隐式翻译行只跟随紧挨着的上一(组)全部歌词行\n\t\tconst targets =\n\t\t\tbaseTimes.length === 0\n\t\t\t\t? state.lastMainLines\n\t\t\t\t: this.matchLinesByTime(baseTimes, state.mainLinesByStartTime);\n\t\tif (!targets || targets.length === 0) return false;\n\n\t\tfor (const line of targets) {\n\t\t\tconst texts = state.translations.get(line);\n\t\t\tif (texts) {\n\t\t\t\ttexts.push(text);\n\t\t\t} else {\n\t\t\t\tstate.translations.set(line, [text]);\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * 按时间戳找出与之对应的歌词行\n\t *\n\t * 翻译行可以不紧挨着主歌词行,所以在全部已出现的主歌词行里按开始时间查找。\n\t * 重复行写法的翻译需要每个时间戳都能找到宿主,只要有一个落空就不算翻译\n\t * @returns 对应的歌词行,时间信息不一致时为 `null`\n\t */\n\tprivate matchLinesByTime(\n\t\tbaseTimes: number[],\n\t\tmainLinesByStartTime: Map<number, LyricLine>,\n\t): LyricLine[] | null {\n\t\tconst targets: LyricLine[] = [];\n\t\tfor (const baseTime of baseTimes) {\n\t\t\tconst line = mainLinesByStartTime.get(baseTime);\n\t\t\tif (!line) return null;\n\t\t\ttargets.push(line);\n\t\t}\n\t\treturn targets;\n\t}\n\n\t/**\n\t * 将一行只有时间戳的歌词行作为上一(组)歌词行的显式结束时间\n\t *\n\t * 与行内写法 `文本[结束时间]` 一致,取该行最后一个时间戳作为结束时间。\n\t * 上一(组)歌词行不存在、已经有结束时间,或该时间戳不晚于其开始时间时,整行被忽略\n\t *\n\t * 重复行写法(`[t1][t2]文本`)会产生多条内容相同的歌词行,\n\t * 此时这个结束时间应该归属哪一条存在语义模糊:\n\t * 给最早的一条会让组内各行的结束时间不一致,给所有行又会造成时间区间相互重叠,\n\t * 格式本身没有说明哪种解读正确。这里选择只标记最后一条(即时间上最近一次出现)的行,\n\t * 组内其余行仍交给后续的推导逻辑决定结束时间\n\t */\n\tprivate appendExplicitEndTime(\n\t\ttokens: Token[],\n\t\tlastMainLines: LyricLine[],\n\t): void {\n\t\tconst lastTimeToken = tokens.findLast(\n\t\t\t(token): token is TimeToken => token.type === \"time\",\n\t\t);\n\t\tconst lastLine = lastMainLines[lastMainLines.length - 1];\n\t\tif (!lastTimeToken || !lastLine) return;\n\n\t\tconst endTime = lastTimeToken.val;\n\t\tif (lastLine.endTime !== -1 || endTime <= lastLine.startTime) return;\n\n\t\tlastLine.endTime = endTime;\n\t}\n\n\tprivate parsePlainLines(\n\t\ttokens: Token[],\n\t\tfeatures: LineFeature,\n\t\tstate: ParseState,\n\t): LyricLine[] {\n\t\tconst baseTimes: number[] = [];\n\t\tconst endIndex =\n\t\t\tfeatures.firstTextIndex !== -1 ? features.firstTextIndex : tokens.length;\n\n\t\t// 收集文本前面的所有时间戳,按照重复行特性生成多行内容相同的歌词行\n\t\tfor (let i = 0; i < endIndex; i++) {\n\t\t\tconst token = tokens[i];\n\t\t\tif (token.type === \"time\" && !baseTimes.includes(token.val)) {\n\t\t\t\tbaseTimes.push(token.val);\n\t\t\t}\n\t\t}\n\n\t\tif (\n\t\t\t!features.isBG &&\n\t\t\tthis.appendTranslation(features.text, baseTimes, state)\n\t\t) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// 逐行歌词只含一个音节,且与歌词同时开始\n\t\treturn baseTimes.map((baseTime) =>\n\t\t\tcreateLine({\n\t\t\t\tstartTime: baseTime,\n\t\t\t\tendTime: -1,\n\t\t\t\twords: [\n\t\t\t\t\tcreateWord({ word: features.text, startTime: baseTime, endTime: -1 }),\n\t\t\t\t],\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate parseWordSyncLine(\n\t\ttokens: Token[],\n\t\tfeatures: LineFeature,\n\t\tstate: ParseState,\n\t): LyricLine[] {\n\t\tconst firstToken = tokens[0];\n\t\t// 延迟逐字标记时间的 token\n\t\tconst delayToken = tokens[features.firstTextIndex - 1];\n\n\t\tif (firstToken?.type !== \"time\" || delayToken?.type !== \"time\") {\n\t\t\treturn [];\n\t\t}\n\n\t\t// 行起始时间是第一个 Token\n\t\tconst baseTime = firstToken.val;\n\n\t\tif (\n\t\t\t!features.isBG &&\n\t\t\tthis.appendTranslation(features.text, [baseTime], state)\n\t\t) {\n\t\t\treturn [];\n\t\t}\n\n\t\t// 首个音节发音时间:紧挨着文本前面的最后一个时间戳\n\t\t// 因为逐字歌词不能很好地处理重复行特性 所以忽略掉之间的、可能为重复行特性的时间戳\n\t\tconst syllableStartTimeInitial = delayToken.val;\n\t\tlet explicitEnd: number | undefined;\n\t\tconst syllables: LyricWord[] = [];\n\n\t\tlet currentText = \"\";\n\t\tlet syllableStartTime = syllableStartTimeInitial;\n\n\t\tconst pushSyllable = (text: string, start: number, end: number) => {\n\t\t\tsyllables.push(\n\t\t\t\tcreateWord({ word: text, startTime: start, endTime: end }),\n\t\t\t);\n\t\t};\n\n\t\tfor (let i = features.firstTextIndex; i < tokens.length; i++) {\n\t\t\tconst tok = tokens[i];\n\t\t\tif (tok.type === \"text\") {\n\t\t\t\tcurrentText += tok.val;\n\t\t\t} else if (tok.type === \"time\") {\n\t\t\t\tconst nextTime = tok.val;\n\n\t\t\t\tif (currentText !== \"\") {\n\t\t\t\t\tpushSyllable(currentText, syllableStartTime, nextTime);\n\t\t\t\t\tcurrentText = \"\";\n\t\t\t\t}\n\t\t\t\tsyllableStartTime = nextTime;\n\n\t\t\t\tif (i === tokens.length - 1) {\n\t\t\t\t\texplicitEnd = nextTime;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// 行尾的剩余文本 即隐式结束时间戳\n\t\tif (currentText !== \"\") {\n\t\t\tpushSyllable(\n\t\t\t\tcurrentText,\n\t\t\t\tsyllableStartTime,\n\t\t\t\t-1, // 下面处理隐式时间戳的时候处理\n\t\t\t);\n\t\t}\n\n\t\t// 逐字音节只有在值得保留时才留下,否则这一行与逐行歌词无异\n\t\treturn [\n\t\t\tcreateLine({\n\t\t\t\tstartTime: baseTime,\n\t\t\t\tendTime: explicitEnd ?? -1,\n\t\t\t\twords: isWordSyncLyric(syllables, baseTime)\n\t\t\t\t\t? syllables\n\t\t\t\t\t: [\n\t\t\t\t\t\t\tcreateWord({\n\t\t\t\t\t\t\t\tword: features.text,\n\t\t\t\t\t\t\t\tstartTime: baseTime,\n\t\t\t\t\t\t\t\tendTime: -1,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t],\n\t\t\t}),\n\t\t];\n\t}\n\n\tprivate finalizeLyricLines(allParsedLines: LyricLine[]): LyricLine[] {\n\t\t// 因为展开了重复行,因此需要按时间戳重新排序\n\t\tallParsedLines.sort((a, b) => a.startTime - b.startTime);\n\n\t\tthis.resolveEndTimes(allParsedLines);\n\n\t\t// 不保留逐字信息的模式下删除逐字时间戳\n\t\tif (!LRC_MODE_FEATURES[this.mode].wordLevel) {\n\t\t\tthis.stripWordTimings(allParsedLines);\n\t\t}\n\n\t\treturn allParsedLines;\n\t}\n\n\t/**\n\t * 决定所有尚未推导的时间,逐行歌词取下一行的开始时间,逐字歌词还会收尾最后一个音节\n\t */\n\tprivate resolveEndTimes(allParsedLines: LyricLine[]): void {\n\t\tfor (let i = 0; i < allParsedLines.length; i++) {\n\t\t\tconst line = allParsedLines[i];\n\t\t\tconst isLastLine = i === allParsedLines.length - 1;\n\n\t\t\t// 如果是逐行歌词,给最后一行设置 LRC 时间戳可表示的最大结束时间\n\t\t\tif (line.endTime === -1) {\n\t\t\t\tif (isLastLine && !isWordSyncLyric(line.words, line.startTime)) {\n\t\t\t\t\tline.endTime = MAX_LRC_TIMESTAMP;\n\t\t\t\t} else if (!isLastLine) {\n\t\t\t\t\tline.endTime = allParsedLines[i + 1].startTime;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 如果是逐字歌词,给最后一个词的结束时间加上1秒\n\t\t\tconst words = line.words;\n\t\t\tif (words.length > 0) {\n\t\t\t\tfor (let j = 0; j < words.length; j++) {\n\t\t\t\t\tconst word = words[j];\n\t\t\t\t\tif (word.endTime !== -1) continue;\n\t\t\t\t\tif (j + 1 < words.length) {\n\t\t\t\t\t\tword.endTime = words[j + 1].startTime;\n\t\t\t\t\t} else if (isLastLine && line.endTime === -1) {\n\t\t\t\t\t\tword.endTime = word.startTime + 1000;\n\t\t\t\t\t\tline.endTime = word.endTime;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tword.endTime = line.endTime;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * 普通 LRC 模式丢弃逐字时间戳,只留下覆盖整行的单个音节\n\t */\n\tprivate stripWordTimings(allParsedLines: LyricLine[]): void {\n\t\tfor (const line of allParsedLines) {\n\t\t\tif (line.words.length <= 1) continue;\n\t\t\tline.words = [\n\t\t\t\tcreateWord({\n\t\t\t\t\tword: joinWords(line.words),\n\t\t\t\t\tstartTime: line.startTime,\n\t\t\t\t\tendTime: line.endTime,\n\t\t\t\t}),\n\t\t\t];\n\t\t}\n\t}\n\n\t/**\n\t * 将翻译展开成与主歌词行同时开始、同时结束的独立歌词行\n\t */\n\tprivate expandTranslations(\n\t\tlines: LyricLine[],\n\t\ttranslations: Map<LyricLine, string[]>,\n\t): LyricLine[] {\n\t\tif (translations.size === 0) return lines;\n\n\t\tconst result: LyricLine[] = [];\n\t\tfor (const line of lines) {\n\t\t\tresult.push(line);\n\t\t\tfor (const text of translations.get(line) ?? []) {\n\t\t\t\tresult.push(\n\t\t\t\t\tcreateLine({\n\t\t\t\t\t\tstartTime: line.startTime,\n\t\t\t\t\t\tendTime: line.endTime,\n\t\t\t\t\t\twords: [\n\t\t\t\t\t\t\tcreateWord({\n\t\t\t\t\t\t\t\tword: text,\n\t\t\t\t\t\t\t\tstartTime: line.startTime,\n\t\t\t\t\t\t\t\tendTime: line.endTime,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t],\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n}\n","/**\n * @fileoverview LRC 家族歌词的解析与生成模块\n *\n * 普通 LRC、增强型 LRC(LRC A2)、ESLyric 逐词歌词与 Salt Player Lyrics 语出同源,\n * 因此共用一套解析和生成逻辑,仅针对每种格式进行小的针对性适配\n *\n * @see https://moriafly.com/standards/spl.html\n */\nimport type { LyricLine, LyricParseResult } from \"../../types\";\nimport { LrcGenerator, type StringifyLrcLikeOptions } from \"./generator\";\nimport { LrcParser, type ParseLrcLikeOptions } from \"./parser\";\n\nexport type {\n\tLrcAuxiliaryLineOptions,\n\tLrcAuxiliaryLinesOptions,\n\tLrcEndTimestampOptions,\n\tStringifyLrcLikeOptions,\n} from \"./generator\";\nexport type { ParseLrcLikeOptions } from \"./parser\";\n\n/**\n * 解析任意 LRC 家族歌词,包括普通 LRC、增强型 LRC、ESLyric 逐词歌词与 Salt Player Lyrics\n *\n * 因为 Salt Player Lyrics 是其余格式的超集,所以一个接口即可解析全部种类\n *\n * 同一时间可能出现多条歌词行(例如翻译与音译),\n * 本接口不做多语言适配,由使用者自行决定如何使用这些时间相同的歌词行\n *\n * @param text 歌词文本\n * @param options 解析选项\n * @returns 解析出来的歌词与元数据\n */\nexport function parseLrcLike(\n\ttext: string,\n\toptions?: ParseLrcLikeOptions,\n): LyricParseResult {\n\treturn new LrcParser(options).parse(text);\n}\n\n/**\n * 生成 LRC 家族歌词\n * @param input 歌词行,或带元数据的解析结果\n * @param options 生成选项\n * @returns 歌词文本\n */\nexport function stringifyLrcLike(\n\tinput: LyricParseResult | LyricLine[],\n\toptions?: StringifyLrcLikeOptions,\n): string {\n\treturn new LrcGenerator(options).generate(input);\n}\n\n/**\n * 解析 LyRiC 格式的歌词字符串\n * @param lrc 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseLrc(lrc: string): LyricLine[] {\n\treturn parseLrcLike(lrc).lines;\n}\n\n/**\n * 解析 ESLyric 逐词歌词格式的歌词字符串\n * @param eslrc 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseEslrc(eslrc: string): LyricLine[] {\n\treturn parseLrcLike(eslrc).lines;\n}\n\n/**\n * 解析 LRC A2(增强 LRC)格式的歌词字符串\n * @param lrc 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseLrcA2(lrc: string): LyricLine[] {\n\treturn parseLrcLike(lrc).lines;\n}\n\n/**\n * 解析 SPL(Salt Player Lyrics)格式的歌词字符串\n *\n * 上述几种格式都语出同源,本接口只是以 SPL 之名调用同一套解析算法\n * @param spl 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseSPL(spl: string): LyricLine[] {\n\treturn parseLrcLike(spl).lines;\n}\n\n/**\n * 将歌词数组转换为 LyRiC 格式的字符串\n * @param lines 歌词数组\n * @returns LyRiC 格式的字符串\n */\nexport function stringifyLrc(lines: LyricLine[]): string {\n\treturn stringifyLrcLike(lines, { mode: \"plain\" });\n}\n\n/**\n * 将歌词数组转换为 ESLyric 逐词歌词格式的字符串\n *\n * ESLyric 的逐词语法为「文本后跟该词的结束时间」,行首时间戳即首个词的开始时间,\n * 因此不写行自身的时间戳,行首时间戳直接取首个词的开始时间\n * @param lines 歌词数组\n * @returns ESLyric 逐词歌词格式的字符串\n */\nexport function stringifyEslrc(lines: LyricLine[]): string {\n\treturn stringifyLrcLike(lines, { mode: \"spl\", inlineBracket: \"square\" });\n}\n\n/**\n * 将歌词数组转换为 LRC A2(增强 LRC)格式的字符串\n * @param lines 歌词数组\n * @returns LRC A2 格式的字符串\n */\nexport function stringifyLrcA2(lines: LyricLine[]): string {\n\treturn stringifyLrcLike(lines, { mode: \"spl\", inlineBracket: \"angle\" });\n}\n\n/**\n * 生成 SPL(Salt Player Lyrics)格式的歌词字符串\n *\n * SPL 与增强型 LRC 的生成行为一致,逐字时间戳同样使用尖括号,\n * 因此本接口与 {@link stringifyLrcA2} 的输出完全相同\n * @param input 歌词行,或带元数据的解析结果\n * @returns SPL 格式的字符串\n */\nexport function stringifySPL(input: LyricParseResult | LyricLine[]): string {\n\treturn stringifyLrcLike(input, { mode: \"spl\", inlineBracket: \"angle\" });\n}\n","/**\n * @fileoverview Lyricify Lines(LYL)格式解析与生成。\n * 该格式为行级结构,每行使用 `[start,end]` 表示时间区间。\n *\n * 格式示例:\n * [type:LyricifyLines]\n * [54260,57380]Stop and stare\n * [57380,62840]I think I'm moving but I go nowhere\n */\nimport type { LyricLine } from \"../types\";\nimport { createLine, createWord, normalizeTimestamp } from \"../utils\";\n\n/**\n * 解析 LYL 格式的歌词字符串\n * @param lyl 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseLyl(lyl: string): LyricLine[] {\n\tconst lines = lyl\n\t\t.split(/\\r?\\n/)\n\t\t.map((l) => l.trim())\n\t\t.filter((l) => l.length > 0);\n\tconst lyricLines: LyricLine[] = [];\n\tconst timeRegex = /^\\[(\\d+),(\\d+)\\](.*)$/;\n\tconst bgRegex = /^[((](.+)[))]$/;\n\n\tfor (const lineStr of lines) {\n\t\tif (lineStr === \"[type:LyricifyLines]\") continue;\n\n\t\tconst timeMatch = lineStr.match(timeRegex);\n\t\tif (!timeMatch) continue;\n\n\t\tconst [, startStr, endStr, text] = timeMatch;\n\t\tconst startTime = Number(startStr);\n\t\tconst endTime = Number(endStr);\n\n\t\tconst backgroundMatch = text.match(bgRegex);\n\t\tconst isBG = Boolean(backgroundMatch);\n\t\tconst textContent = (backgroundMatch ? backgroundMatch[1] : text).trim();\n\t\tif (!textContent) continue;\n\n\t\tlyricLines.push(\n\t\t\tcreateLine({\n\t\t\t\tstartTime,\n\t\t\t\tendTime,\n\t\t\t\tisBG,\n\t\t\t\twords: [createWord({ word: textContent, startTime, endTime })],\n\t\t\t}),\n\t\t);\n\t}\n\n\treturn lyricLines;\n}\n\n/**\n * 将歌词数组转换为 LYL 格式的字符串\n * @param lines 歌词数组\n * @returns LYL 格式的字符串\n */\nexport function stringifyLyl(lines: LyricLine[]): string {\n\tconst header = \"[type:LyricifyLines]\";\n\tconst body = lines.map((line) => {\n\t\tconst text = line.words.map((w) => w.word).join(\"\");\n\t\tconst printText = line.isBG ? `(${text})` : text;\n\t\treturn `[${normalizeTimestamp(line.startTime)},${normalizeTimestamp(line.endTime)}]${printText}`;\n\t});\n\treturn [header, ...body].join(\"\\n\");\n}\n","/**\n * @fileoverview QRC(QQ 音乐逐词歌词)格式解析与生成。\n * 行开头为 [startTime,duration],每个词为 word(startTime,duration)\n *\n * 格式示例:\n * [190871,1984]For (190871,361)the (191232,172)first (191404,376)time(191780,1075)\n * [193459,4198]What's (193459,412)past (193871,574)is (194445,506)past(194951,2706)\n */\nimport type { LyricLine, LyricWord } from \"../types\";\nimport {\n\tcreateLine,\n\tcreateWord,\n\tnormalizeDuration,\n\tnormalizeTimestamp,\n} from \"../utils\";\n\n/**\n * 解析 QRC 格式的歌词字符串\n * @param qrc 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseQrc(qrc: string): LyricLine[] {\n\tconst wordPattern = /(.*?)\\((\\d+),(\\d+)\\)/g;\n\tconst linePattern = /^\\[(\\d+),(\\d+)\\]/;\n\n\tconst lines = qrc\n\t\t.split(/\\r?\\n/)\n\t\t.map((l) => l.trim())\n\t\t.filter((l) => l.length > 0);\n\n\treturn lines\n\t\t.map((lineStr) => {\n\t\t\tconst lineMatch = lineStr.match(linePattern);\n\t\t\tif (!lineMatch) return null;\n\t\t\tconst [linePrefix, lineStartStr, lineDurStr] = lineMatch;\n\n\t\t\tconst lineStart = Number(lineStartStr);\n\t\t\tconst lineDuration = Number(lineDurStr);\n\n\t\t\tconst words: LyricWord[] = [];\n\t\t\tconst lineContent = lineStr.slice(linePrefix.length).trim();\n\t\t\tif (!lineContent) return null;\n\n\t\t\tfor (const wordMatch of lineContent.matchAll(wordPattern)) {\n\t\t\t\tconst [, wordText, wordStartStr, wordDurStr] = wordMatch;\n\t\t\t\tconst wordStart = Number(wordStartStr);\n\t\t\t\tconst wordDur = Number(wordDurStr);\n\n\t\t\t\twords.push(\n\t\t\t\t\tcreateWord({\n\t\t\t\t\t\tword: wordText,\n\t\t\t\t\t\tstartTime: wordStart,\n\t\t\t\t\t\tendTime: wordStart + wordDur,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst isBG =\n\t\t\t\twords.length > 0 &&\n\t\t\t\t/^[((]/.test(words[0].word) &&\n\t\t\t\t/[))]$/.test(words[words.length - 1].word);\n\n\t\t\tif (isBG) {\n\t\t\t\twords[0].word = words[0].word.replace(/^[((]/, \"\");\n\t\t\t\twords[words.length - 1].word = words[words.length - 1].word.replace(\n\t\t\t\t\t/[))]$/,\n\t\t\t\t\t\"\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createLine({\n\t\t\t\tstartTime: lineStart,\n\t\t\t\tendTime: lineStart + lineDuration,\n\t\t\t\twords,\n\t\t\t\tisBG,\n\t\t\t});\n\t\t})\n\t\t.filter((line) => line !== null);\n}\n\n/**\n * 将歌词数组转换为 QRC 格式的字符串\n * @param lines 歌词数组\n * @returns QRC 格式的字符串\n */\nexport function stringifyQrc(lines: LyricLine[]): string {\n\treturn lines\n\t\t.map((line) => {\n\t\t\tconst lineStart = normalizeTimestamp(line.startTime);\n\t\t\tconst lineEnd = normalizeTimestamp(line.endTime);\n\t\t\tconst lineDuration = normalizeDuration(lineEnd - lineStart);\n\n\t\t\tconst lineWords: string[] = [];\n\t\t\tfor (const [\n\t\t\t\tindex,\n\t\t\t\t{ word, startTime, endTime },\n\t\t\t] of line.words.entries()) {\n\t\t\t\tif (!word.trim() && lineWords.length) {\n\t\t\t\t\tlineWords[lineWords.length - 1] += word;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlet printedWord = word;\n\t\t\t\tif (line.isBG) {\n\t\t\t\t\tif (index === 0) printedWord = `(${printedWord}`;\n\t\t\t\t\tif (index === line.words.length - 1) printedWord += \")\";\n\t\t\t\t}\n\t\t\t\tconst normalizedWordStart = normalizeTimestamp(startTime);\n\t\t\t\tconst normalizedWordEnd = normalizeTimestamp(endTime);\n\t\t\t\tconst wordDuration = normalizeDuration(\n\t\t\t\t\tnormalizedWordEnd - normalizedWordStart,\n\t\t\t\t);\n\t\t\t\tlineWords.push(\n\t\t\t\t\t`${printedWord}(${normalizedWordStart},${wordDuration})`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn `[${lineStart},${lineDuration}]${lineWords.join(\"\")}`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n","import {\n\texportTTML,\n\tparseTTML as parseTTMLPacked,\n} from \"@applemusic-like-lyrics/ttml\";\nimport type { TTMLLyric } from \"../types\";\n\n/**\n * 解析 TTML 格式(包含 AMLL 特有属性信息)的歌词字符串\n * @param ttmlText 歌词字符串\n * @returns 成功解析出来的 TTML 歌词对象\n */\nexport function parseTTML(ttmlText: string): TTMLLyric {\n\treturn parseTTMLPacked(ttmlText);\n}\n\n/**\n * 将歌词数组转换为 TTML 格式(包含 AMLL 特有属性信息)的歌词字符串\n * @param ttmlLyric TTML 歌词对象\n */\nexport function stringifyTTML(ttmlLyric: TTMLLyric): string {\n\treturn exportTTML(ttmlLyric);\n}\n","/**\n * @fileoverview YRC(网易云音乐逐词歌词)格式解析与生成。\n * 行开头为 [startTime,duration],每个词为 (startTime,duration,0)word\n *\n * 格式示例:\n * [190871,1984](190871,361,0)For (191232,172,0)the (191404,376,0)first (191780,1075,0)time\n * [193459,4198](193459,412,0)What's (193871,574,0)past (194445,506,0)is (194951,2706,0)past\n */\nimport type { LyricLine, LyricWord } from \"../types\";\nimport {\n\tcreateLine,\n\tcreateWord,\n\tnormalizeDuration,\n\tnormalizeTimestamp,\n} from \"../utils\";\n\nconst beginParenPattern = /^[((]/;\nconst endParenPattern = /[))]$/;\nfunction checkIsBG(words: LyricWord[]): boolean {\n\treturn (\n\t\twords.length > 0 &&\n\t\tbeginParenPattern.test(words[0].word) &&\n\t\tendParenPattern.test(words[words.length - 1].word)\n\t);\n}\nfunction trimBGParentheses(words: LyricWord[]): void {\n\twords[0].word = words[0].word.slice(1);\n\twords[words.length - 1].word = words[words.length - 1].word.slice(0, -1);\n}\n\n/**\n * 解析 YRC 格式的歌词字符串\n * @param yrc 歌词字符串\n * @returns 成功解析出来的歌词\n */\nexport function parseYrc(yrc: string): LyricLine[] {\n\tconst wordPattern = /^(.*?)\\((\\d+),(\\d+),0\\)/;\n\tconst linePattern = /^\\[(\\d+),(\\d+)\\]/;\n\n\tconst lines = yrc\n\t\t.split(/\\r?\\n/)\n\t\t.map((l) => l.trim())\n\t\t.filter((l) => l.length > 0);\n\n\treturn lines\n\t\t.map((lineStr) => {\n\t\t\tconst lineMatch = lineStr.match(linePattern);\n\t\t\tif (!lineMatch) return null;\n\t\t\tconst [linePrefix, lineStartStr, lineDurStr] = lineMatch;\n\t\t\tconst lineStart = Number(lineStartStr);\n\t\t\tconst lineDuration = Number(lineDurStr);\n\n\t\t\tconst words: LyricWord[] = [];\n\t\t\tlet lineContent = lineStr.slice(linePrefix.length).trim();\n\t\t\tif (!lineContent) return null;\n\n\t\t\tlet lastStart = -1;\n\t\t\tlet lastEnd = -1;\n\t\t\twhile (true) {\n\t\t\t\tconst wordMatch = lineContent.match(wordPattern);\n\t\t\t\tif (!wordMatch) break;\n\t\t\t\tconst [fullMatch, lastText, wordStartStr, wordDurStr] = wordMatch;\n\t\t\t\tif (lastText && lastStart !== -1)\n\t\t\t\t\twords.push(\n\t\t\t\t\t\tcreateWord({\n\t\t\t\t\t\t\tword: lastText,\n\t\t\t\t\t\t\tstartTime: lastStart,\n\t\t\t\t\t\t\tendTime: lastEnd,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\tconst wordStart = Number(wordStartStr);\n\t\t\t\tconst wordDur = Number(wordDurStr);\n\t\t\t\tconst wordEnd = wordStart + wordDur;\n\t\t\t\t[lastStart, lastEnd] = [wordStart, wordEnd];\n\t\t\t\tlineContent = lineContent.slice(fullMatch.length);\n\t\t\t}\n\t\t\tif (lastStart !== -1 && lineContent)\n\t\t\t\twords.push(\n\t\t\t\t\tcreateWord({\n\t\t\t\t\t\tword: lineContent,\n\t\t\t\t\t\tstartTime: lastStart,\n\t\t\t\t\t\tendTime: lastEnd,\n\t\t\t\t\t}),\n\t\t\t\t);\n\n\t\t\tconst isBG = checkIsBG(words);\n\t\t\tif (isBG) trimBGParentheses(words);\n\t\t\treturn createLine({\n\t\t\t\tstartTime: lineStart,\n\t\t\t\tendTime: lineStart + lineDuration,\n\t\t\t\twords,\n\t\t\t\tisBG,\n\t\t\t});\n\t\t})\n\t\t.filter((line): line is LyricLine => line !== null);\n}\n\nfunction makeParenthesesFull(text: string): string {\n\treturn text.replace(/\\(/g, \"(\").replace(/\\)/g, \")\");\n}\n\n/**\n * 将歌词数组转换为 YRC 格式的字符串\n * @param lines 歌词数组\n * @returns YRC 格式的字符串\n */\nexport function stringifyYrc(lines: LyricLine[]): string {\n\treturn lines\n\t\t.map((line) => {\n\t\t\tconst lineStart = normalizeTimestamp(line.startTime);\n\t\t\tconst lineEnd = normalizeTimestamp(line.endTime);\n\t\t\tconst lineDuration = normalizeDuration(lineEnd - lineStart);\n\n\t\t\tconst lineWords: string[] = [];\n\t\t\tfor (const [\n\t\t\t\tindex,\n\t\t\t\t{ word, startTime, endTime },\n\t\t\t] of line.words.entries()) {\n\t\t\t\tif (!word.trim() && lineWords.length) {\n\t\t\t\t\tlineWords[lineWords.length - 1] += word;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlet printedWord = makeParenthesesFull(word);\n\t\t\t\tif (line.isBG) {\n\t\t\t\t\tif (index === 0) printedWord = `(${printedWord}`;\n\t\t\t\t\tif (index === line.words.length - 1) printedWord += \")\";\n\t\t\t\t}\n\t\t\t\tconst normalizedWordStart = normalizeTimestamp(startTime);\n\t\t\t\tconst normalizedWordEnd = normalizeTimestamp(endTime);\n\t\t\t\tconst wordDuration = normalizeDuration(\n\t\t\t\t\tnormalizedWordEnd - normalizedWordStart,\n\t\t\t\t);\n\t\t\t\tlineWords.push(\n\t\t\t\t\t`(${normalizedWordStart},${wordDuration},0)${printedWord}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn `[${lineStart},${lineDuration}]${lineWords.join(\"\")}`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n","export { stringifyAss } from \"./formats/ass\";\nexport { decryptQrcHex, encryptQrcHex } from \"./formats/eqrc\";\nexport { parseLqe, stringifyLqe } from \"./formats/lqe\";\nexport type {\n\tLrcAuxiliaryLineOptions,\n\tLrcAuxiliaryLinesOptions,\n\tLrcEndTimestampOptions,\n\tParseLrcLikeOptions,\n\tStringifyLrcLikeOptions,\n} from \"./formats/lrc\";\nexport {\n\tparseEslrc,\n\tparseLrc,\n\tparseLrcA2,\n\tparseLrcLike,\n\tparseSPL,\n\tstringifyEslrc,\n\tstringifyLrc,\n\tstringifyLrcA2,\n\tstringifyLrcLike,\n\tstringifySPL,\n} from \"./formats/lrc\";\nexport { parseLyl, stringifyLyl } from \"./formats/lyl\";\nexport { parseLys, stringifyLys } from \"./formats/lys\";\nexport { parseQrc, stringifyQrc } from \"./formats/qrc\";\nexport { parseTTML, stringifyTTML } from \"./formats/ttml\";\nexport { parseYrc, stringifyYrc } from \"./formats/yrc\";\n\nimport { stringifyLrcA2 } from \"./formats/lrc\";\n\n/**\n * {@link stringifyLrcA2} 的别名。\n *\n * @deprecated 此为兼容旧版本拼写错误的接口,请改用 `stringifyLrcA2`。此接口将在未来版本中移除。\n */\nexport function stringifylrcA2(\n\t...args: Parameters<typeof stringifyLrcA2>\n): ReturnType<typeof stringifyLrcA2> {\n\treturn stringifyLrcA2(...args);\n}\n\nexport type {\n\tLyricLine,\n\tLyricParseResult,\n\tLyricWord,\n\tTTMLLyric,\n} from \"./types\";\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@applemusic-like-lyrics/lyric",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "一个歌词解析/生成模块,着重于歌词内容解析,支持多种格式",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/amll-dev/applemusic-like-lyrics.git",
|
|
@@ -44,14 +44,13 @@
|
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@biomejs/biome": "^2.
|
|
48
|
-
"@types/node": "^
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"vitest": "^4.1.6"
|
|
47
|
+
"@biomejs/biome": "^2.5.7",
|
|
48
|
+
"@types/node": "^26.2.0",
|
|
49
|
+
"tsdown": "^0.22.14",
|
|
50
|
+
"vitest": "^4.1.10"
|
|
52
51
|
},
|
|
53
52
|
"dependencies": {
|
|
54
|
-
"pako": "^
|
|
53
|
+
"pako": "^3.0.1",
|
|
55
54
|
"@applemusic-like-lyrics/ttml": "^1.0.1"
|
|
56
55
|
},
|
|
57
56
|
"scripts": {
|