Initial commit

This commit is contained in:
Sebastian
2025-11-26 19:00:04 +00:00
commit 0ba05b6483
27 changed files with 2517 additions and 0 deletions

View File

@@ -0,0 +1,163 @@
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 }
);
}
}