62 lines
2.9 KiB
TypeScript
62 lines
2.9 KiB
TypeScript
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,
|
|
});
|
|
}
|
|
}
|