Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | import { NextResponse } from 'next/server' import { existsSync, readdirSync } from 'fs' import { join } from 'path' import { withAuth } from '@/lib/auth/withAuth' const AUDIO_DIR = join(process.cwd(), 'data', 'audio') /** * GET /api/audio/collected-clips/manifest?voices=onyx,nova * * Lightweight endpoint returning which clip IDs have pre-generated mp3 files * for each requested voice. Includes both static manifest clips ({clipId}.mp3) * and collected clips (cc-{clipId}.mp3). Used by TtsAudioManager at boot to * know which clips can play pre-generated audio. * * Response: { clipIdsByVoice: { onyx: ["abc123", ...], nova: [...] } } */ export const GET = withAuth(async (request) => { try { const voicesParam = request.nextUrl.searchParams.get('voices') if (!voicesParam) { return NextResponse.json({ clipIdsByVoice: {} }) } const voices = voicesParam .split(',') .map((v) => v.trim()) .filter(Boolean) const clipIdsByVoice: Record<string, string[]> = {} for (const voice of voices) { const voiceDir = join(AUDIO_DIR, voice) if (!existsSync(voiceDir)) { clipIdsByVoice[voice] = [] continue } const files = readdirSync(voiceDir) const clipIds: string[] = [] for (const f of files) { if (f === '.deactivated') continue if (f.endsWith('.mp3')) { if (f.startsWith('cc-')) { clipIds.push(f.slice(3, -4)) } else { clipIds.push(f.slice(0, -4)) } } else if (f.endsWith('.webm')) { if (f.startsWith('cc-')) { clipIds.push(f.slice(3, -5)) } else { clipIds.push(f.slice(0, -5)) } } } clipIdsByVoice[voice] = clipIds } return NextResponse.json({ clipIdsByVoice }) } catch (error) { console.error('Error fetching collected clips manifest:', error) return NextResponse.json({ error: 'Failed to fetch manifest' }, { status: 500 }) } }) |