Spaces:
Running
Running
| import { NextResponse } from 'next/server' | |
| export const dynamic = 'force-dynamic' | |
| export const runtime = 'nodejs' | |
| interface SongRequest { | |
| title: string | |
| style: string | |
| lyrics: string | |
| passkey: string | |
| } | |
| export async function POST(request: Request) { | |
| try { | |
| const body: SongRequest = await request.json() | |
| const { title, style, lyrics, passkey } = body | |
| // Verify passkey | |
| if (!passkey) { | |
| return NextResponse.json( | |
| { error: 'Passkey is required' }, | |
| { status: 401 } | |
| ) | |
| } | |
| // Get ElevenLabs API key from environment | |
| const elevenLabsApiKey = process.env.ELEVENLABS_API_KEY | |
| if (!elevenLabsApiKey) { | |
| return NextResponse.json( | |
| { error: 'ElevenLabs API key not configured. Set ELEVENLABS_API_KEY environment variable.' }, | |
| { status: 500 } | |
| ) | |
| } | |
| // Prepare the prompt for music generation | |
| const musicPrompt = `${style} song with the following lyrics: ${lyrics.substring(0, 500)}` | |
| console.log('Generating music with ElevenLabs:', { title, style, promptLength: musicPrompt.length }) | |
| // Call ElevenLabs Music API | |
| const response = await fetch('https://api.elevenlabs.io/v1/music/detailed', { | |
| method: 'POST', | |
| headers: { | |
| 'xi-api-key': elevenLabsApiKey, | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ | |
| prompt: musicPrompt, | |
| music_length_ms: 30000, // 30 seconds for demo | |
| model_id: 'music_v1', | |
| }), | |
| }) | |
| if (!response.ok) { | |
| const errorText = await response.text() | |
| console.error('ElevenLabs API error:', { | |
| status: response.status, | |
| statusText: response.statusText, | |
| error: errorText | |
| }) | |
| return NextResponse.json( | |
| { error: `ElevenLabs API error: ${response.status} ${response.statusText}` }, | |
| { status: response.status } | |
| ) | |
| } | |
| // Get the audio data as buffer | |
| const audioBuffer = await response.arrayBuffer() | |
| // Save the audio to local storage or return as base64 | |
| const audioBase64 = Buffer.from(audioBuffer).toString('base64') | |
| const audioDataUrl = `data:audio/mpeg;base64,${audioBase64}` | |
| // Create voice content entry | |
| const voiceContent = { | |
| id: `song-${Date.now()}`, | |
| type: 'song', | |
| title, | |
| style, | |
| lyrics, | |
| audioUrl: audioDataUrl, | |
| timestamp: Date.now(), | |
| isProcessing: false, | |
| } | |
| // Return the content - the client will save it to localStorage | |
| return NextResponse.json({ | |
| success: true, | |
| content: voiceContent, | |
| message: 'Song generated successfully! Open Voice Studio app to listen.', | |
| }) | |
| } catch (error) { | |
| console.error('Error generating song:', error) | |
| return NextResponse.json( | |
| { error: error instanceof Error ? error.message : 'Failed to generate song' }, | |
| { status: 500 } | |
| ) | |
| } | |
| } | |