import { NextRequest, NextResponse } from 'next/server'; import { type VideoGenerationConfig } from '@/lib/google-ai'; import { projectId, location, credentials } from '@/lib/google-ai-server'; import { GoogleAuth } from 'google-auth-library'; export const runtime = 'nodejs'; export const maxDuration = 300; // Los videos pueden tardar más export async function POST(req: NextRequest) { try { const body: VideoGenerationConfig = await req.json(); const { model, prompt, aspectRatio = '16:9', duration = 5, negativePrompt, } = body; if (!prompt || !model) { return NextResponse.json( { error: 'Prompt y modelo son requeridos' }, { status: 400 } ); } // Configurar autenticación const auth = new GoogleAuth({ credentials: credentials, scopes: ['https://www.googleapis.com/auth/cloud-platform'], }); const client = await auth.getClient(); const accessToken = await client.getAccessToken(); if (!accessToken.token) { throw new Error('No se pudo obtener el token de acceso'); } // Construir el endpoint de la API const endpoint = `https://${location}-aiplatform.googleapis.com/v1/projects/${projectId}/locations/${location}/publishers/google/models/${model}:predict`; // Construir el prompt completo let fullPrompt = prompt; if (negativePrompt) { fullPrompt += `\n\nNegative prompt: ${negativePrompt}`; } // Construir el payload const payload = { instances: [ { prompt: fullPrompt, }, ], parameters: { aspectRatio: aspectRatio, videoDuration: `${duration}s`, }, }; console.log(`Endpoint: ${endpoint}`); // Hacer la solicitud a la API de Vertex AI const response = await fetch(endpoint, { method: 'POST', headers: { 'Authorization': `Bearer ${accessToken.token}`, 'Content-Type': 'application/json', }, body: JSON.stringify(payload), }); const data = await response.json(); if (!response.ok) { console.error('Error de la API:', data); throw new Error( data.error?.message || `Error ${response.status}: ${response.statusText}` ); } // Extraer video de la respuesta let videoData: string | null = null; if (data.predictions && data.predictions.length > 0) { const prediction = data.predictions[0]; // Buscar el video en diferentes formatos posibles if (prediction.bytesBase64Encoded) { videoData = prediction.bytesBase64Encoded; } else if (prediction.videoBase64) { videoData = prediction.videoBase64; } else if (prediction.video) { videoData = prediction.video; } } // Si no hay video, retornar error con más información if (!videoData) { console.error('No se encontró video en la respuesta'); return NextResponse.json( { error: 'El modelo no generó un video', details: 'El modelo respondió pero no incluyó datos de video en el formato esperado', response: data, suggestion: 'Los modelos Veo pueden necesitar acceso especial o estar en preview. Verifica que tu proyecto tenga acceso a estos modelos.', }, { status: 500 } ); } return NextResponse.json({ videoData: videoData, model: model, prompt: prompt, aspectRatio: aspectRatio, duration: duration, }); } catch (error: any) { console.error('Error generando video:', error); // Manejar errores específicos de la API let errorMessage = 'Error generando video'; let errorDetails = error.message; if (error.message?.includes('credentials') || error.message?.includes('authentication')) { errorMessage = 'Error de autenticación'; errorDetails = 'Verifica las credenciales del Service Account'; } else if (error.message?.includes('Quota exceeded') || error.message?.includes('quota')) { errorMessage = 'Cuota de uso excedida'; errorDetails = 'Necesitas solicitar un aumento de cuota para los modelos Veo en Google Cloud Console. Ve a: https://console.cloud.google.com/iam-admin/quotas y busca "Online prediction requests per base model"'; } else if (error.message?.includes('safety')) { errorMessage = 'Contenido bloqueado por seguridad'; errorDetails = 'El prompt fue bloqueado por políticas de seguridad'; } else if (error.message?.includes('permission') || error.message?.includes('403')) { errorMessage = 'Error de permisos'; errorDetails = 'El Service Account no tiene permisos para Vertex AI o los modelos Veo no están habilitados en tu proyecto'; } else if (error.message?.includes('not found') || error.message?.includes('404')) { errorMessage = 'Modelo no encontrado'; errorDetails = 'El modelo Veo puede no estar disponible en tu región (us-central1). Prueba solicitar acceso a los modelos Veo en Google Cloud Console.'; } else if (error.message?.includes('Internal')) { errorMessage = 'Error interno del servidor'; errorDetails = 'Los modelos Veo están en preview y pueden tener disponibilidad limitada. Intenta con otro modelo o más tarde.'; } return NextResponse.json( { error: errorMessage, details: errorDetails, fullError: error.message, stack: process.env.NODE_ENV === 'development' ? error.stack : undefined, }, { status: 500 } ); } }