[M] Move lyrics
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import * as ne from '@neteasecloudmusicapienhanced/api'
|
import * as ne from '@neteasecloudmusicapienhanced/api'
|
||||||
import { aiParseLyrics } from '../../shared/lyricsParse'
|
import { aiParseLyrics } from './tools/lyrics'
|
||||||
import type { NeteaseSongBrief } from '../../shared/types'
|
import type { NeteaseSongBrief } from '../../shared/types'
|
||||||
import { db } from './db'
|
import { db } from './db'
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import OpenAI from 'openai'
|
import OpenAI from 'openai'
|
||||||
import type { LyricLine, LyricSegment } from './types'
|
import type { LyricLine, LyricSegment } from '../../../shared/types'
|
||||||
|
|
||||||
// Please put OPENAI_API_KEY in your environment variables.
|
// Please put OPENAI_API_KEY in your environment variables.
|
||||||
const client = new OpenAI()
|
const client = new OpenAI()
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { db } from "./db"
|
import { db } from "./db"
|
||||||
import type { UserDocument, UserData } from "../../shared/types.ts";
|
import type { UserDocument, UserData } from "../../shared/types.ts";
|
||||||
|
import { error } from "@sveltejs/kit";
|
||||||
|
|
||||||
const users = db.collection<UserDocument>("users")
|
const users = db.collection<UserDocument>("users")
|
||||||
|
|
||||||
@@ -23,9 +24,10 @@ export async function createUser(registUA: string): Promise<string> {
|
|||||||
* @returns User document or null if not found
|
* @returns User document or null if not found
|
||||||
*/
|
*/
|
||||||
export const getUserBySession = (session: string) => users.findOne({ sessions: session })
|
export const getUserBySession = (session: string) => users.findOne({ sessions: session })
|
||||||
export async function login(session: string): Promise<UserDocument> {
|
export async function login(session?: string): Promise<UserDocument> {
|
||||||
|
if (!session) throw error(401, 'Invalid session')
|
||||||
const user = await getUserBySession(session)
|
const user = await getUserBySession(session)
|
||||||
if (!user) throw new Error('Invalid session')
|
if (!user) throw error(401, 'Invalid session')
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
const DATA_DIR = './data'
|
|
||||||
@@ -1,212 +0,0 @@
|
|||||||
import OpenAI from 'openai'
|
|
||||||
import type { LyricSegment } from './types'
|
|
||||||
import { lyric } from '@neteasecloudmusicapienhanced/api'
|
|
||||||
|
|
||||||
// Please put OPENAI_API_KEY in your environment variables.
|
|
||||||
const client = new OpenAI()
|
|
||||||
const req = {
|
|
||||||
model: "gpt-5.1-chat-latest",
|
|
||||||
messages: [
|
|
||||||
{
|
|
||||||
role: "system",
|
|
||||||
content: `あなたは歌詞処理を専門とするAIです。
|
|
||||||
以下のタスクを実行してください。
|
|
||||||
|
|
||||||
タスク
|
|
||||||
タイムスタンプ付きの日本語の歌詞テキスト(LRC形式)を入力として受け取ります。
|
|
||||||
このテキストを解析し、指定された形式のJSON配列に変換してください。
|
|
||||||
|
|
||||||
処理ルール
|
|
||||||
メタデータの除外: "作词"、"作曲"、"编曲"など、歌詞以外の情報を含む行はすべて除外してください。
|
|
||||||
JSON形式: 出力はJSON配列とし、各要素はtimeとlyricの2つのキーを持つオブジェクトとします。
|
|
||||||
timeキー: 元の行からタイムスタンプ(例:00:15.570)をそのまま文字列として格納します。
|
|
||||||
lyricキー: 歌詞のテキストを解析し、配列として格納します。
|
|
||||||
ふりがな: 漢字(または漢字と仮名の混合語)は、["漢字", "ふりがな"]という形式の2要素配列で表現してください。(例: ["蝉", "せみ"])
|
|
||||||
その他: 漢字を含まないひらがな、カタカナ、句読点、ローマ字などは、そのまま文字列として配列に格納してください。(例: "の", "ママは")
|
|
||||||
|
|
||||||
重要
|
|
||||||
以下の例に示されている形式とまったく同じ出力を生成してください。
|
|
||||||
|
|
||||||
例`
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "user",
|
|
||||||
content: `[00:00.000] 作词 : 椎名林檎
|
|
||||||
[00:01.000] 作曲 : 椎名林檎
|
|
||||||
[00:02.000] 编曲 : 亀田誠治
|
|
||||||
[00:15.570]蝉の声を聞く度に
|
|
||||||
[00:19.270]目に浮かぶ九十九里浜
|
|
||||||
[00:22.600]皺々の祖母の手を離れ
|
|
||||||
[00:25.880]独りで訪れた歓楽街
|
|
||||||
[00:29.840]ママは此処の女王様
|
|
||||||
[00:33.520]生き写しの様なあたし
|
|
||||||
[00:36.760]誰しもが手を伸べて
|
|
||||||
[00:39.340]子供ながらに魅せられた歓楽街
|
|
||||||
[00:43.720]十五になったあたしを
|
|
||||||
[00:46.890]置いて女王は消えた
|
|
||||||
[00:50.710]毎週金曜日に来ていた
|
|
||||||
[00:53.970]男と暮らすのだろう
|
|
||||||
[01:03.840]「一度栄えし者でも
|
|
||||||
[01:07.370]必ずや衰えゆく」
|
|
||||||
[01:10.740]その意味を知る時を迎え
|
|
||||||
[01:13.990]足を踏み入れたは歓楽街
|
|
||||||
[01:17.440]消えて行った女を憎めど夏は今
|
|
||||||
[01:24.480]女王と云う肩書きを誇らしげに掲げる
|
|
||||||
[01:58.370]女に成ったあたしが
|
|
||||||
[02:01.950]売るのは自分だけで
|
|
||||||
[02:05.440]同情を欲したときに
|
|
||||||
[02:08.790]全てを失うだろう
|
|
||||||
[02:12.720]JR新宿駅の東口を出たら
|
|
||||||
[02:19.740]其処はあたしの庭
|
|
||||||
[02:23.030]大遊戯場歌舞伎町
|
|
||||||
[02:33.740]今夜からは此の町で
|
|
||||||
[02:39.300]娘のあたしが女王`
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"role": "assistant",
|
|
||||||
"content": `\`\`\`json
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"time": "00:15.570",
|
|
||||||
"lyric": [["蝉", "せみ"], "の", ["声", "こえ"], "を", ["聞", "き"], "く", ["度", "たび"], "に"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "00:19.270",
|
|
||||||
"lyric": [["目", "め"], "に", ["浮", "う"], "かぶ", ["九十九里浜", "くじゅうくりはま"]]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "00:22.600",
|
|
||||||
"lyric": [["皺々", "しわしわ"], "の", ["祖母", "そぼ"], "の", ["手", "て"], "を", ["離", "はな"], "れ"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "00:25.880",
|
|
||||||
"lyric": [["独", "ひと"], "り", "で", ["訪", "おとず"], "れた", ["歓楽街", "かんらくがい"]]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "00:29.840",
|
|
||||||
"lyric": ["ママは", ["此処", "ここ"], "の", ["女王様", "じょおうさま"]]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "00:33.520",
|
|
||||||
"lyric": [["生き写し", "いきうつし"], "の", ["様", "よう"], "なあたし"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "00:36.760",
|
|
||||||
"lyric": [["誰", "だれ"], "しもが", ["手", "て"], "を", ["伸", "の"], "べて"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "00:39.340",
|
|
||||||
"lyric": [["子供", "こども"], "ながらに", ["魅", "み"], "せられた", ["歓楽街", "かんらくがい"]]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "00:43.720",
|
|
||||||
"lyric": [["十五", "じゅうご"], "になったあたしを"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "00:46.890",
|
|
||||||
"lyric": [["置", "お"], "いて", ["女王", "じょおう"], "は", ["消", "き"], "えた"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "00:50.710",
|
|
||||||
"lyric": [["毎週", "まいしゅう"], ["金曜日", "きんようび"], "に", ["来", "き"], "ていた"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "00:53.970",
|
|
||||||
"lyric": [["男", "おとこ"], "と", ["暮", "く"], "らすのだろう"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "01:03.840",
|
|
||||||
"lyric": ["「", ["一度", "いちど"], ["栄", "さか"], "えし", ["者", "もの"], "でも"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "0E:07.370",
|
|
||||||
"lyric": [["必", "かなら"], "ずや", ["衰", "おとろ"], "えゆく」"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "01:10.740",
|
|
||||||
"lyric": ["その", ["意味", "いみ"], "を", ["知", "し"], "る", ["時", "とき"], "を", ["迎", "むか"], "え"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "01:13.990",
|
|
||||||
"lyric": [["足", "あし"], "を", ["踏", "ふ"], "み", ["入", "い"], "れたは", ["歓楽街", "かんらくがい"]]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "01:17.440",
|
|
||||||
"lyric": [["消", "き"], "えて", ["行", "い"], "った", ["女", "おんな"], "を", ["憎", "にく"], "めど", ["夏", "なつ"], "は", ["今", "いま"]]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "01:24.480",
|
|
||||||
"lyric": [["女王", "じょおう"], "と", ["云", "い"], "う", ["肩書き", "かたがき"], "を", ["誇", "ほこ"], "らしげに", ["掲", "かか"], "げる"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "01:58.370",
|
|
||||||
"lyric": [["女", "おんな"], "に", ["成", "な"], "ったあたしが"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "02:01.950",
|
|
||||||
"lyric": [["売", "う"], "るのは", ["自分", "じぶん"], "だけで"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "02:05.440",
|
|
||||||
"lyric": [["同情", "どうじょう"], "を", ["欲", "ほ"], "したときに"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "02:08.790",
|
|
||||||
"lyric": [["全", "すべ"], "てを", ["失", "うしな"], "うだろう"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "02:12.720",
|
|
||||||
"lyric": ["JR", ["新宿駅", "しんじゅくえき"], "の", ["東口", "ひがしぐち"], "を", ["出", "で"], "たら"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "02:19.740",
|
|
||||||
"lyric": [["其処", "そこ"], "はあたしの", ["庭", "にわ"]]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "02:23.030",
|
|
||||||
"lyric": [["大遊戯場", "だいゆうぎじょう"], ["歌舞伎町", "かぶきちょう"]]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "02:33.740",
|
|
||||||
"lyric": [["今夜", "こんや"], "からは", ["此", "こ"], "の", ["町", "まち"], "で"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"time": "02:39.300",
|
|
||||||
"lyric": [["娘", "むすめ"], "のあたしが", ["女王", "じょおう"]]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
\`\`\``
|
|
||||||
},
|
|
||||||
{
|
|
||||||
role: "user",
|
|
||||||
content: ""
|
|
||||||
}
|
|
||||||
],
|
|
||||||
response_format: {
|
|
||||||
type: "text"
|
|
||||||
},
|
|
||||||
// temperature: 0.6,
|
|
||||||
max_completion_tokens: 2048,
|
|
||||||
// top_p: 0.7,
|
|
||||||
frequency_penalty: 0,
|
|
||||||
presence_penalty: 0,
|
|
||||||
store: false
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function aiParseLyrics(raw: string): Promise<LyricSegment[]> {
|
|
||||||
const thisReq = JSON.parse(JSON.stringify(req))
|
|
||||||
thisReq.messages[thisReq.messages.length - 1].content = raw
|
|
||||||
const response = await client.chat.completions.create(thisReq)
|
|
||||||
const text = response.choices[0].message?.content || ''
|
|
||||||
const jsonText = text.replace(/```json/, '').replace(/```/, '').trim()
|
|
||||||
try {
|
|
||||||
return JSON.parse(jsonText)
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Failed to parse JSON from AI response:', jsonText)
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// const lrcResp = (await lyric({ id: 25723366 })).body as any
|
|
||||||
// const lrc = lrcResp.lrc.lyric
|
|
||||||
// console.log(await aiParseLyrics(lrc))
|
|
||||||
Reference in New Issue
Block a user