Merge branch 'lyswhut:dev' into dev
This commit is contained in:
commit
a597249744
1143
package-lock.json
generated
1143
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lx-music-desktop",
|
||||
"version": "2.3.0-beta.9",
|
||||
"version": "2.3.0-beta.10",
|
||||
"description": "一个免费的音乐查找助手",
|
||||
"main": "./dist/main.js",
|
||||
"productName": "lx-music-desktop",
|
||||
@ -221,8 +221,8 @@
|
||||
"@types/needle": "^3.2.0",
|
||||
"@types/tunnel": "^0.0.3",
|
||||
"@types/ws": "8.5.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.11",
|
||||
"@typescript-eslint/parser": "^5.59.11",
|
||||
"@typescript-eslint/eslint-plugin": "^5.60.0",
|
||||
"@typescript-eslint/parser": "^5.60.0",
|
||||
"@volar/vue-language-plugin-pug": "^1.6.5",
|
||||
"babel-loader": "^9.1.2",
|
||||
"browserslist": "^4.21.9",
|
||||
@ -235,12 +235,12 @@
|
||||
"css-minimizer-webpack-plugin": "^5.0.1",
|
||||
"del": "^6.1.1",
|
||||
"electron": "^22.3.13",
|
||||
"electron-builder": "^24.4.0",
|
||||
"electron-builder": "^24.5.0",
|
||||
"electron-debug": "^3.2.0",
|
||||
"electron-devtools-installer": "^3.2.0",
|
||||
"electron-to-chromium": "^1.4.432",
|
||||
"electron-updater": "^6.1.0",
|
||||
"eslint": "^8.42.0",
|
||||
"electron-to-chromium": "^1.4.435",
|
||||
"electron-updater": "^6.1.1",
|
||||
"eslint": "^8.43.0",
|
||||
"eslint-config-standard": "^17.1.0",
|
||||
"eslint-config-standard-with-typescript": "^35.0.0",
|
||||
"eslint-formatter-friendly": "github:lyswhut/eslint-friendly-formatter#2170d1320e2fad13615a9dcf229669f0bb473a53",
|
||||
@ -248,7 +248,7 @@
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-n": "^15.7.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-vue": "^9.14.1",
|
||||
"eslint-plugin-vue": "^9.15.0",
|
||||
"eslint-plugin-vue-pug": "^0.6.0",
|
||||
"eslint-webpack-plugin": "^4.0.1",
|
||||
"html-webpack-plugin": "^5.5.3",
|
||||
@ -266,7 +266,7 @@
|
||||
"svg-sprite-loader": "^6.0.11",
|
||||
"svg-transform-loader": "^2.0.13",
|
||||
"svgo-loader": "^4.0.0",
|
||||
"terser": "^5.18.0",
|
||||
"terser": "^5.18.1",
|
||||
"terser-webpack-plugin": "^5.3.9",
|
||||
"ts-loader": "^9.4.3",
|
||||
"typescript": "^5.1.3",
|
||||
@ -285,7 +285,7 @@
|
||||
"bufferutil": "^4.0.7",
|
||||
"comlink": "~4.3.1",
|
||||
"crypto-js": "^4.1.1",
|
||||
"electron-font-manager": "github:lyswhut/electron-font-manager#60348260de557753c870cc671c56da6f58fd0ef7",
|
||||
"electron-font-manager": "github:lyswhut/electron-font-manager#6d2f5ecf850c4fe34812b9394913680462ee0dae",
|
||||
"electron-log": "^4.4.8",
|
||||
"electron-store": "^8.1.0",
|
||||
"font-list": "^1.5.0",
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
- Windows、MacOS平台下的字体列表改用原生方式获取,现在Windows平台下能显示当前已安装的更多类型字体了(注:MacOS平台未测,可用性未知)
|
||||
- 移除桌面歌词窗口透明边距,在Linux下的桌面歌词可以完全拖到贴合屏幕边缘了
|
||||
- 过滤嵌入、下载的翻译、罗马音歌词时间标签,与主歌词时间不匹配的歌词将被丢弃,防止出现原歌词与翻译歌词顺序错乱的问题(#1358)
|
||||
|
||||
### 修复
|
||||
|
||||
@ -20,6 +21,7 @@
|
||||
- 修复Deepin 20下启用桌面歌词时可能会导致桌面卡死的问题(#1288)
|
||||
- 修复添加单首歌曲弹窗列表创建按钮无法取消的问题
|
||||
- 修复mg歌单搜索歌单播放数量显示问题
|
||||
- 修复tx翻译歌词解析丢失的问题(更新版本后需手动清理一次歌词缓存)
|
||||
|
||||
### 其他
|
||||
|
||||
|
||||
@ -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'])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -100,8 +100,10 @@ const parseTools = {
|
||||
return str.replace(/^[\S\s]*?LyricContent="/, '').replace(/"\/>[\S\s]*?$/, '')
|
||||
},
|
||||
getIntv(interval) {
|
||||
let [m, s, ms] = interval.split(/:|\./)
|
||||
|
||||
if (!interval.includes('.')) interval += '.0'
|
||||
let arr = interval.split(/:|\./)
|
||||
while (arr.length < 3) arr.unshift('0')
|
||||
const [m, s, ms] = arr
|
||||
return parseInt(m) * 3600000 + parseInt(s) * 1000 + parseInt(ms)
|
||||
},
|
||||
fixRlrcTimeTag(rlrc, lrc) {
|
||||
@ -123,7 +125,7 @@ const parseTools = {
|
||||
const lrcLineResult = this.rxps.lineTime2.exec(lrcLine)
|
||||
if (!lrcLineResult) continue
|
||||
const t2 = this.getIntv(lrcLineResult[1])
|
||||
if (Math.abs(t1 - t2) < 10) {
|
||||
if (Math.abs(t1 - t2) < 100) {
|
||||
newLrc.push(line.replace(this.rxps.lineTime2, lrcLineResult[0]))
|
||||
break
|
||||
}
|
||||
@ -140,21 +142,25 @@ const parseTools = {
|
||||
const tlrcLines = tlrc.split('\n')
|
||||
let lrcLines = lrc.split('\n')
|
||||
// let temp = []
|
||||
const timeTagRxp = /^\[[\d:.]+\]/
|
||||
let newLrc = []
|
||||
tlrcLines.forEach((line) => {
|
||||
const result = timeTagRxp.exec(line)
|
||||
const result = this.rxps.lineTime2.exec(line)
|
||||
if (!result) return
|
||||
const words = line.replace(timeTagRxp, '')
|
||||
const words = line.replace(this.rxps.lineTime2, '')
|
||||
if (!words.trim()) return
|
||||
const tag = result[0].replace(/\d]/, '').replace(this.rxps.timeLabelFixRxp, '')
|
||||
let time = result[1]
|
||||
if (time.includes('.')) {
|
||||
time += ''.padStart(3 - time.split('.')[1].length, '0')
|
||||
}
|
||||
const t1 = this.getIntv(time)
|
||||
|
||||
while (lrcLines.length) {
|
||||
const lrcLine = lrcLines.shift()
|
||||
const lrcLineResult = timeTagRxp.exec(lrcLine)
|
||||
const lrcLineResult = this.rxps.lineTime2.exec(lrcLine)
|
||||
if (!lrcLineResult) continue
|
||||
if (lrcLineResult[0].includes(tag)) {
|
||||
newLrc.push(line.replace(timeTagRxp, lrcLineResult[0]))
|
||||
const t2 = this.getIntv(lrcLineResult[1])
|
||||
if (Math.abs(t1 - t2) < 100) {
|
||||
newLrc.push(line.replace(this.rxps.lineTime2, lrcLineResult[0]))
|
||||
break
|
||||
}
|
||||
// temp.push(line)
|
||||
|
||||
@ -126,7 +126,10 @@ const parseTools = {
|
||||
})
|
||||
},
|
||||
getIntv(interval) {
|
||||
let [m, s, ms] = interval.split(/:|\./)
|
||||
if (!interval.includes('.')) interval += '.0'
|
||||
let arr = interval.split(/:|\./)
|
||||
while (arr.length < 3) arr.unshift('0')
|
||||
const [m, s, ms] = arr
|
||||
return parseInt(m) * 3600000 + parseInt(s) * 1000 + parseInt(ms)
|
||||
},
|
||||
fixTimeTag(lrc, targetlrc) {
|
||||
|
||||
@ -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<LX.Music.MusicFileMeta, 'lyrics'>, 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'
|
||||
|
||||
74
src/renderer/worker/download/lrcTool.ts
Normal file
74
src/renderer/worker/download/lrcTool.ts
Normal file
@ -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<string>, 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<string>()
|
||||
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
|
||||
}
|
||||
@ -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 => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user