import { NextResponse } from 'next/server'; import { recordEvent } from '@/lib/auditDb'; import { generateSeedanceVideo } from '@/lib/videoProviders'; import { loadSession, saveRemoteVideo, saveSession } from '@/lib/storage'; import { VIDEO_TEMPLATES } from '@/lib/templates'; import type { VideoGenerationRequest, VideoTask } from '@/lib/types'; export const runtime = 'nodejs'; export const dynamic = 'force-dynamic'; export async function POST(req: Request) { const body = (await req.json()) as VideoGenerationRequest; try { recordEvent({ action: 'video.generate_started', sessionId: body.sessionId, targetType: 'video', targetId: body.templateId, status: 'started', provider: 'seedance', metadata: { ratio: body.ratio, duration: body.duration, hasImage: Boolean(body.imageUrl), refs: body.references?.length ?? 0 } }); const response = await generateSeedanceVideo(body); let task: VideoTask | undefined; let videoUrl = response.videoUrl; if (body.sessionId && body.templateId) { const session = await loadSession(body.sessionId); if (!session) return NextResponse.json({ error: 'session not found' }, { status: 404 }); const template = VIDEO_TEMPLATES.find(item => item.id === body.templateId); const now = Date.now(); if (videoUrl) { videoUrl = await saveRemoteVideo(session.id, response.taskId || body.templateId, videoUrl); } task = { id: `vid_${session.id}_${body.templateId}`, templateId: body.templateId, title: body.templateTitle || template?.title || body.templateId, description: template?.description || '', prompt: body.prompt, anchorImageUrl: body.imageUrl, provider: response.provider, model: response.model, taskId: response.taskId, status: response.status, videoUrl, ratio: body.ratio || template?.ratio || '16:9', duration: body.duration || template?.duration || 6, submittedAt: now, updatedAt: now, raw: response.raw, }; session.videoTasks = [ ...(session.videoTasks ?? []).filter(item => item.templateId !== body.templateId), task, ]; await saveSession(session); } recordEvent({ action: 'video.generate_submitted', sessionId: body.sessionId, targetType: 'video', targetId: response.taskId ?? body.templateId ?? response.status, status: 'queued', provider: 'seedance', metadata: { status: response.status, templateId: body.templateId } }); return NextResponse.json({ ...response, videoUrl, task }); } catch (error) { const message = String(error); recordEvent({ action: 'video.generate_failed', sessionId: body.sessionId, targetType: 'video', targetId: body.templateId, status: 'error', provider: 'seedance', message }); return NextResponse.json({ error: message }, { status: message.includes('SEEDANCE_API_KEY missing') ? 503 : 500, }); } }