From 23f118fb1a1af6dc6c558d4ce13cab0b9bbe4c67 Mon Sep 17 00:00:00 2001 From: lyswhut Date: Wed, 21 Jun 2023 11:59:38 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BF=87=E6=BB=A4=E5=B5=8C=E5=85=A5=E3=80=81?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E7=9A=84=E7=BF=BB=E8=AF=91=E3=80=81=E7=BD=97?= =?UTF-8?q?=E9=A9=AC=E9=9F=B3=E6=AD=8C=E8=AF=8D=E6=97=B6=E9=97=B4=E6=A0=87?= =?UTF-8?q?=E7=AD=BE=EF=BC=88#1358=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- publish/changeLog.md | 1 + src/renderer/store/download/action.ts | 29 ++++++---- src/renderer/worker/download/common.ts | 5 +- src/renderer/worker/download/lrcTool.ts | 74 +++++++++++++++++++++++++ src/renderer/worker/download/utils.ts | 4 +- 5 files changed, 98 insertions(+), 15 deletions(-) create mode 100644 src/renderer/worker/download/lrcTool.ts diff --git a/publish/changeLog.md b/publish/changeLog.md index 3299d89d..977d9c01 100644 --- a/publish/changeLog.md +++ b/publish/changeLog.md @@ -7,6 +7,7 @@ - Windows、MacOS平台下的字体列表改用原生方式获取,现在Windows平台下能显示当前已安装的更多类型字体了(注:MacOS平台未测,可用性未知) - 移除桌面歌词窗口透明边距,在Linux下的桌面歌词可以完全拖到贴合屏幕边缘了 +- 过滤嵌入、下载的翻译、罗马音歌词时间标签,与主歌词时间不匹配的歌词将被丢弃,防止出现原歌词与翻译歌词顺序错乱的问题(#1358) ### 修复 diff --git a/src/renderer/store/download/action.ts b/src/renderer/store/download/action.ts index 02b856e2..02db7e09 100644 --- a/src/renderer/store/download/action.ts +++ b/src/renderer/store/download/action.ts @@ -148,19 +148,22 @@ const saveMeta = (downloadInfo: LX.Download.ListItem) => { : Promise.resolve(null), ] void Promise.all(tasks).then(([imgUrl, lyrics]) => { - let lyric: null | string = null - if (lyrics?.lyric) { - lyric = fixKgLyric(lyrics.lyric) - if (appSetting['download.isEmbedLyricT'] && lyrics.tlyric) lyric += '\n' + lyrics.tlyric + '\n' - if (appSetting['download.isEmbedLyricR'] && lyrics.rlyric) lyric += '\n' + lyrics.rlyric + '\n' + const lrcData = { + lrc: '', + tlrc: null as string | null, + rlrc: null as string | null, + } + if (lyrics) { + lrcData.lrc = lyrics.lyric + if (appSetting['download.isEmbedLyricT'] && lyrics.tlyric) lrcData.tlrc = lyrics.tlyric + if (appSetting['download.isEmbedLyricR'] && lyrics.rlyric) lrcData.rlrc = lyrics.rlyric } void window.lx.worker.download.writeMeta(downloadInfo.metadata.filePath, { title: downloadInfo.metadata.musicInfo.name, artist: downloadInfo.metadata.musicInfo.singer, album: downloadInfo.metadata.musicInfo.meta.albumName, APIC: imgUrl, - lyrics: lyric, - }) + }, lrcData) }) } @@ -177,11 +180,13 @@ const downloadLyric = (downloadInfo: LX.Download.ListItem) => { }).then(lrcs => { if (lrcs.lyric) { lrcs.lyric = fixKgLyric(lrcs.lyric) - let lyric = lrcs.lyric - if (appSetting['download.isDownloadTLrc'] && lrcs.tlyric) lyric += '\n' + lrcs.tlyric + '\n' - if (appSetting['download.isDownloadRLrc'] && lrcs.rlyric) lyric += '\n' + lrcs.rlyric + '\n' - void window.lx.worker.download.saveLrc(downloadInfo.metadata.filePath.replace(/(mp3|flac|ape|wav)$/, 'lrc'), - lyric, appSetting['download.lrcFormat']) + const lrcData = { + lrc: lrcs.lyric, + tlrc: appSetting['download.isDownloadTLrc'] && lrcs.tlyric ? lrcs.tlyric : null, + rlrc: appSetting['download.isDownloadRLrc'] && lrcs.rlyric ? lrcs.rlyric : null, + } + void window.lx.worker.download.saveLrc(lrcData, downloadInfo.metadata.filePath.replace(/(mp3|flac|ape|wav)$/, 'lrc'), + appSetting['download.lrcFormat']) } }) } diff --git a/src/renderer/worker/download/common.ts b/src/renderer/worker/download/common.ts index 946ecf3d..6aafe61e 100644 --- a/src/renderer/worker/download/common.ts +++ b/src/renderer/worker/download/common.ts @@ -1,7 +1,8 @@ import { setMeta } from '@common/utils/musicMeta' +import { mergeLyrics } from './lrcTool' -export const writeMeta = (filePath: string, meta: LX.Music.MusicFileMeta) => { - setMeta(filePath, meta) +export const writeMeta = (filePath: string, meta: Omit, lyricData: { lrc: string, tlrc: string | null, rlrc: string | null }) => { + setMeta(filePath, { ...meta, lyrics: mergeLyrics(lyricData.lrc, lyricData.tlrc, lyricData.rlrc) || null }) } export { saveLrc } from './utils' diff --git a/src/renderer/worker/download/lrcTool.ts b/src/renderer/worker/download/lrcTool.ts new file mode 100644 index 00000000..bbb31f69 --- /dev/null +++ b/src/renderer/worker/download/lrcTool.ts @@ -0,0 +1,74 @@ +const timeFieldExp = /^(?:\[[\d:.]+\])+/g +const timeExp = /\d{1,3}(:\d{1,3}){0,2}(?:\.\d{1,3})/g + +const t_rxp_1 = /^0+(\d+)/ +const t_rxp_2 = /:0+(\d+)/g +const t_rxp_3 = /\.0+(\d+)/ +const formatTimeLabel = (label: string) => { + return label.replace(t_rxp_1, '$1') + .replace(t_rxp_2, ':$1') + .replace(t_rxp_3, '.$1') +} + +const filterExtendedLyricLabel = (lrcTimeLabels: Set, extendedLyric: string) => { + const extendedLines = extendedLyric.split(/\r\n|\n|\r/) + const lines: string[] = [] + for (let i = 0; i < extendedLines.length; i++) { + let line = extendedLines[i].trim() + let result = timeFieldExp.exec(line) + if (!result) continue + + const timeField = result[0] + const text = line.replace(timeFieldExp, '').trim() + if (!text) continue + let times = timeField.match(timeExp) + if (times == null) continue + + const newTimes = times.filter(time => { + const timeStr = formatTimeLabel(time) + return lrcTimeLabels.has(timeStr) + }) + if (newTimes.length != times.length) { + if (!newTimes.length) continue + line = `[${newTimes.join('][')}]${text}` + } + lines.push(line) + } + + return lines.join('\n') +} + +const parseLrcTimeLabel = (lrc: string) => { + const lines = lrc.split(/\r\n|\n|\r/) + const linesSet = new Set() + const length = lines.length + for (let i = 0; i < length; i++) { + const line = lines[i].trim() + let result = timeFieldExp.exec(line) + if (result) { + const timeField = result[0] + const text = line.replace(timeFieldExp, '').trim() + if (text) { + const times = timeField.match(timeExp) + if (times == null) continue + for (let time of times) { + linesSet.add(formatTimeLabel(time)) + } + } + } + } + + return linesSet +} + + +export const mergeLyrics = (lrc: string, tlrc: string | null, rlrc: string | null) => { + if (!tlrc && !rlrc) return lrc + + const lrcTimeLabels = parseLrcTimeLabel(lrc) + // console.log(lrcTimeLabels) + if (tlrc) lrc += `\n\n${filterExtendedLyricLabel(lrcTimeLabels, tlrc)}\n` + if (rlrc) lrc += `\n\n${filterExtendedLyricLabel(lrcTimeLabels, rlrc)}\n` + // console.log(lrc) + return lrc +} diff --git a/src/renderer/worker/download/utils.ts b/src/renderer/worker/download/utils.ts index cfe0b427..97434e55 100644 --- a/src/renderer/worker/download/utils.ts +++ b/src/renderer/worker/download/utils.ts @@ -1,6 +1,7 @@ import { DOWNLOAD_STATUS, QUALITYS } from '@common/constants' import { filterFileName } from '@common/utils/common' import { joinPath } from '@common/utils/nodejs' +import { mergeLyrics } from './lrcTool' import fs from 'fs' /** @@ -9,8 +10,9 @@ import fs from 'fs' * @param {*} lrc * @param {*} format */ -export const saveLrc = async(filePath: string, lrc: string, format: LX.LyricFormat) => { +export const saveLrc = async(lrcData: { lrc: string, tlrc: string | null, rlrc: string | null }, filePath: string, format: LX.LyricFormat) => { const iconv = await import('iconv-lite') + const lrc = mergeLyrics(lrcData.lrc, lrcData.tlrc, lrcData.rlrc) switch (format) { case 'gbk': fs.writeFile(filePath, iconv.encode(lrc, 'gbk', { addBOM: true }), err => {