新增设置-播放设置-显示歌词罗马音

This commit is contained in:
lyswhut
2022-05-10 11:12:14 +08:00
parent c65802c1c3
commit a5ec36bf89
24 changed files with 156 additions and 100 deletions
@@ -27,8 +27,10 @@
<div :class="[$style.lyricSelectContent, 'select', 'scroll', 'lyricSelectContent']" v-if="isShowLrcSelectContent" @contextmenu="handleCopySelectText">
<div v-for="(info, index) in lyric.lines" :key="index" :class="[$style.lyricSelectline, { [$style.lrcActive]: lyric.line == index }]">
<span>{{info.text}}</span>
<br v-if="info.translation"/>
<span :class="$style.lyricSelectlineTransition">{{info.translation}}</span>
<template v-for="(lrc, index) in info.extendedLyrics" :key="index">
<br />
<span :class="$style.lyricSelectlineExtended">{{lrc}}</span>
</template>
</div>
</div>
</transition>
@@ -77,6 +79,7 @@ export default {
const lyricInfo = reactive({
lyric: '',
tlyric: '',
rlyric: '',
lxlyric: '',
rawlyric: '',
musicInfo: null,
@@ -84,6 +87,7 @@ export default {
const updateMusicInfo = () => {
lyricInfo.lyric = playerMusicInfo.lrc
lyricInfo.tlyric = playerMusicInfo.tlrc
lyricInfo.rlyric = playerMusicInfo.rlrc
lyricInfo.lxlyric = playerMusicInfo.lxlrc
lyricInfo.rawlyric = playerMusicInfo.rawlrc
lyricInfo.musicInfo = musicInfoItem.value
@@ -94,10 +98,11 @@ export default {
lyricMenuXY.y = event.pageY
lyricMenuVisible.value = true
}
const handleUpdateLyric = ({ lyric, tlyric, lxlyric, offset }) => {
const handleUpdateLyric = ({ lyric, tlyric, rlyric, lxlyric, offset }) => {
setMusicInfo({
lrc: lyric,
tlrc: tlyric,
rlrc: rlyric,
lxlrc: lxlyric,
})
// console.log(offset)
@@ -189,7 +194,7 @@ export default {
transition: @transition-theme;
transition-property: padding;
.translation {
.extended {
transition: @transition-theme !important;
transition-property: font-size, color;
font-size: .9em;
@@ -205,7 +210,7 @@ export default {
.line {
color: @color-theme;
}
.translation {
.extended {
color: @color-theme;
}
// span {
@@ -243,7 +248,7 @@ export default {
:global {
.lrc-content {
&.active {
.translation {
.extended {
font-size: .94em;
}
span {
@@ -316,7 +321,7 @@ export default {
transition-property: color, font-size;
line-height: 1.3;
}
.lyricSelectlineTransition {
.lyricSelectlineExtended {
font-size: 14px;
}
.lrc-active {
@@ -336,7 +341,7 @@ each(@themes, {
color: ~'@{color-@{value}-player-detail-lyric}';
&.active {
.translation {
.extended {
color: ~'@{color-@{value}-player-detail-lyric-active}';
}
.line {
@@ -114,15 +114,18 @@ export default {
const updateLyric = offset => {
let lyric = props.lyricInfo.lyric
let tlyric = props.lyricInfo.tlyric
let rlyric = props.lyricInfo.rlyric
let lxlyric = props.lyricInfo.lxlyric
if (offsetTagRxp.test(lyric)) {
lyric = lyric.replace(offsetTagAllRxp, `[offset:${offset}]`)
if (tlyric) tlyric = tlyric.replace(offsetTagAllRxp, `[offset:${offset}]`)
if (lxlyric) lxlyric = lxlyric.replace(offsetTagAllRxp, `[offset:${offset}]`)
if (rlyric) rlyric = rlyric.replace(offsetTagAllRxp, `[offset:${offset}]`)
} else {
lyric = `[offset:${offset}]\n` + lyric
if (tlyric) tlyric = `[offset:${offset}]\n` + tlyric
if (lxlyric) lxlyric = `[offset:${offset}]\n` + lxlyric
if (rlyric) rlyric = `[offset:${offset}]\n` + rlyric
}
if (offset == originOffset.value) {
@@ -131,6 +134,7 @@ export default {
saveLyric(props.lyricInfo.musicInfo, {
lyric,
tlyric,
rlyric,
lxlyric,
})
}
@@ -138,6 +142,7 @@ export default {
emit('updateLyric', {
lyric,
tlyric,
rlyric,
lxlyric,
offset,
})
+1
View File
@@ -6,6 +6,7 @@ export const musicInfo = window.musicInfo = reactive({
img: null,
lrc: null,
tlrc: null,
rlrc: null,
lxlrc: null,
rawlrc: null,
url: null,
@@ -43,11 +43,14 @@ export default ({ setting }) => {
const setLyric = () => {
if (!musicInfo.songmid) return
const extendedLyrics = []
if (setting.value.player.isShowLyricTranslation && musicInfo.tlrc) extendedLyrics.push(musicInfo.tlrc)
if (setting.value.player.isShowLyricRoma && musicInfo.rlrc) extendedLyrics.push(musicInfo.rlrc)
lrc.setLyric(
setting.value.player.isPlayLxlrc && musicInfo.lxlrc ? musicInfo.lxlrc : musicInfo.lrc,
setting.value.player.isShowLyricTranslation && musicInfo.tlrc ? musicInfo.tlrc : '',
extendedLyrics,
)
setDesktopLyricInfo('lyric', { lrc: musicInfo.lrc, tlrc: musicInfo.tlrc, lxlrc: musicInfo.lxlrc })
setDesktopLyricInfo('lyric', { lrc: musicInfo.lrc, tlrc: musicInfo.tlrc, rlrc: musicInfo.rlrc, lxlrc: musicInfo.lxlrc })
if (isPlay.value && (musicInfo.url || playMusicInfo.listId == 'download')) {
setTimeout(() => {
@@ -99,6 +102,7 @@ export default ({ setting }) => {
album: musicInfo.album,
lrc: musicInfo.lrc,
tlrc: musicInfo.tlrc,
rlrc: musicInfo.rlrc,
lxlrc: musicInfo.lxlrc,
isPlay: isPlay.value,
line: lyric.line,
@@ -135,20 +135,22 @@ export default ({ setting }) => {
}
}
const setLrc = (targetSong) => {
getLrc(targetSong).then(({ lyric, tlyric, lxlyric, rawInfo }) => {
getLrc(targetSong).then(({ lyric, tlyric, rlyric, lxlyric, rawInfo }) => {
if (targetSong.songmid !== musicInfo.songmid) return
return (
setting.value.player.isS2t
? Promise.all([
lyric ? langS2T(lyric) : Promise.resolve(''),
tlyric ? langS2T(tlyric) : Promise.resolve(''),
rlyric ? langS2T(rlyric) : Promise.resolve(''),
lxlyric ? langS2T(lxlyric) : Promise.resolve(''),
])
: Promise.resolve([lyric, tlyric, lxlyric])
).then(([lyric, tlyric, lxlyric]) => {
: Promise.resolve([lyric, tlyric, rlyric, lxlyric])
).then(([lyric, tlyric, rlyric, lxlyric]) => {
setMusicInfo({
lrc: lyric,
tlrc: tlyric,
rlrc: rlyric,
lxlrc: lxlyric,
rawlrc: rawInfo.lyric,
})
@@ -213,6 +215,7 @@ export default ({ setting }) => {
img: null,
lrc: null,
tlrc: null,
rlrc: null,
lxlrc: null,
rawlrc: null,
url: null,
+4 -4
View File
@@ -185,14 +185,14 @@ const getLyric = function(musicInfo, isUseOtherSource, isS2t) {
return getLyricFromStorage(musicInfo).then(lrcInfo => {
return (
existTimeExp.test(lrcInfo.lyric)
? Promise.resolve({ lyric: lrcInfo.lyric, tlyric: lrcInfo.tlyric || '' })
? Promise.resolve({ lyric: lrcInfo.lyric, tlyric: lrcInfo.tlyric || '', rlyric: lrcInfo.rlyric || '', lxlyric: lrcInfo.lxlyric || '' })
: (
isUseOtherSource
? handleGetLyric.call(this, musicInfo)
: music[musicInfo.source].getLyric(musicInfo).promise
).then(({ lyric, tlyric, lxlyric }) => {
setLyric(musicInfo, { lyric, tlyric, lxlyric })
return { lyric, tlyric, lxlyric }
).then(({ lyric, tlyric, rlyric, lxlyric }) => {
setLyric(musicInfo, { lyric, tlyric, rlyric, lxlyric })
return { lyric, tlyric, rlyric, lxlyric }
}).catch(err => {
console.log(err)
return null
+7 -4
View File
@@ -223,7 +223,7 @@ const actions = {
},
async getLrc({ commit, state }, musicInfo) {
const lrcInfo = await getStoreLyric(musicInfo)
// lrcInfo = {}
// let lrcInfo = {}
// if (lrcRequest && lrcRequest.cancelHttp) lrcRequest.cancelHttp()
if (existTimeExp.test(lrcInfo.lyric) && lrcInfo.tlyric != null) {
// if (musicInfo.lrc.startsWith('\ufeff[id:$00000000]')) {
@@ -242,14 +242,16 @@ const actions = {
default:
return buildLyricInfo(lrcInfo, musicInfo)
}
} else if (lrcInfo.rlyric == null) {
if (musicInfo.source != 'wy') return buildLyricInfo(lrcInfo, musicInfo)
} else return buildLyricInfo(lrcInfo, musicInfo)
}
// lrcRequest = music[musicInfo.source].getLyric(musicInfo)
return getLyric.call(this, musicInfo).then(({ lyric, tlyric, lxlyric }) => {
return getLyric.call(this, musicInfo).then(({ lyric, tlyric, rlyric, lxlyric }) => {
// lrcRequest = null
commit('setLrc', { musicInfo, lyric, tlyric, lxlyric })
return buildLyricInfo({ lyric, tlyric, lxlyric }, musicInfo)
commit('setLrc', { musicInfo, lyric, tlyric, rlyric, lxlyric })
return buildLyricInfo({ lyric, tlyric, rlyric, lxlyric }, musicInfo)
}).catch(err => {
// lrcRequest = null
return Promise.reject(err)
@@ -443,6 +445,7 @@ const mutations = {
setLyric(datas.musicInfo, {
lyric: datas.lyric,
tlyric: datas.tlyric,
rlyric: datas.rlyric,
lxlyric: datas.lxlyric,
})
},
+4 -4
View File
@@ -514,13 +514,13 @@ export const parseUrlParams = str => {
export const getLyric = musicInfo => rendererInvoke(NAMES.mainWindow.get_lyric, `${musicInfo.source}_${musicInfo.songmid}`)
export const getLyricRaw = musicInfo => rendererInvoke(NAMES.mainWindow.get_lyric_raw, `${musicInfo.source}_${musicInfo.songmid}`)
export const setLyric = (musicInfo, { lyric, tlyric, lxlyric }) => rendererSend(NAMES.mainWindow.save_lyric_raw, {
export const setLyric = (musicInfo, { lyric, tlyric, rlyric, lxlyric }) => rendererSend(NAMES.mainWindow.save_lyric_raw, {
id: `${musicInfo.source}_${musicInfo.songmid}`,
lyrics: { lyric, tlyric, lxlyric },
lyrics: { lyric, tlyric, rlyric, lxlyric },
})
export const setLyricEdited = (musicInfo, { lyric, tlyric, lxlyric }) => rendererSend(NAMES.mainWindow.save_lyric_edited, {
export const setLyricEdited = (musicInfo, { lyric, tlyric, rlyric, lxlyric }) => rendererSend(NAMES.mainWindow.save_lyric_edited, {
id: `${musicInfo.source}_${musicInfo.songmid}`,
lyrics: { lyric, tlyric, lxlyric },
lyrics: { lyric, tlyric, rlyric, lxlyric },
})
export const removeLyricEdited = musicInfo => rendererSend(NAMES.mainWindow.remove_lyric_edited, `${musicInfo.source}_${musicInfo.songmid}`)
@@ -20,14 +20,14 @@ const createAnimation = (dom, duration) => new window.Animation(new window.Keyfr
// https://jsfiddle.net/ceqpnbky/1/
module.exports = class FontPlayer {
constructor({ time = 0, lyric = '', translationLyric = '', lineClassName = '', fontClassName = '', translationClassName = '', lineModeClassName = '', shadowContent = false, shadowClassName = '' }) {
constructor({ time = 0, lyric = '', extendedLyrics = '', lineClassName = '', fontClassName = '', extendedLrcClassName = '', lineModeClassName = '', shadowContent = false, shadowClassName = '' }) {
this.time = time
this.lyric = lyric
this.translationLyric = translationLyric
this.extendedLyrics = extendedLyrics
this.lineClassName = lineClassName
this.fontClassName = fontClassName
this.translationClassName = translationClassName
this.extendedLrcClassName = extendedLrcClassName
this.lineModeClassName = lineModeClassName
this.shadowContent = shadowContent
this.shadowClassName = shadowClassName
@@ -40,8 +40,8 @@ module.exports = class FontPlayer {
this.fontContent = null
this.timeoutTools = new TimeoutTools()
this.waitPlayTimeout = new TimeoutTools()
this.timeoutTools = new TimeoutTools(80)
this.waitPlayTimeout = new TimeoutTools(80)
this._init()
}
@@ -64,20 +64,20 @@ module.exports = class FontPlayer {
this.fontContent.appendChild(this.fontShadowContent)
}
this.lineContent.appendChild(this.fontContent)
if (this.translationLyric) {
this.translationContent = document.createElement('div')
this.translationContent.style = 'position:relative;display:inline-block;'
this.translationContent.className = this.translationClassName
this.translationContent.textContent = this.translationLyric
for (const lrc of this.extendedLyrics) {
const extendedLrcContent = document.createElement('div')
extendedLrcContent.style = 'position:relative;display:inline-block;'
extendedLrcContent.className = this.extendedLrcClassName
extendedLrcContent.textContent = lrc
this.lineContent.appendChild(document.createElement('br'))
this.lineContent.appendChild(this.translationContent)
this.lineContent.appendChild(extendedLrcContent)
if (this.shadowContent) {
this.translationShadowContent = document.createElement('div')
this.translationShadowContent.style = 'position:absolute;top:0;left:0;width:100%;z-index:-1;'
this.translationShadowContent.className = this.shadowClassName
this.translationShadowContent.textContent = this.translationLyric
this.translationContent.appendChild(this.translationShadowContent)
const extendedLrcShadowContent = document.createElement('div')
extendedLrcShadowContent.style = 'position:absolute;top:0;left:0;width:100%;z-index:-1;'
extendedLrcShadowContent.className = this.shadowClassName
extendedLrcShadowContent.textContent = lrc
extendedLrcContent.appendChild(extendedLrcShadowContent)
}
}
this._parseLyric()
+13 -13
View File
@@ -6,11 +6,11 @@ const fontTimeExp = /<(\d+),(\d+)>/g
module.exports = class Lyric {
constructor({
lyric = '',
translationLyric = '',
extendedLyrics = [],
offset = 0,
lineClassName = '',
fontClassName = 'font',
translationClassName = 'translation',
extendedLrcClassName = 'extended',
activeLineClassName = 'active',
lineModeClassName = 'line',
shadowClassName = '',
@@ -19,14 +19,14 @@ module.exports = class Lyric {
onSetLyric = function() { },
}) {
this.lyric = lyric
this.translationLyric = translationLyric
this.extendedLyrics = extendedLyrics
this.offset = offset
this.onPlay = onPlay
this.onSetLyric = onSetLyric
this.lineClassName = lineClassName
this.fontClassName = fontClassName
this.translationClassName = translationClassName
this.extendedLrcClassName = extendedLrcClassName
this.activeLineClassName = activeLineClassName
this.lineModeClassName = lineModeClassName
this.shadowClassName = shadowClassName
@@ -46,7 +46,7 @@ module.exports = class Lyric {
this.playingLineNum = -1
this.isLineMode = false
this.linePlayer.setLyric(this.lyric, this.translationLyric)
this.linePlayer.setLyric(this.lyric, this.extendedLyrics)
}
_handleLinePlayerOnPlay = (num, text, curTime) => {
@@ -104,10 +104,10 @@ module.exports = class Lyric {
const fontPlayer = new FontPlayer({
time: line.time,
lyric: line.text,
translationLyric: line.translation,
extendedLyrics: line.extendedLyrics,
lineClassName: this.lineClassName,
fontClassName: this.fontClassName,
translationClassName: this.translationClassName,
extendedLrcClassName: this.extendedLrcClassName,
lineModeClassName: this.lineModeClassName,
shadowClassName: this.shadowClassName,
shadowContent: this.shadowContent,
@@ -117,7 +117,7 @@ module.exports = class Lyric {
return {
text: line.text,
time: line.time,
translation: line.translation,
extendedLyrics: line.extendedLyrics,
dom_line: fontPlayer.lineContent,
}
})
@@ -126,10 +126,10 @@ module.exports = class Lyric {
const fontPlayer = new FontPlayer({
time: line.time,
lyric: line.text,
translationLyric: line.translation,
extendedLyrics: line.extendedLyrics,
lineClassName: this.lineClassName,
fontClassName: this.fontClassName,
translationClassName: this.translationClassName,
extendedLrcClassName: this.extendedLrcClassName,
shadowClassName: this.shadowClassName,
shadowContent: this.shadowContent,
})
@@ -138,7 +138,7 @@ module.exports = class Lyric {
return {
text: line.text.replace(fontTimeExp, ''),
time: line.time,
translation: line.translation,
extendedLyrics: line.extendedLyrics,
dom_line: fontPlayer.lineContent,
}
})
@@ -162,9 +162,9 @@ module.exports = class Lyric {
if (this.playingLineNum > -1) this._lineFonts[this.playingLineNum].pause()
}
setLyric(lyric, translationLyric) {
setLyric(lyric, extendedLyrics) {
this.lyric = lyric
this.translationLyric = translationLyric
this.extendedLyrics = extendedLyrics
this._init()
}
}
@@ -11,11 +11,26 @@ const tagRegMap = {
const timeoutTools = new TimeoutTools()
const parseExtendedLyric = (lrcLinesMap, extendedLyric) => {
const extendedLines = extendedLyric.split(/\r\n|\n|\r/)
for (let i = 0; i < extendedLines.length; i++) {
const line = extendedLines[i].trim()
let result = timeExp.exec(line)
if (result) {
const text = line.replace(timeExp, '').trim()
if (text) {
const timeStr = RegExp.$1.replace(/(\.\d\d)0$/, '$1')
const targetLine = lrcLinesMap[timeStr]
if (targetLine) targetLine.extendedLyrics.push(text)
}
}
}
}
module.exports = class LinePlayer {
constructor({ offset = 0, onPlay = function() { }, onSetLyric = function() { } } = {}) {
this.tags = {}
this.lines = null
this.translationLines = null
this.onPlay = onPlay
this.onSetLyric = onSetLyric
this.isPlay = false
@@ -28,7 +43,7 @@ module.exports = class LinePlayer {
_init() {
if (this.lyric == null) this.lyric = ''
if (this.translationLyric == null) this.translationLyric = ''
if (this.extendedLyrics == null) this.extendedLyrics = []
this._initTag()
this._initLines()
this.onSetLyric(this.lines, this.tags.offset + this.offset)
@@ -50,17 +65,15 @@ module.exports = class LinePlayer {
_initLines() {
this.lines = []
this.translationLines = []
const lines = this.lyric.split(/\r\n|\r|\n/)
const linesMap = {}
// const translationLines = this.translationLyric.split('\n')
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim()
let result = timeExp.exec(line)
if (result) {
const text = line.replace(timeExp, '').trim()
if (text) {
const timeStr = RegExp.$1
const timeStr = RegExp.$1.replace(/(\.\d\d)0$/, '$1')
const timeArr = timeStr.split(':')
if (timeArr.length < 3) timeArr.unshift(0)
if (timeArr[2].indexOf('.') > -1) {
@@ -70,24 +83,13 @@ module.exports = class LinePlayer {
linesMap[timeStr] = {
time: parseInt(timeArr[0]) * 60 * 60 * 1000 + parseInt(timeArr[1]) * 60 * 1000 + parseInt(timeArr[2]) * 1000 + parseInt(timeArr[3] || 0),
text,
extendedLyrics: [],
}
}
}
}
const translationLines = this.translationLyric.split('\n')
for (let i = 0; i < translationLines.length; i++) {
const line = translationLines[i].trim()
let result = timeExp.exec(line)
if (result) {
const text = line.replace(timeExp, '').trim()
if (text) {
const timeStr = RegExp.$1
const targetLine = linesMap[timeStr]
if (targetLine) targetLine.translation = text
}
}
}
for (const lrc of this.extendedLyrics) parseExtendedLyric(linesMap, lrc)
this.lines = Object.values(linesMap)
this.lines.sort((a, b) => {
return a.time - b.time
@@ -172,11 +174,11 @@ module.exports = class LinePlayer {
}
}
setLyric(lyric, translationLyric) {
// console.log(translationLyric)
setLyric(lyric, extendedLyrics) {
// console.log(extendedLyrics)
if (this.isPlay) this.pause()
this.lyric = lyric
this.translationLyric = translationLyric
this.extendedLyrics = extendedLyrics
this._init()
}
}
@@ -2,12 +2,12 @@
const getNow = exports.getNow = typeof performance == 'object' && window.performance.now ? window.performance.now.bind(window.performance) : Date.now.bind(Date)
exports.TimeoutTools = class TimeoutTools {
constructor() {
constructor(thresholdTime = 200) {
this.invokeTime = 0
this.animationFrameId = null
this.timeoutId = null
this.callback = null
this.thresholdTime = 200
this.thresholdTime = thresholdTime
}
run() {
+7 -3
View File
@@ -34,26 +34,30 @@ import { linuxapi } from './utils/crypto'
// return lxlyric.trim()
// }
// https://github.com/Binaryify/NeteaseCloudMusicApi/pull/1523/files
export default songmid => {
const requestObj = httpFetch('https://music.163.com/api/linux/forward', {
method: 'post',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36',
form: linuxapi({
method: 'POST',
url: 'https://music.163.com/api/song/lyric',
url: 'https://music.163.com/api/song/lyric?_nmclfl=1',
params: {
id: songmid,
lv: -1,
kv: -1,
tv: -1,
lv: -1,
rv: -1,
kv: -1,
},
}),
})
requestObj.promise = requestObj.promise.then(({ body }) => {
if (body.code !== 200 || !body?.lrc?.lyric) return Promise.reject(new Error('Get lyric failed'))
// console.log(body)
return {
lyric: body.lrc.lyric,
tlyric: body.tlyric?.lyric ?? '',
rlyric: body.romalrc?.lyric ?? '',
// lxlyric: parseLyric(body.klyric.lyric),
}
})
@@ -5,6 +5,8 @@ dd
base-checkbox(id="setting_player_save_play_time" v-model="currentStting.player.isSavePlayTime" :label="$t('setting__play_save_play_time')")
.gap-top
base-checkbox(id="setting_player_lyric_transition" v-model="currentStting.player.isShowLyricTranslation" :label="$t('setting__play_lyric_transition')")
.gap-top
base-checkbox(id="setting_player_lyric_roma" v-model="currentStting.player.isShowLyricRoma" :label="$t('setting__play_lyric_roma')")
.gap-top
base-checkbox(id="setting_player_auto_skip_on_error" v-model="currentStting.player.autoSkipOnError" :label="$t('setting__play_auto_skip_on_error')")
.gap-top
+1
View File
@@ -10,6 +10,7 @@ export const currentStting = ref({
mediaDeviceId: 'default',
isMediaDeviceRemovedStopPlay: false,
isShowLyricTranslation: false,
isShowLyricRoma: false,
isS2t: false, // 是否将歌词从简体转换为繁体
isPlayLxlrc: true,
isSavePlayTime: false,