video-flow-toon/src/routes/production/storyboard/batchAddStoryboardInfo.ts
2026-04-12 17:46:59 +08:00

109 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import express from "express";
import u from "@/utils";
import { z } from "zod";
import { error, success } from "@/lib/responseFormat";
import { validateFields } from "@/middleware/middleware";
const router = express.Router();
export default router.post(
"/",
validateFields({
data: z.array(
z.object({
prompt: z.string(),
duration: z.number(),
track: z.string(),
state: z.string(),
src: z.string().nullable(),
videoDesc: z.string(),
shouldGenerateImage: z.number(),
associateAssetsIds: z.array(z.number()),
}),
),
scriptId: z.number(),
projectId: z.number(),
}),
async (req, res) => {
const { data, scriptId, projectId } = req.body;
if (!data.length) return res.status(400).send({ success: false, message: "数据不能为空" });
for (const item of data) {
const [id] = await u.db("o_storyboard").insert({
prompt: item.prompt,
duration: String(item.duration),
state: item.state,
scriptId,
projectId,
track:item.track,
videoDesc:item.videoDesc,
shouldGenerateImage:item.shouldGenerateImage,
createTime: Date.now(),
});
if (item.associateAssetsIds?.length) {
await u.db("o_assets2Storyboard").insert(
item.associateAssetsIds.map((assetId: number) => ({
assetId,
storyboardId: id,
})),
);
}
item.id = id;
}
const lastStoryboard = await u.db("o_storyboard").where("scriptId", scriptId);
if (!lastStoryboard || !lastStoryboard.length) return res.status(400).send(error("未查到分镜数据"));
//根据track分组
const storyboardGroupByTrack: Record<string, number[]> = {};
lastStoryboard.forEach((item: any) => {
if (!storyboardGroupByTrack[item.track]) {
storyboardGroupByTrack[item.track] = [];
}
storyboardGroupByTrack[item.track].push(item.id);
});
//循环先查询数据库中是否已存在相同track名称的trackId有则复用没有则新建
for (const track in storyboardGroupByTrack) {
const storyboardIds = storyboardGroupByTrack[track] ?? [];
// 计算该track下所有分镜的duration总和
const trackDuration = lastStoryboard
.filter((item: any) => item.track == track)
.reduce((sum: number, item: any) => sum + Number(item.duration), 0);
// 查找该scriptId下是否已有相同track名称且已分配trackId的分镜记录
const existingStoryboard = await u.db("o_storyboard").where({ scriptId, track }).whereNotNull("trackId").first();
let trackId: number;
if (existingStoryboard?.trackId) {
// 已存在相同track名称的trackId直接复用并更新duration
trackId = existingStoryboard.trackId;
await u.db("o_videoTrack").where("id", trackId).update({ duration: trackDuration });
} else {
// 不存在新建videoTrack
const [newTrackId] = await u.db("o_videoTrack").insert({
scriptId,
projectId,
duration: trackDuration,
});
trackId = newTrackId;
}
await u.db("o_storyboard").whereIn("id", storyboardIds).update({ trackId });
}
const storyboardData = await Promise.all(
lastStoryboard.map(async (i) => {
return {
associateAssetsIds: await u.db("o_assets2Storyboard").where("storyboardId", i.id).orderBy("rowid").select("assetId").pluck("assetId"),
src: i.filePath ? await u.oss.getFileUrl(i.filePath) : "",
id: i.id,
trackId: i.trackId,
prompt: i.prompt,
duration: Number(i.duration),
state: i.state,
scriptId: i.scriptId,
reason: i.reason,
};
}),
);
return res.status(200).send(success(storyboardData));
},
);