diff --git a/.gitignore b/.gitignore index a477b18..f5037b4 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,5 @@ vite.config.ts.timestamp-* data/ public/assets/fonts/cache -.idea \ No newline at end of file +.idea +static/audio \ No newline at end of file diff --git a/src/lib/server/songs.ts b/src/lib/server/songs.ts index 85eeb06..bd624df 100644 --- a/src/lib/server/songs.ts +++ b/src/lib/server/songs.ts @@ -6,6 +6,10 @@ import { franc } from 'franc' import { error } from '@sveltejs/kit' import type { ObjectId } from 'mongodb' import '../../shared/ext' +import { promises as fs } from 'fs' +import path from 'path' + +const CACHE_DIR = path.resolve('static/audio') /** * Functional wrapper to cache API results to MongoDB. @@ -89,6 +93,30 @@ export const getLyricsProcessed = cached('lyrics_processed', return aiParseLyrics(raw.lrc.lyric) }) +export const getSongUrl = async (id: number | string) => { + await fs.mkdir(CACHE_DIR, { recursive: true }) + + const filePath = path.join(CACHE_DIR, `${id}/standard.mp3`) + const publicUrl = `/audio/${id}/standard.mp3` + if (await fs.exists(filePath)) return publicUrl + + console.log(`Downloading song ${id}...`) + // @ts-ignore + const res = await ne.song_url_v1({ id: id.toString(), level: 'standard' }) + const url = (res.body as any).data?.[0]?.url + + if (!url) throw error(404, 'Song URL not found') + + const audioRes = await fetch(url) + if (!audioRes.ok) throw error(500, 'Failed to download song') + + const buffer = await audioRes.arrayBuffer() + await fs.writeFile(filePath, Buffer.from(buffer)) + console.log(`Song ${id} cached to ${filePath}`) + + return publicUrl +} + export interface ImportSession { id: string diff --git a/src/routes/song/[id]/+page.server.ts b/src/routes/song/[id]/+page.server.ts index 27d2367..7644b49 100644 --- a/src/routes/song/[id]/+page.server.ts +++ b/src/routes/song/[id]/+page.server.ts @@ -1,9 +1,10 @@ import type { PageServerLoad } from './$types' -import { getLyricsProcessed, getSongRaw, listRecPlaylists } from "$lib/server/songs.ts"; +import { getLyricsProcessed, getSongRaw, getSongUrl } from "$lib/server/songs.ts"; export const load: PageServerLoad = async ({ params }) => { const songId = +params.id const song = await getSongRaw(songId) const lrc = await getLyricsProcessed(songId) - return { song, lrc } + const audioUrl = await getSongUrl(songId) + return { song, lrc, audioUrl } } \ No newline at end of file