@applemusic-like-lyrics/lyric 1.0.0 → 1.0.2

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.
@@ -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"],"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"],"mappings":"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AAG;EAAI;EAAG;EAAG;EAAI;EAAG;EAAG;EAAI;EAAG;EAC3E;EAAI;EAAG;EAAG;EAAI;EAAI;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAI;EAAI;EAAG;EAAI;EAAG;EAAG;EACzD;CACuB;EACvB;EAAG;EAAI;EAAI;EAAG;EAAG;EAAG;EAAG;EAAI;EAAG;EAAG;EAAG;EAAG;EAAI;EAAI;EAAG;EAAI;EAAI;EAAG;EAAI;EAAG;EAAG;EAAI;EAC3E;EAAG;EAAG;EAAG;EAAG;EAAI;EAAG;EAAI;EAAI;EAAG;EAAI;EAAG;EAAG;EAAG;EAAI;EAAI;EAAG;EAAI;EAAI;EAAG;EAAG;EAAI;EAAG;EAC3E;EAAG;EAAG;EAAG;EAAI;EAAG;EAAG;EAAI;EAAI;EAAI;EAAG;EAAG;EAAG;EAAG;EAAI;EAAI;EAAG;EAAG;EACzD;CACuB;EACvB;EAAG;EAAI;EAAG;EAAG;EAAG;EAAI;EAAI;EAAG;EAAG;EAAG;EAAG;EAAI;EAAI;EAAG;EAAI;EAAG;EAAI;EAAI;EAAG;EAAI;EAAG;EAAG;EAC3E;EAAG;EAAG;EAAG;EAAI;EAAI;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAG;EAAI;EAAI;EAAI;EAAG;EAAG;EAAI;EAAG;EAAI;EAAG;EAAG;EAAG;EAC5E;EAAI;EAAI;EAAG;EAAI;EAAG;EAAG;EAAI;EAAG;EAAI;EAAG;EAAI;EAAG;EAAG;EAAI;EAAG;EAAG;EACvD;CACuB;EACvB;EAAI;EAAG;EAAI;EAAI;EAAG;EAAG;EAAG;EAAG;EAAG;EAAI;EAAG;EAAG;EAAI;EAAG;EAAG;EAAI;EAAI;EAAI;EAAG;EAAG;EAAG;EAAI;EAC3E;EAAG;EAAG;EAAG;EAAI;EAAI;EAAG;EAAI;EAAG;EAAG;EAAG;EAAI;EAAI;EAAG;EAAG;EAAG;EAAI;EAAG;EAAG;EAAG;EAAG;EAAI;EAAG;EACzE;EAAI;EAAG;EAAG;EAAG;EAAG;EAAI;EAAG;EAAG;EAAI;EAAI;EAAI;EAAI;EAAG;EAAG;EAAG;EAAG;EAAG;EACzD;CACuB;EACvB;EAAG;EAAI;EAAG;EAAI;EAAI;EAAG;EAAG;EAAI;EA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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/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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"}
package/package.json CHANGED
@@ -1,50 +1,69 @@
1
1
  {
2
- "name": "@applemusic-like-lyrics/lyric",
3
- "version": "1.0.0",
4
- "description": "一个歌词解析/生成模块,着重于歌词内容解析,支持多种格式",
5
- "repository": {
6
- "url": "https://github.com/amll-dev/applemusic-like-lyrics.git",
7
- "directory": "packages/lyric",
8
- "type": "git"
9
- },
10
- "license": "GPL-3.0",
11
- "type": "module",
12
- "files": [
13
- "dist"
14
- ],
15
- "main": "./dist/amll-lyric.cjs",
16
- "module": "./dist/amll-lyric.mjs",
17
- "types": "./dist/amll-lyric.d.mts",
18
- "exports": {
19
- "import": {
20
- "types": "./dist/amll-lyric.d.mts",
21
- "default": "./dist/amll-lyric.mjs"
22
- },
23
- "require": {
24
- "types": "./dist/amll-lyric.d.cts",
25
- "default": "./dist/amll-lyric.cjs"
26
- }
27
- },
28
- "scripts": {
29
- "build:docs": "typedoc --plugin typedoc-plugin-markdown --out docs src/index.ts",
30
- "typecheck": "tsgo -b",
31
- "build-only": "tsdown",
32
- "build": "run-p typecheck \"build-only {@}\" --",
33
- "build:dev": "tsdown",
34
- "fmt": "biome format --write ./src",
35
- "dev": "vite dev",
36
- "test": "bun test",
37
- "test:watch": "bun test --watch",
38
- "test:coverage": "bun test --coverage"
39
- },
40
- "devDependencies": {
41
- "@biomejs/biome": "^2.4.8",
42
- "@types/node": "^25.5.2",
43
- "@types/pako": "^2.0.4",
44
- "tsdown": "^0.21.9"
45
- },
46
- "dependencies": {
47
- "pako": "^2.1.0",
48
- "@applemusic-like-lyrics/ttml": "^1.0.0"
49
- }
50
- }
2
+ "name": "@applemusic-like-lyrics/lyric",
3
+ "version": "1.0.2",
4
+ "description": "一个歌词解析/生成模块,着重于歌词内容解析,支持多种格式",
5
+ "repository": {
6
+ "url": "https://github.com/amll-dev/applemusic-like-lyrics.git",
7
+ "directory": "packages/lyric",
8
+ "type": "git"
9
+ },
10
+ "license": "AGPL-3.0-only",
11
+ "nx": {
12
+ "tags": [
13
+ "library"
14
+ ],
15
+ "targets": {
16
+ "test": {
17
+ "executor": "nx:run-commands",
18
+ "options": {
19
+ "command": "vitest test",
20
+ "cwd": "packages/lyric"
21
+ }
22
+ },
23
+ "nx-release-publish": {
24
+ "executor": "@nx/js:release-publish",
25
+ "dependsOn": []
26
+ }
27
+ }
28
+ },
29
+ "type": "module",
30
+ "files": [
31
+ "dist"
32
+ ],
33
+ "main": "./dist/amll-lyric.cjs",
34
+ "module": "./dist/amll-lyric.mjs",
35
+ "types": "./dist/amll-lyric.d.mts",
36
+ "exports": {
37
+ "import": {
38
+ "types": "./dist/amll-lyric.d.mts",
39
+ "default": "./dist/amll-lyric.mjs"
40
+ },
41
+ "require": {
42
+ "types": "./dist/amll-lyric.d.cts",
43
+ "default": "./dist/amll-lyric.cjs"
44
+ }
45
+ },
46
+ "devDependencies": {
47
+ "@biomejs/biome": "^2.4.8",
48
+ "@types/node": "^25.8.0",
49
+ "@types/pako": "^2.0.4",
50
+ "tsdown": "^0.22.0",
51
+ "vitest": "^4.1.6"
52
+ },
53
+ "dependencies": {
54
+ "pako": "^2.1.0",
55
+ "@applemusic-like-lyrics/ttml": "^1.0.1"
56
+ },
57
+ "scripts": {
58
+ "build:docs": "typedoc --plugin typedoc-plugin-markdown --out docs src/index.ts",
59
+ "typecheck": "tsgo -b",
60
+ "build-only": "tsdown",
61
+ "build": "run-p typecheck \"build-only {@}\" --",
62
+ "build:dev": "tsdown",
63
+ "fmt": "biome format --write ./src",
64
+ "dev": "vite dev",
65
+ "test": "vitest test",
66
+ "test:watch": "vitest test --watch",
67
+ "test:coverage": "vitest test --coverage"
68
+ }
69
+ }