From 669c1fe490dbbf7f0d2cf8c99f6fb8d525dc6a6a Mon Sep 17 00:00:00 2001 From: lyswhut Date: Sun, 23 Aug 2020 15:45:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E`=E6=98=BE=E7=A4=BA=E6=AD=8C?= =?UTF-8?q?=E8=AF=8D=E7=BF=BB=E8=AF=91`=E8=AE=BE=E7=BD=AE=EF=BC=8C?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=BC=80=E5=90=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- publish/changeLog.md | 1 + src/common/defaultSetting.js | 3 +- src/main/modules/winLyric/event.js | 1 + src/main/modules/winLyric/rendererEvent.js | 2 +- src/renderer-lyric/App.vue | 7 ++-- src/renderer-lyric/components/core/Lyric.vue | 24 +++++++++++-- src/renderer/components/core/Player.vue | 25 ++++++++----- src/renderer/lang/en-us/view/setting.json | 1 + src/renderer/lang/zh-cn/view/setting.json | 1 + src/renderer/lang/zh-tw/view/setting.json | 1 + src/renderer/store/modules/download.js | 10 +++--- src/renderer/store/modules/player.js | 7 ++-- src/renderer/utils/music/bd/index.js | 2 +- src/renderer/utils/music/kg/lyric.js | 5 ++- src/renderer/utils/music/kw/lyric.js | 5 ++- src/renderer/utils/music/mg/lyric.js | 10 ++++-- src/renderer/utils/music/tx/lyric.js | 8 +++-- src/renderer/utils/music/wy/lyric.js | 27 ++++++++------ src/renderer/utils/music/xm/lyric.js | 37 +++++++++++++++++--- src/renderer/views/Setting.vue | 4 +++ 20 files changed, 137 insertions(+), 44 deletions(-) diff --git a/publish/changeLog.md b/publish/changeLog.md index 61047eb8..cb2a418f 100644 --- a/publish/changeLog.md +++ b/publish/changeLog.md @@ -2,6 +2,7 @@ - 在歌单详情界面新增播放当前歌单按钮、收藏歌单按钮 - 新增`不允许将歌词窗口拖出主屏幕之外`的设置项,默认开启,在连接多个屏幕时想要拖动到其他屏幕时可关闭此设置 +- 新增`显示歌词翻译`设置,默认开启,仅支持某些平台,注:无论该设置是否开启,嵌入或下载歌词时都不会带上翻译 ### 修复 diff --git a/src/common/defaultSetting.js b/src/common/defaultSetting.js index 07909bad..37163597 100644 --- a/src/common/defaultSetting.js +++ b/src/common/defaultSetting.js @@ -3,7 +3,7 @@ const os = require('os') const { isMac } = require('./utils') const defaultSetting = { - version: '1.0.35', + version: '1.0.36', player: { togglePlayMethod: 'listLoop', highQuality: false, @@ -12,6 +12,7 @@ const defaultSetting = { isMute: false, mediaDeviceId: 'default', isMediaDeviceRemovedStopPlay: false, + isShowLyricTransition: true, }, desktopLyric: { enable: false, diff --git a/src/main/modules/winLyric/event.js b/src/main/modules/winLyric/event.js index 0c5a7935..513adc16 100644 --- a/src/main/modules/winLyric/event.js +++ b/src/main/modules/winLyric/event.js @@ -13,6 +13,7 @@ const setLrcConfig = () => { mainSend(global.modules.lyricWindow, ipcWinLyricNames.set_lyric_config, { config: desktopLyric, languageId: global.appSetting.langId, + isShowLyricTransition: global.appSetting.player.isShowLyricTransition, }) if (isLock != desktopLyric.isLock) { isLock = desktopLyric.isLock diff --git a/src/main/modules/winLyric/rendererEvent.js b/src/main/modules/winLyric/rendererEvent.js index 86dc448d..75d38dbc 100644 --- a/src/main/modules/winLyric/rendererEvent.js +++ b/src/main/modules/winLyric/rendererEvent.js @@ -24,7 +24,7 @@ mainOn(ipcWinLyricNames.set_lyric_config, (event, config) => { }) mainHandle(ipcWinLyricNames.get_lyric_config, async() => { - return { config: global.appSetting.desktopLyric, languageId: global.appSetting.langId } + return { config: global.appSetting.desktopLyric, languageId: global.appSetting.langId, isShowLyricTransition: global.appSetting.player.isShowLyricTransition } }) mainOn(ipcWinLyricNames.set_win_bounds, (event, options) => { diff --git a/src/renderer-lyric/App.vue b/src/renderer-lyric/App.vue index c66cfd67..a734428f 100644 --- a/src/renderer-lyric/App.vue +++ b/src/renderer-lyric/App.vue @@ -4,7 +4,7 @@ transition(enter-active-class="animated-fast fadeIn" leave-active-class="animated-fast fadeOut") .control-bar(v-show="!lrcConfig.isLock") core-control-bar(:lrcConfig="lrcConfig" :themes="themeList") - core-lyric(:lrcConfig="lrcConfig") + core-lyric(:lrcConfig="lrcConfig" :isShowLyricTransition="isShowLyricTransition") div.resize-left(@mousedown.self="handleMouseDown('left', $event)") div.resize-top(@mousedown.self="handleMouseDown('top', $event)") div.resize-right(@mousedown.self="handleMouseDown('right', $event)") @@ -44,6 +44,7 @@ export default { isZoomActiveLrc: true, }, }, + isShowLyricTransition: true, themeList: [ { id: 0, @@ -117,8 +118,10 @@ export default { document.removeEventListener('mouseup', this.handleMouseUp) }, methods: { - handleUpdateConfig({ config, languageId }) { + handleUpdateConfig({ config, languageId, isShowLyricTransition }) { + console.log(isShowLyricTransition) this.lrcConfig = config + this.isShowLyricTransition = isShowLyricTransition if (this.$i18n.locale !== languageId && languageId != null) this.$i18n.locale = languageId }, handleMouseDown(origin, event) { diff --git a/src/renderer-lyric/components/core/Lyric.vue b/src/renderer-lyric/components/core/Lyric.vue index 4949341a..c73bd333 100644 --- a/src/renderer-lyric/components/core/Lyric.vue +++ b/src/renderer-lyric/components/core/Lyric.vue @@ -27,6 +27,10 @@ export default { } }, }, + isShowLyricTransition: { + type: Boolean, + default: true, + }, }, data() { return { @@ -58,6 +62,10 @@ export default { lyricLines: [], isSetedLines: false, isPlay: false, + lyrics: { + lyric: '', + tlyric: '', + }, } }, computed: { @@ -112,6 +120,11 @@ export default { }, immediate: true, }, + isShowLyricTransition(n) { + console.log(n) + this.setLyric() + rendererSend(NAMES.winLyric.get_lyric_info, 'status') + }, }, created() { rendererOn(NAMES.winLyric.set_lyric_info, (event, data) => this.handleSetInfo(data)) @@ -144,7 +157,9 @@ export default { // console.log(type, data) switch (type) { case 'lyric': - window.lrc.setLyric(data) + this.lyrics.lyric = data.lrc + this.lyrics.tlyric = data.tlrc + this.setLyric() break case 'play': this.isPlay = true @@ -156,7 +171,9 @@ export default { break case 'info': // console.log('info', data) - window.lrc.setLyric(data.lyric) + this.lyrics.lyric = data.lyric + this.lyrics.tlyric = data.tlyric + this.setLyric() this.$nextTick(() => { this.lyric.line = data.line rendererSend(NAMES.winLyric.get_lyric_info, 'status') @@ -261,6 +278,9 @@ export default { close() { rendererSend(NAMES.winLyric.close) }, + setLyric() { + window.lrc.setLyric((this.isShowLyricTransition && this.lyrics.tlyric ? this.lyrics.tlyric + '\n' : '') + this.lyrics.lyric) + }, }, } diff --git a/src/renderer/components/core/Player.vue b/src/renderer/components/core/Player.vue index 1f4dea88..f2d8cd3a 100644 --- a/src/renderer/components/core/Player.vue +++ b/src/renderer/components/core/Player.vue @@ -153,6 +153,7 @@ export default { name: this.musicInfo.name, album: this.musicInfo.album, lyric: this.musicInfo.lrc, + tlyric: this.musicInfo.tlrc, isPlay: this.isPlay, line: this.lyric.line, played_time: audio.currentTime * 1000, @@ -203,6 +204,9 @@ export default { 'setting.player.mediaDeviceId'(n) { this.setMediaDevice() }, + 'setting.player.isShowLyricTransition'() { + this.setLyric() + }, async list(n, o) { if (n === o && this.musicInfo.songmid) { let index = this.listId == 'download' @@ -612,24 +616,22 @@ export default { }, setLrc(targetSong) { this.musicInfo.lrc = targetSong.lrc + this.musicInfo.tlrc = targetSong.tlrc - let lrcP = this.musicInfo.lrc + let lrcP = this.musicInfo.lrc && this.musicInfo.tlrc != null ? Promise.resolve() : this.getLrc(targetSong).then(() => { this.musicInfo.lrc = targetSong.lrc + this.musicInfo.tlrc = targetSong.tlrc }) lrcP .then(() => { - window.lrc.setLyric(this.musicInfo.lrc) - this.handleUpdateWinLyricInfo('lyric', this.musicInfo.lrc) - if (this.isPlay && (this.musicInfo.url || this.listId == 'download')) { - window.lrc.play(audio.currentTime * 1000) - this.handleUpdateWinLyricInfo('play', audio.currentTime * 1000) - } + this.setLyric() + this.handleUpdateWinLyricInfo('lyric', { lrc: this.musicInfo.lrc, tlrc: this.musicInfo.tlrc }) }) .catch(() => { - this.handleUpdateWinLyricInfo('lyric', this.musicInfo.lrc) + this.handleUpdateWinLyricInfo('lyric', { lrc: this.musicInfo.lrc, tlrc: this.musicInfo.tlrc }) this.status = this.statusText = this.$t('core.player.lyric_error') }) }, @@ -818,6 +820,13 @@ export default { info, }) }, + setLyric() { + window.lrc.setLyric((this.setting.player.isShowLyricTransition && this.musicInfo.tlrc ? this.musicInfo.tlrc + '\n' : '') + this.musicInfo.lrc) + if (this.isPlay && (this.musicInfo.url || this.listId == 'download')) { + window.lrc.play(audio.currentTime * 1000) + this.handleUpdateWinLyricInfo('play', audio.currentTime * 1000) + } + }, }, } diff --git a/src/renderer/lang/en-us/view/setting.json b/src/renderer/lang/en-us/view/setting.json index ac1f2b7c..ec8ab69a 100644 --- a/src/renderer/lang/en-us/view/setting.json +++ b/src/renderer/lang/en-us/view/setting.json @@ -35,6 +35,7 @@ "play_toggle_random": "Playlist shuffle", "play_toggle_list": "Play in order", "play_toggle_single_loop": "Single repeat", + "play_lyric_transition": "Show lyrics translation", "play_quality_title": "The 320k quality is preferred for playing", "play_quality": "Prefer High Quality 320k", "play_task_bar_title": "Show playing progress on the taskbar", diff --git a/src/renderer/lang/zh-cn/view/setting.json b/src/renderer/lang/zh-cn/view/setting.json index 844c3f6b..d84c9073 100644 --- a/src/renderer/lang/zh-cn/view/setting.json +++ b/src/renderer/lang/zh-cn/view/setting.json @@ -35,6 +35,7 @@ "play_toggle_random": "列表随机", "play_toggle_list": "顺序播放", "play_toggle_single_loop": "单曲循环", + "play_lyric_transition": "显示歌词翻译", "play_quality_title": "启用时将优先播放320K品质的歌曲", "play_quality": "优先播放高品质音乐", "play_task_bar_title": "在任务栏上显示当前歌曲播放进度", diff --git a/src/renderer/lang/zh-tw/view/setting.json b/src/renderer/lang/zh-tw/view/setting.json index f46798d9..9701fa8e 100644 --- a/src/renderer/lang/zh-tw/view/setting.json +++ b/src/renderer/lang/zh-tw/view/setting.json @@ -34,6 +34,7 @@ "play_toggle_random": "列表隨機", "play_toggle_list": "順序播放", "play_toggle_single_loop": "單曲循環", + "play_lyric_transition": "顯示歌詞翻譯", "play_quality_title": "啟用時將優先播放320K品質的歌曲", "play_quality": "優先播放高品質音樂", "play_task_bar_title": "在任務欄上顯示當前歌曲播放進度", diff --git a/src/renderer/store/modules/download.js b/src/renderer/store/modules/download.js index 8166686d..036a9f87 100644 --- a/src/renderer/store/modules/download.js +++ b/src/renderer/store/modules/download.js @@ -177,7 +177,7 @@ const saveMeta = (downloadInfo, filePath, isEmbedPic, isEmbedLyric) => { : Promise.resolve(), isEmbedLyric ? downloadInfo.musicInfo.lrc - ? Promise.resolve(downloadInfo.musicInfo.lrc) + ? Promise.resolve({ lyric: downloadInfo.musicInfo.lrc, tlyric: downloadInfo.musicInfo.tlrc || '' }) : music[downloadInfo.musicInfo.source].getLyric(downloadInfo.musicInfo).promise.catch(err => { console.log(err) return null @@ -190,7 +190,7 @@ const saveMeta = (downloadInfo, filePath, isEmbedPic, isEmbedLyric) => { artist: downloadInfo.musicInfo.singer, album: downloadInfo.musicInfo.albumName, APIC: imgUrl, - lyrics, + lyrics: lyrics.lyric, }) }) } @@ -202,10 +202,10 @@ const saveMeta = (downloadInfo, filePath, isEmbedPic, isEmbedLyric) => { */ const downloadLyric = (downloadInfo, filePath) => { const promise = downloadInfo.musicInfo.lrc - ? Promise.resolve(downloadInfo.musicInfo.lrc) + ? Promise.resolve({ lyric: downloadInfo.musicInfo.lrc, tlyric: downloadInfo.musicInfo.tlrc || '' }) : music[downloadInfo.musicInfo.source].getLyric(downloadInfo.musicInfo).promise - promise.then(lrc => { - if (lrc) saveLrc(filePath.replace(/(mp3|flac|ape|wav)$/, 'lrc'), lrc) + promise.then(lrcs => { + if (lrcs.lyric) saveLrc(filePath.replace(/(mp3|flac|ape|wav)$/, 'lrc'), lrcs.lyric) }) } diff --git a/src/renderer/store/modules/player.js b/src/renderer/store/modules/player.js index 84da8ded..16fbc8a0 100644 --- a/src/renderer/store/modules/player.js +++ b/src/renderer/store/modules/player.js @@ -60,9 +60,9 @@ const actions = { getLrc({ commit, state }, musicInfo) { if (lrcRequest && lrcRequest.cancelHttp) lrcRequest.cancelHttp() lrcRequest = music[musicInfo.source].getLyric(musicInfo) - return lrcRequest.promise.then(lrc => { + return lrcRequest.promise.then(({ lyric, tlyric }) => { lrcRequest = null - commit('setLrc', { musicInfo, lrc }) + commit('setLrc', { musicInfo, lyric, tlyric }) }).catch(err => { lrcRequest = null return Promise.reject(err) @@ -80,7 +80,8 @@ const mutations = { datas.musicInfo.img = datas.url }, setLrc(state, datas) { - datas.musicInfo.lrc = datas.lrc + datas.musicInfo.lrc = datas.lyric + datas.musicInfo.tlrc = datas.tlyric }, setList(state, { list, index }) { state.listInfo = list diff --git a/src/renderer/utils/music/bd/index.js b/src/renderer/utils/music/bd/index.js index c83fe67e..de780c90 100644 --- a/src/renderer/utils/music/bd/index.js +++ b/src/renderer/utils/music/bd/index.js @@ -21,7 +21,7 @@ const bd = { }, getLyric(songInfo) { const requestObj = this.getMusicInfo(songInfo) - requestObj.promise = requestObj.promise.then(info => httpFetch(info.lrclink).promise.then(resp => resp.body)) + requestObj.promise = requestObj.promise.then(info => httpFetch(info.lrclink).promise.then(resp => ({ lyric: resp.body, tlyric: '' }))) return requestObj }, // getLyric(songInfo) { diff --git a/src/renderer/utils/music/kg/lyric.js b/src/renderer/utils/music/kg/lyric.js index dab3fc00..a6574791 100644 --- a/src/renderer/utils/music/kg/lyric.js +++ b/src/renderer/utils/music/kg/lyric.js @@ -26,7 +26,10 @@ export default { requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj) return tryRequestObj.promise } - return body + return { + lyric: body, + tlyric: '', + } }) return requestObj }, diff --git a/src/renderer/utils/music/kw/lyric.js b/src/renderer/utils/music/kw/lyric.js index 29f6a1d7..91fd52f3 100644 --- a/src/renderer/utils/music/kw/lyric.js +++ b/src/renderer/utils/music/kw/lyric.js @@ -17,7 +17,10 @@ export default { return requestObj.promise.then(({ statusCode, body, raw }) => { if (statusCode != 200) return Promise.reject(new Error(JSON.stringify(body))) return decodeLyric({ lrcBase64: raw.toString('base64'), isGetLyricx }).then(base64Data => { - return Buffer.from(base64Data, 'base64').toString() + return { + lyric: Buffer.from(base64Data, 'base64').toString(), + tlyric: '', + } }) }) }) diff --git a/src/renderer/utils/music/mg/lyric.js b/src/renderer/utils/music/mg/lyric.js index 330aa10d..cd6a49ef 100644 --- a/src/renderer/utils/music/mg/lyric.js +++ b/src/renderer/utils/music/mg/lyric.js @@ -12,7 +12,10 @@ export default { requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj) return tryRequestObj.promise } - return body + return { + lyric: body, + tlyric: '', + } }) return requestObj } else { @@ -28,7 +31,10 @@ export default { requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj) return tryRequestObj.promise } - return body.lyric + return { + lyric: body.lyric, + tlyric: '', + } }) return requestObj } diff --git a/src/renderer/utils/music/tx/lyric.js b/src/renderer/utils/music/tx/lyric.js index d86233ba..a371a6e7 100644 --- a/src/renderer/utils/music/tx/lyric.js +++ b/src/renderer/utils/music/tx/lyric.js @@ -6,13 +6,17 @@ export default { matchLrc: /.+"lyric":"([\w=+/]*)".+/, }, getLyric(songmid) { - const requestObj = httpFetch(`https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg?songmid=${songmid}&g_tk=2001461048&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8&platform=yqq`, { + const requestObj = httpFetch(`https://c.y.qq.com/lyric/fcgi-bin/fcg_query_lyric_new.fcg?songmid=${songmid}&g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&platform=yqq`, { headers: { Referer: 'https://y.qq.com/portal/player.html', }, }) requestObj.promise = requestObj.promise.then(({ body }) => { - return decodeName(b64DecodeUnicode(body.replace(this.regexps.matchLrc, '$1'))) + if (body.code != 0) return Promise.reject(new Error('获取歌词失败')) + return { + lyric: decodeName(b64DecodeUnicode(body.lyric)), + tlyric: decodeName(b64DecodeUnicode(body.trans)), + } }) return requestObj }, diff --git a/src/renderer/utils/music/wy/lyric.js b/src/renderer/utils/music/wy/lyric.js index 819b3931..6ae95d34 100644 --- a/src/renderer/utils/music/wy/lyric.js +++ b/src/renderer/utils/music/wy/lyric.js @@ -1,20 +1,27 @@ import { httpFetch } from '../../request' -import { weapi } from './utils/crypto' +import { linuxapi } from './utils/crypto' export default songmid => { - const requestObj = httpFetch('http://music.163.com/weapi/song/lyric?csrf_token=', { + const requestObj = httpFetch('https://music.163.com/api/linux/forward', { method: 'post', - headers: { - 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36', - Referer: 'https://music.163.com/song?id=' + songmid, - origin: 'https://music.163.com', - }, - form: weapi({ id: songmid, lv: -1, tv: -1, csrf_token: '' }), + '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', + params: { + id: songmid, + lv: -1, + kv: -1, + tv: -1, + }, + }), }) requestObj.promise = requestObj.promise.then(({ body }) => { - // console.log(body) if (body.code !== 200) return Promise.reject('获取歌词失败') - return body.lrc.lyric + return { + lyric: body.lrc.lyric, + tlyric: body.tlyric.lyric, + } }) return requestObj } diff --git a/src/renderer/utils/music/xm/lyric.js b/src/renderer/utils/music/xm/lyric.js index 4f83c57f..d1e85d79 100644 --- a/src/renderer/utils/music/xm/lyric.js +++ b/src/renderer/utils/music/xm/lyric.js @@ -1,6 +1,23 @@ import { httpGet, httpFetch } from '../../request' import { xmRequest } from './util' +const parseLyric = str => { + str = str.replace(/(?:<\d+>|\r)/g, '') + let tlyric = [] + let lyric = str.replace(/\[[\d:.]+\].*?\n\[x-trans\].*/g, s => { + // console.log(s) + let [lrc, tlrc] = s.split('\n') + tlrc = tlrc.replace('[x-trans]', lrc.replace(/^(\[[\d:.]+\]).*$/, '$1')) + tlyric.push(tlrc) + return lrc + }) + tlyric = tlyric.join('\n') + return { + lyric, + tlyric, + } +} + export default { failTime: 0, expireTime: 60 * 1000 * 1000, @@ -13,7 +30,10 @@ export default { requestObj.cancelHttp = tryRequestObj.cancelHttp.bind(tryRequestObj) return tryRequestObj.promise } - return body + return url.endsWith('.xtrc') ? parseLyric(body) : { + lyric: body, + tlyric: '', + } }) return requestObj }, @@ -27,7 +47,10 @@ export default { }, }, function(err, resp, body) { if (err || resp.statusCode !== 200) return this.getLyricFile(url, ++retryNum).then(resolve).catch(reject) - return resolve(body) + return resolve(url.endsWith('.xtrc') ? parseLyric(body) : { + lyric: body, + tlyric: '', + }) }) }) }, @@ -47,8 +70,12 @@ export default { return tryRequestObj.promise } if (!body.result.data.lyrics.length) return Promise.reject(new Error('未找到歌词')) - let lrc = body.result.data.lyrics.find(lyric => /\.lrc$/.test(lyric.lyricUrl)) - return lrc ? lrc.content : Promise.reject(new Error('未找到歌词')) + let lrc = body.result.data.lyrics.find(lyric => /\.(trc|lrc)$/.test(lyric.lyricUrl)) + return lrc + ? lrc.lyricUrl.endsWith('.trc') + ? parseLyric(lrc.content) + : { lyric: lrc.content, tlyric: '' } + : Promise.reject(new Error('未找到歌词')) }) return requestObj }, @@ -74,7 +101,7 @@ export default { return requestObj }, getLyric(songInfo) { - if (songInfo.lrcUrl && /\.lrc$/.test(songInfo.lrcUrl)) return this.getLyricFile_1(songInfo.lrcUrl) + if (songInfo.lrcUrl && /\.(xtrc|lrc)$/.test(songInfo.lrcUrl)) return this.getLyricFile_1(songInfo.lrcUrl) return Date.now() - this.failTime > this.expireTime ? this.getLyricUrl_1(songInfo) : this.getLyricUrl_2(songInfo) }, } diff --git a/src/renderer/views/Setting.vue b/src/renderer/views/Setting.vue index b135728a..8a12effa 100644 --- a/src/renderer/views/Setting.vue +++ b/src/renderer/views/Setting.vue @@ -58,6 +58,10 @@ div.scroll(:class="$style.setting") div material-checkbox(:id="`setting_player_togglePlay_${item.value}`" :class="$style.gapLeft" :value="item.value" :key="item.value" v-model="current_setting.player.togglePlayMethod" v-for="item in togglePlayMethods" :label="item.name") + dd + h3 {{$t('view.setting.play_lyric_transition')}} + div + material-checkbox(id="setting_player_lyric_transition" v-model="current_setting.player.isShowLyricTransition" :label="$t('view.setting.is_show')") dd(:title="$t('view.setting.play_quality_title')") h3 {{$t('view.setting.play_quality')}} div