增加视频提示词生成
This commit is contained in:
parent
24c0f3ea4e
commit
f7830d862c
@ -536,6 +536,9 @@ description: 专注于从剧本内容中提取所使用的资产(角色、场
|
|||||||
table.integer("videoId");
|
table.integer("videoId");
|
||||||
table.integer("projectId");
|
table.integer("projectId");
|
||||||
table.integer("scriptId");
|
table.integer("scriptId");
|
||||||
|
table.text("state");
|
||||||
|
table.text("reason");
|
||||||
|
table.text("prompt");
|
||||||
table.primary(["id"]);
|
table.primary(["id"]);
|
||||||
table.unique(["id"]);
|
table.unique(["id"]);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -72,7 +72,11 @@ export default router.post(
|
|||||||
.db("o_storyboard")
|
.db("o_storyboard")
|
||||||
.where("scriptId", scriptId)
|
.where("scriptId", scriptId)
|
||||||
.select("id", "trackId", "prompt", "duration", "state", "scriptId", "reason", "filePath");
|
.select("id", "trackId", "prompt", "duration", "state", "scriptId", "reason", "filePath");
|
||||||
if (!lastStoryboard || !lastStoryboard.length) return res.status(400).send(error("为查到分镜数据"));
|
if (!lastStoryboard || !lastStoryboard.length) return res.status(400).send(error("未查到分镜数据"));
|
||||||
|
batchGenerateVideoPrompts(
|
||||||
|
data.map((i: any) => i.id),
|
||||||
|
projectId,
|
||||||
|
);
|
||||||
const storyboardData = await Promise.all(
|
const storyboardData = await Promise.all(
|
||||||
lastStoryboard.map(async (i) => {
|
lastStoryboard.map(async (i) => {
|
||||||
return {
|
return {
|
||||||
@ -91,3 +95,58 @@ export default router.post(
|
|||||||
return res.status(200).send(success(storyboardData));
|
return res.status(200).send(success(storyboardData));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
async function batchGenerateVideoPrompts(storyboardIds: number[], projectId: number) {
|
||||||
|
const lastStoryboard = await u.db("o_storyboard").whereIn("id", storyboardIds).select("id", "trackId", "prompt");
|
||||||
|
const allTrackIds = lastStoryboard.map((i) => i.trackId);
|
||||||
|
const storyboardPromptRecord: Record<number, string[]> = {};
|
||||||
|
lastStoryboard.forEach((i) => {
|
||||||
|
if (i.trackId) {
|
||||||
|
if (!storyboardPromptRecord[i.trackId]) {
|
||||||
|
storyboardPromptRecord[i.trackId] = [];
|
||||||
|
}
|
||||||
|
storyboardPromptRecord[i.trackId].push(i.prompt!);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const projectSetting = await u.db("o_project").where("id", projectId).select("artStyle").first();
|
||||||
|
const systemPrompt = u.getArtPrompt(projectSetting?.artStyle!, "art_storyboard_video");
|
||||||
|
await u
|
||||||
|
.db("o_videoTrack")
|
||||||
|
.whereIn("id", allTrackIds as number[])
|
||||||
|
.update({
|
||||||
|
state: "生成中",
|
||||||
|
});
|
||||||
|
for (const trackId in storyboardPromptRecord) {
|
||||||
|
const storboardPrompts = storyboardPromptRecord[trackId];
|
||||||
|
try {
|
||||||
|
const { text } = await u.Ai.Text("universalAi").invoke({
|
||||||
|
messages: [
|
||||||
|
{
|
||||||
|
role: "system",
|
||||||
|
content: systemPrompt,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: "user",
|
||||||
|
content: `请根据我所提供的 ${storboardPrompts.length} 条分镜内容,为我生成一条视频提示词,请直接输出提示词内容,不做任何解释说明。
|
||||||
|
分镜内容如下:
|
||||||
|
${storboardPrompts.map((i, index) => `${index + 1}.${i}`).join("\n")}`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
await u.db("o_videoTrack").where("id", trackId).update({
|
||||||
|
state: "已完成",
|
||||||
|
prompt: text,
|
||||||
|
});
|
||||||
|
console.log("%c Line:116 🍎 text", "background:#42b983", text);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("生成视频提示词失败", e);
|
||||||
|
await u
|
||||||
|
.db("o_videoTrack")
|
||||||
|
.where("id", trackId)
|
||||||
|
.update({
|
||||||
|
state: "生成失败",
|
||||||
|
reason: u.error(e).message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -58,37 +58,23 @@ export default router.post(
|
|||||||
}),
|
}),
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
const { scriptIds, projectId, groupSize = 5 } = req.body;
|
const { scriptIds, projectId, groupSize = 5 } = req.body;
|
||||||
|
|
||||||
if (!scriptIds.length) return res.status(400).send(error("请先选择剧本"));
|
if (!scriptIds.length) return res.status(400).send(error("请先选择剧本"));
|
||||||
const scripts = await u.db("o_script").whereIn("id", scriptIds);
|
const scripts = await u.db("o_script").whereIn("id", scriptIds);
|
||||||
const intansce = u.Ai.Text("universalAi");
|
const intansce = u.Ai.Text("universalAi");
|
||||||
|
|
||||||
// 查询已有的剧本-资产关联,找出已经提取过资产的剧本
|
|
||||||
const existingScriptAssets = await u.db("o_scriptAssets").whereIn("scriptId", scriptIds).select("scriptId");
|
|
||||||
const scriptIdsWithAssets = new Set(existingScriptAssets.map((sa: any) => sa.scriptId));
|
|
||||||
|
|
||||||
// 构建 scriptId -> script 内容的映射
|
// 构建 scriptId -> script 内容的映射
|
||||||
const scriptMap = new Map(scripts.map((s: o_script) => [s.id, s]));
|
const scriptMap = new Map(scripts.map((s: o_script) => [s.id, s]));
|
||||||
|
|
||||||
// 过滤掉已成功提取过资产的剧本(extractState === 1 且有关联资产)
|
await u.db("o_script").whereIn("id", scriptIds).update({
|
||||||
const filteredScriptIds = scriptIds.filter((id: number) => {
|
|
||||||
const script = scriptMap.get(id);
|
|
||||||
return !(script?.extractState === 1 && scriptIdsWithAssets.has(id));
|
|
||||||
});
|
|
||||||
const skippedCount = scriptIds.length - filteredScriptIds.length;
|
|
||||||
|
|
||||||
if (!filteredScriptIds.length) {
|
|
||||||
return res.send(success("所有剧本已提取过资产,无需重复提取"));
|
|
||||||
}
|
|
||||||
|
|
||||||
await u.db("o_script").whereIn("id", filteredScriptIds).update({
|
|
||||||
extractState: 0,
|
extractState: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
const errors: { scriptId: number; error: string }[] = [];
|
const errors: { scriptId: number; error: string }[] = [];
|
||||||
let successCount = 0;
|
let successCount = 0;
|
||||||
|
|
||||||
// 将过滤后的 scriptIds 按 groupSize(默认5)分组,每组一起发给 AI
|
// 将 scriptIds 按 groupSize(默认5)分组,每组一起发给 AI
|
||||||
const scriptGroups = chunkArray(filteredScriptIds, groupSize);
|
const scriptGroups = chunkArray(scriptIds, groupSize);
|
||||||
|
|
||||||
/** 一组剧本提取完成后统一入库并建立关联 */
|
/** 一组剧本提取完成后统一入库并建立关联 */
|
||||||
async function persistGroupResult(result: GroupResult) {
|
async function persistGroupResult(result: GroupResult) {
|
||||||
@ -257,6 +243,6 @@ export default router.post(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.send(success(skippedCount > 0 ? `开始提取资产,跳过 ${skippedCount} 个已提取的剧本` : "开始提取资产"));
|
return res.send(success("开始提取资产"));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
12
src/types/database.d.ts
vendored
12
src/types/database.d.ts
vendored
@ -1,6 +1,12 @@
|
|||||||
// @db-hash ae0b5b1d792b614db036441010965ace
|
// @db-hash f82eb99171699f051830710c1f816b59
|
||||||
//该文件由脚本自动生成,请勿手动修改
|
//该文件由脚本自动生成,请勿手动修改
|
||||||
|
|
||||||
|
export interface _o_videoTrack_old_20260401 {
|
||||||
|
'id'?: number;
|
||||||
|
'projectId'?: number | null;
|
||||||
|
'scriptId'?: number | null;
|
||||||
|
'videoId'?: number | null;
|
||||||
|
}
|
||||||
export interface memories {
|
export interface memories {
|
||||||
'content': string;
|
'content': string;
|
||||||
'createTime': number;
|
'createTime': number;
|
||||||
@ -217,11 +223,15 @@ export interface o_video {
|
|||||||
export interface o_videoTrack {
|
export interface o_videoTrack {
|
||||||
'id'?: number;
|
'id'?: number;
|
||||||
'projectId'?: number | null;
|
'projectId'?: number | null;
|
||||||
|
'prompt'?: string | null;
|
||||||
|
'reason'?: string | null;
|
||||||
'scriptId'?: number | null;
|
'scriptId'?: number | null;
|
||||||
|
'state'?: string | null;
|
||||||
'videoId'?: number | null;
|
'videoId'?: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DB {
|
export interface DB {
|
||||||
|
"_o_videoTrack_old_20260401": _o_videoTrack_old_20260401;
|
||||||
"memories": memories;
|
"memories": memories;
|
||||||
"o_agentDeploy": o_agentDeploy;
|
"o_agentDeploy": o_agentDeploy;
|
||||||
"o_agentWorkData": o_agentWorkData;
|
"o_agentWorkData": o_agentWorkData;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user