import express from "express"; import u from "@/utils"; import { z } from "zod"; import { v4 as uuidv4 } from "uuid"; import { success } from "@/lib/responseFormat"; import { validateFields } from "@/middleware/middleware"; const router = express.Router(); export default router.post( "/", validateFields({ projectId: z.number(), scriptId: z.number(), uploadData: z.array( z.object({ id: z.number(), type: z.string(), }), ), prompt: z.string(), model: z.string(), mode: z.string(), resolution: z.string(), duration: z.number(), audio: z.boolean().optional(), trackId: z.number(), }), async (req, res) => { const { scriptId, projectId, prompt, uploadData, model, duration, resolution, audio, mode, trackId } = req.body; //获取生成视频比例 const ratio = await u.db("o_project").select("videoRatio").where("id", projectId).first(); const videoPath = `/${projectId}/video/${uuidv4()}.mp4`; //视频保存路径 //新增 const [videoId] = await u.db("o_video").insert({ filePath: videoPath, time: Date.now(), state: "生成中", scriptId, projectId, videoTrackId: trackId, }); //查询出图片数据 const images = await Promise.all( uploadData.map(async (item: { id: number; type: string }) => { if (item.type === "storyboard") { const filePath = await u.db("o_storyboard").where("id", item.id).select("filePath").first(); return filePath?.filePath; } if (item.type === "assets") { const filePath = await u .db("o_assets") .where("o_assets.id", item.id) .leftJoin("o_image", "o_assets.imageId", "o_image.id") .select("o_image.filePath") .first(); return filePath?.filePath; } }), ); //把images里面的图片转成base64格式 const base64 = await Promise.all( images.map(async (item) => { if (!item) return null; return await u.oss.getImageBase64(item); }), ); res.status(200).send(success(videoId)); (async () => { try { const relatedObjects = { projectId, videoId, scriptId, type: "视频", }; const aiVideo = u.Ai.Video(model); await aiVideo.run( { prompt, imageBase64: base64.filter((item) => item !== null) as string[], mode, duration, aspectRatio: (ratio?.videoRatio as `${number}:${number}`) || "16:9", resolution, audio, }, { projectId, taskClass: "视频生成", describe: "根据提示词生成视频", relatedObjects: JSON.stringify(relatedObjects), }, ); await aiVideo.save(videoPath); await u.db("o_video").where("id", videoId).update({ state: "生成成功" }); } catch (error: any) { await u .db("o_video") .where("id", videoId) .update({ state: "生成失败", errorReason: error instanceof Error ? error.message : "未知错误", }); } })(); }, );