开放API 添加歌词翻译字段
parent
c54b38a068
commit
32f47aaa34
|
@ -5,3 +5,11 @@
|
||||||
### 变更
|
### 变更
|
||||||
|
|
||||||
- 设置-播放设置-优先播放320k音质选项改为“优先播放的音质”,允许选择更高优先播放的音质,如果歌曲及音源支持的话(#1839)
|
- 设置-播放设置-优先播放320k音质选项改为“优先播放的音质”,允许选择更高优先播放的音质,如果歌曲及音源支持的话(#1839)
|
||||||
|
|
||||||
|
### 开放API变更
|
||||||
|
|
||||||
|
- `/status` 的入参现在与 `/subscribe-player-status` 保持一致
|
||||||
|
- `/status` 新增 `filter` 入参用于过滤返回的字段,并内置了默认值,与之前相比默认不再返回 `picUrl`
|
||||||
|
- `/status` 及 `/subscribe-player-status` 的可用字段名添加了 `lyricLineAllText`,它对应的值是当前句歌词及扩展歌词文本(扩展歌词包含翻译、罗马音等,按换行符分割)
|
||||||
|
|
||||||
|
详情看开放API接入文档
|
||||||
|
|
|
@ -26,6 +26,7 @@ declare namespace LX {
|
||||||
duration: number
|
duration: number
|
||||||
playbackRate: number
|
playbackRate: number
|
||||||
lyricLineText: string
|
lyricLineText: string
|
||||||
|
lyricLineAllText: string
|
||||||
lyric: string
|
lyric: string
|
||||||
collect: boolean
|
collect: boolean
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,6 +244,7 @@ export const initAppSetting = async() => {
|
||||||
duration: 0,
|
duration: 0,
|
||||||
playbackRate: 1,
|
playbackRate: 1,
|
||||||
lyricLineText: '',
|
lyricLineText: '',
|
||||||
|
lyricLineAllText: '',
|
||||||
lyric: '',
|
lyric: '',
|
||||||
collect: false,
|
collect: false,
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,13 +14,32 @@ type SubscribeKeys = keyof LX.Player.Status
|
||||||
let httpServer: http.Server
|
let httpServer: http.Server
|
||||||
let sockets = new Set<Socket>()
|
let sockets = new Set<Socket>()
|
||||||
let responses = new Map<http.ServerResponse<http.IncomingMessage>, SubscribeKeys[]>()
|
let responses = new Map<http.ServerResponse<http.IncomingMessage>, SubscribeKeys[]>()
|
||||||
|
let playerStatusKeys: SubscribeKeys[]
|
||||||
|
|
||||||
|
const defaultFilter = [
|
||||||
|
'status',
|
||||||
|
'name',
|
||||||
|
'singer',
|
||||||
|
'albumName',
|
||||||
|
'lyricLineText',
|
||||||
|
'duration',
|
||||||
|
'progress',
|
||||||
|
'playbackRate',
|
||||||
|
] satisfies SubscribeKeys[]
|
||||||
|
|
||||||
const parseFilter = (filter: any) => {
|
const parseFilter = (filter: any) => {
|
||||||
const keys = Object.keys(global.lx.player_status) as SubscribeKeys[]
|
if (typeof filter != 'string') return defaultFilter
|
||||||
if (typeof filter != 'string') return keys
|
|
||||||
filter = filter.split(',')
|
filter = filter.split(',')
|
||||||
const subKeys = keys.filter(k => filter.includes(k))
|
const subKeys = playerStatusKeys.filter(k => filter.includes(k))
|
||||||
return subKeys.length ? subKeys : keys
|
return subKeys.length ? subKeys : defaultFilter
|
||||||
|
}
|
||||||
|
const handleSendStatus = (res: http.ServerResponse<http.IncomingMessage>, query?: string) => {
|
||||||
|
const keys = parseFilter(querystring.parse(query ?? '').filter)
|
||||||
|
const resp: Partial<Record<SubscribeKeys, any>> = {}
|
||||||
|
for (const k of keys) resp[k] = global.lx.player_status[k]
|
||||||
|
res.setHeader('Content-Type', 'application/json; charset=utf-8')
|
||||||
|
res.writeHead(200)
|
||||||
|
res.end(JSON.stringify(resp))
|
||||||
}
|
}
|
||||||
const handleSubscribePlayerStatus = (req: http.IncomingMessage, res: http.ServerResponse<http.IncomingMessage>, query?: string) => {
|
const handleSubscribePlayerStatus = (req: http.IncomingMessage, res: http.ServerResponse<http.IncomingMessage>, query?: string) => {
|
||||||
res.writeHead(200, {
|
res.writeHead(200, {
|
||||||
|
@ -43,26 +62,15 @@ const handleSubscribePlayerStatus = (req: http.IncomingMessage, res: http.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleStartServer = async(port: number, ip: string) => new Promise<void>((resolve, reject) => {
|
const handleStartServer = async(port: number, ip: string) => new Promise<void>((resolve, reject) => {
|
||||||
|
playerStatusKeys = Object.keys(global.lx.player_status) as SubscribeKeys[]
|
||||||
httpServer = http.createServer((req, res): void => {
|
httpServer = http.createServer((req, res): void => {
|
||||||
const [endUrl, query] = `/${req.url?.split('/').at(-1) ?? ''}`.split('?')
|
const [endUrl, query] = `/${req.url?.split('/').at(-1) ?? ''}`.split('?')
|
||||||
let code
|
let code
|
||||||
let msg
|
let msg
|
||||||
switch (endUrl) {
|
switch (endUrl) {
|
||||||
case '/status':
|
case '/status':
|
||||||
code = 200
|
handleSendStatus(res, query)
|
||||||
res.setHeader('Content-Type', 'application/json; charset=utf-8')
|
return
|
||||||
msg = JSON.stringify({
|
|
||||||
status: global.lx.player_status.status,
|
|
||||||
name: global.lx.player_status.name,
|
|
||||||
singer: global.lx.player_status.singer,
|
|
||||||
albumName: global.lx.player_status.albumName,
|
|
||||||
duration: global.lx.player_status.duration,
|
|
||||||
progress: global.lx.player_status.progress,
|
|
||||||
picUrl: global.lx.player_status.picUrl,
|
|
||||||
playbackRate: global.lx.player_status.playbackRate,
|
|
||||||
lyricLineText: global.lx.player_status.lyricLineText,
|
|
||||||
})
|
|
||||||
break
|
|
||||||
// case '/test':
|
// case '/test':
|
||||||
// code = 200
|
// code = 200
|
||||||
// res.setHeader('Content-Type', 'text/html; charset=utf-8')
|
// res.setHeader('Content-Type', 'text/html; charset=utf-8')
|
||||||
|
|
|
@ -87,7 +87,7 @@ export const init = () => {
|
||||||
onPlay(line, text) {
|
onPlay(line, text) {
|
||||||
setText(text, Math.max(line, 0))
|
setText(text, Math.max(line, 0))
|
||||||
setStatusText(text)
|
setStatusText(text)
|
||||||
window.app_event.lyricLinePlay(text)
|
window.app_event.lyricLinePlay(text, line)
|
||||||
// console.log(line, text)
|
// console.log(line, text)
|
||||||
},
|
},
|
||||||
onSetLyric(lines, offset) { // listening lyrics seting event
|
onSetLyric(lines, offset) { // listening lyrics seting event
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { throttle } from '@common/utils'
|
||||||
import { pause, play, playNext, playPrev } from '@renderer/core/player'
|
import { pause, play, playNext, playPrev } from '@renderer/core/player'
|
||||||
import { playProgress } from '@renderer/store/player/playProgress'
|
import { playProgress } from '@renderer/store/player/playProgress'
|
||||||
import { appSetting } from '@renderer/store/setting'
|
import { appSetting } from '@renderer/store/setting'
|
||||||
|
import { lyric } from '@renderer/store/player/lyric'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
// const setVisibleDesktopLyric = useCommit('setVisibleDesktopLyric')
|
// const setVisibleDesktopLyric = useCommit('setVisibleDesktopLyric')
|
||||||
|
@ -58,9 +59,11 @@ export default () => {
|
||||||
picUrl: musicInfo.pic ?? '',
|
picUrl: musicInfo.pic ?? '',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const handleSetLyricLine = (text: string) => {
|
const handleSetLyricLine = (text: string, line: number) => {
|
||||||
|
let curLine = lyric.lines[line]?.extendedLyrics.join('\n') ?? ''
|
||||||
sendPlayerStatus({
|
sendPlayerStatus({
|
||||||
lyricLineText: text,
|
lyricLineText: text,
|
||||||
|
lyricLineAllText: curLine ? text + '\n' + curLine : text,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// const handleSetTaskbarThumbnailClip = (clip) => {
|
// const handleSetTaskbarThumbnailClip = (clip) => {
|
||||||
|
|
|
@ -145,8 +145,8 @@ export class AppEvent extends Event {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 歌词行播放
|
// 歌词行播放
|
||||||
lyricLinePlay(text: string) {
|
lyricLinePlay(text: string, line: number) {
|
||||||
this.emit('lyricLinePlay', text)
|
this.emit('lyricLinePlay', text, line)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 我的列表改变事件
|
// 我的列表改变事件
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { reactive } from '@common/utils/vueTools'
|
import { reactive } from '@common/utils/vueTools'
|
||||||
|
|
||||||
interface Line {
|
export interface Line {
|
||||||
text: string
|
text: string
|
||||||
time: number
|
time: number
|
||||||
extendedLyrics: string[]
|
extendedLyrics: string[]
|
||||||
|
|
Loading…
Reference in New Issue