修改分镜表
This commit is contained in:
parent
2f0a064363
commit
a53ff46de2
@ -1,223 +1,3 @@
|
|||||||
# 决策层 Agent 技能指令
|
你是一个测试流程助手,你专门生成假数据:
|
||||||
|
你必须使用XML格式写入工作区分镜面板:<storyboard><items prompt=提示词内容 track=分组 duration=视频推荐时间 associateAssetsIds=[该分镜所需的资产ID列表]/></storyboard>
|
||||||
你是视频制作项目的**决策层 Agent**,**只负责决策和任务派发**:理解用户意图、拆解任务、调度执行层与监督层、把控质量。
|
现在请根据哟用户指令直接输出xml假数据
|
||||||
你是唯一与用户直接对接的 Agent,执行层和监督层只接收你派发的指令。
|
|
||||||
|
|
||||||
**核心原则:**
|
|
||||||
- **决策层不执行具体任务**,不读取工作区数据(不调用 get_flowData),不直接操作任何资产或分镜数据。所有具体工作由执行层完成。
|
|
||||||
- **决策层不做执行层的判断**,执行层返回什么结论就基于该结论决策下一步。
|
|
||||||
|
|
||||||
## 核心职责
|
|
||||||
|
|
||||||
1. **需求分析**:解析用户请求,判断属于流水线哪个阶段
|
|
||||||
2. **任务拆解**:将复杂请求分解为可执行的子任务
|
|
||||||
3. **调度执行**:通过 `run_sub_agent_execution` 派发任务到执行层
|
|
||||||
4. **质量管控**:通过 `run_sub_agent_supervision` 调用监督层审核产出物
|
|
||||||
5. **记忆检索**:通过 `deepRetrieve` 获取历史上下文和项目进度记忆
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 制作流水线
|
|
||||||
|
|
||||||
五个阶段**必须按顺序执行**:
|
|
||||||
|
|
||||||
```
|
|
||||||
阶段1: 衍生资产分析 → 阶段2: 衍生资产生成(可选) → 阶段3: 导演规划 → 阶段4: 构建分镜表 → 阶段5: 生成分镜
|
|
||||||
```
|
|
||||||
|
|
||||||
### 全局约束
|
|
||||||
|
|
||||||
- **资产约束**:阶段3、4、5 只能使用资产库中已存在的资产(含阶段1已写入的衍生资产)
|
|
||||||
- **异步操作**:阶段2的图片生成、阶段5的分镜图片生成均为异步操作,派发后告知用户等待即可
|
|
||||||
- **审核规则**:仅阶段3(导演规划)和阶段4(构建分镜表)需要审核,执行完毕后自动派发监督层
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 阶段1:衍生资产分析
|
|
||||||
|
|
||||||
| 项 | 说明 |
|
|
||||||
|----|------|
|
|
||||||
| 派发 | 执行层分析剧本,识别并写入衍生资产信息 |
|
|
||||||
| 输出 | 衍生资产分析报告 + 衍生资产写入结果(或"无需衍生"结论) |
|
|
||||||
| 前置条件 | 剧本和资产已存在于工作区 |
|
|
||||||
| 审核 | 不需要 |
|
|
||||||
|
|
||||||
**决策层行为:**
|
|
||||||
|
|
||||||
| 执行层返回 | 决策层操作 |
|
|
||||||
|-----------|-----------|
|
|
||||||
| "不需要衍生资产" | 向用户简要告知,直接进入阶段3 |
|
|
||||||
| 衍生资产清单(已写入) | 展示给用户,询问是否确认生成图片 |
|
|
||||||
|
|
||||||
**用户确认分支(仅有新增资产时):**
|
|
||||||
|
|
||||||
| 用户反馈 | 操作 |
|
|
||||||
|----------|------|
|
|
||||||
| 确认全部生成 | 进入阶段2 |
|
|
||||||
| 部分生成 | 将用户选择的子集传递给阶段2 |
|
|
||||||
| 跳过 | 直接进入阶段3,告知后续仅使用现有资产 |
|
|
||||||
| 调整清单 | 重新派发分析或将调整后清单传递给阶段2 |
|
|
||||||
|
|
||||||
> 约束:阶段1必须完成衍生资产信息写入;分析结果需展示给用户确认是否进入图片生成,且不可自动进入阶段2。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 阶段2:衍生资产生成(可选)
|
|
||||||
|
|
||||||
| 项 | 说明 |
|
|
||||||
|----|------|
|
|
||||||
| 派发 | 执行层对已写入的衍生资产生成图片 |
|
|
||||||
| 输入 | 用户确认需要生成图片的衍生资产清单(来自阶段1) |
|
|
||||||
| 输出 | 图片生成启动 |
|
|
||||||
| 前置条件 | 阶段1完成且用户确认生成 |
|
|
||||||
| 审核 | 不需要 |
|
|
||||||
|
|
||||||
**决策层行为:** 将用户确认的资产清单(或子集)派发给执行层。返回确认后,告知用户图片生成中,直接进入阶段3。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 阶段3:导演规划
|
|
||||||
|
|
||||||
| 项 | 说明 |
|
|
||||||
|----|------|
|
|
||||||
| 派发 | 执行层制定导演拍摄计划 |
|
|
||||||
| 输出 | 导演拍摄计划(执行层通过 set_plane 同步到前端) |
|
|
||||||
| 质量门 | 计划覆盖全部剧情、节奏合理、与资产匹配 |
|
|
||||||
| 前置条件 | 阶段1完成(含跳过阶段2的情况) |
|
|
||||||
| 审核 | **需要** → 执行完毕后自动派发监督层 |
|
|
||||||
|
|
||||||
**阶段特有约束:** 规划中引用的角色、道具、场景必须在资产列表中存在。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 阶段4:构建分镜表
|
|
||||||
|
|
||||||
| 项 | 说明 |
|
|
||||||
|----|------|
|
|
||||||
| 派发 | 执行层将剧本拆分为分镜,生成结构化分镜表 |
|
|
||||||
| 输出 | 结构化分镜表(执行层通过 set_flowData 保存) |
|
|
||||||
| 质量门 | 分镜拆分粒度合理、字段完整、关联资产正确 |
|
|
||||||
| 前置条件 | 阶段3(导演规划)完成 |
|
|
||||||
| 审核 | **需要** → 执行完毕后自动派发监督层 |
|
|
||||||
|
|
||||||
**阶段特有约束:** `associateAssetsIds` 中的索引必须指向资产库中实际存在的资产。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 阶段5:生成分镜
|
|
||||||
|
|
||||||
| 项 | 说明 |
|
|
||||||
|----|------|
|
|
||||||
| 派发 | 执行层调用图片生成接口生成分镜图片 |
|
|
||||||
| 输出 | 生成的分镜图片 |
|
|
||||||
| 前置条件 | 阶段4完成且用户确认 |
|
|
||||||
| 审核 | 不需要 |
|
|
||||||
|
|
||||||
**决策层行为:** 执行层返回确认后,告知用户图片生成已启动,流程结束。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 调度与派发规范
|
|
||||||
|
|
||||||
### 派发指令要求
|
|
||||||
|
|
||||||
**派发给执行层和监督层的任务指令正文严格不超过100字。** 执行层已具备完整技能指令,只需告知任务类型和关键参数。
|
|
||||||
|
|
||||||
### 执行层派发
|
|
||||||
|
|
||||||
使用 `run_sub_agent_execution` 调用执行层:
|
|
||||||
|
|
||||||
```
|
|
||||||
run_sub_agent_execution(
|
|
||||||
prompts: "<按模板构建的具体指令>"
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 审核派发与结果处理
|
|
||||||
|
|
||||||
阶段3或阶段4执行完毕后:
|
|
||||||
1. 将执行层返回的确认消息展示给用户
|
|
||||||
2. **紧接着自动调用监督层审核**(无需等待用户指示)
|
|
||||||
|
|
||||||
```
|
|
||||||
run_sub_agent_supervision(
|
|
||||||
prompts: "请审核【{阶段名}】的产出物。审核维度:{维度列表}"
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
监督层审核完毕后将报告展示给用户。决策层**等待用户回复**,根据反馈操作:
|
|
||||||
|
|
||||||
| 用户反馈 | 操作 |
|
|
||||||
|----------|------|
|
|
||||||
| 通过 / 下一阶段 | 派发下一阶段任务 |
|
|
||||||
| 需要修复 | 根据用户指示构建修复指令,派发执行层 |
|
|
||||||
| 重做 | 重新派发当前阶段任务 |
|
|
||||||
|
|
||||||
### 调度决策树
|
|
||||||
|
|
||||||
| 用户请求 | 处理规则 |
|
|
||||||
|----------|----------|
|
|
||||||
| 明确指定阶段 | 检查前置条件 → 派发该阶段 |
|
|
||||||
| "从头开始" / "完整制作" | 从阶段1顺序执行 |
|
|
||||||
| "继续" / "下一步" | `deepRetrieve` 获取进度 → 从当前阶段继续 |
|
|
||||||
| "修改/优化 X" | 定位对应阶段 → 派发修改任务 |
|
|
||||||
| 模糊请求 | `deepRetrieve` 获取进度 → 从当前阶段继续 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 指令模板
|
|
||||||
|
|
||||||
### 执行派发格式
|
|
||||||
|
|
||||||
```
|
|
||||||
你是执行层Agent,请执行【{任务类型}】任务。
|
|
||||||
目标:{一句话目标}
|
|
||||||
上下文:{必要数据摘要}
|
|
||||||
要求:
|
|
||||||
1. {具体步骤1}
|
|
||||||
2. {具体步骤2}
|
|
||||||
约束:{特殊约束条件}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 修复派发格式
|
|
||||||
|
|
||||||
```
|
|
||||||
你是执行层Agent,请修复【{任务类型}】的以下问题。
|
|
||||||
用户确认的修复项:
|
|
||||||
1. {问题} → 修改为:{方案}
|
|
||||||
保持其余内容不变。
|
|
||||||
```
|
|
||||||
|
|
||||||
> 修复指令中只包含用户明确确认要修的项,不包含用户未回应或跳过的问题。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 记忆检索策略
|
|
||||||
|
|
||||||
在以下场景使用 `deepRetrieve`:
|
|
||||||
1. **新会话开始**:检索项目当前进度、已完成阶段
|
|
||||||
2. **用户提到之前的内容**:检索相关历史产出摘要
|
|
||||||
3. **质量问题追溯**:检索之前的审核结果和修改记录
|
|
||||||
4. **判断前置条件**:检索各阶段是否已完成
|
|
||||||
|
|
||||||
> `deepRetrieve` 用于检索历史记忆和进度状态,不用于读取工作区当前数据。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 与用户交互规范
|
|
||||||
|
|
||||||
1. **进度汇报**:每完成一个阶段,汇报结果摘要和下一步计划
|
|
||||||
2. **审核结果展示**:阶段3、4由监督层审核后展示报告,等待用户反馈
|
|
||||||
3. **等待用户决策**:审核发现问题时,**必须等待用户明确指示**后再执行修复,不可自行决定
|
|
||||||
4. **不暴露内部机制**:不向用户提及 Agent 名称、工具名称等实现细节
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 错误处理
|
|
||||||
|
|
||||||
| 场景 | 处理 |
|
|
||||||
|------|------|
|
|
||||||
| 执行层返回错误 | 分析原因,调整指令重新派发(最多重试2次) |
|
|
||||||
| 监督层发现质量问题 | 等待用户确认修复方案 → 派发修复指令 |
|
|
||||||
| 前置条件不满足 | 提示用户需先完成哪个阶段 |
|
|
||||||
| 记忆检索无结果 | 请求用户提供必要上下文 |
|
|
||||||
|
|||||||
@ -138,7 +138,7 @@ function createSubAgent(parentCtx: AgentContext) {
|
|||||||
"你必须使用如下XML格式写入工作区:\n```",
|
"你必须使用如下XML格式写入工作区:\n```",
|
||||||
"拍摄计划:<scriptPlan>内容</scriptPlan>",
|
"拍摄计划:<scriptPlan>内容</scriptPlan>",
|
||||||
"分镜表:<storyboardTable>内容</storyboardTable>",
|
"分镜表:<storyboardTable>内容</storyboardTable>",
|
||||||
"分镜面板:<storyboard> <items prompt=提示词内容 group=分组 duration=视频推荐时间 associateAssetsIds=[资产ID列表] /></storyboard>",
|
"分镜面板:<storyboard> <items prompt=提示词内容 track=分组 duration=视频推荐时间 associateAssetsIds=[该分镜所需的资产ID列表] /></storyboard>",
|
||||||
"```",
|
"```",
|
||||||
].join("\n");
|
].join("\n");
|
||||||
// "剧本:<script>内容</script>",
|
// "剧本:<script>内容</script>",
|
||||||
|
|||||||
@ -176,7 +176,7 @@ function createSubAgent(parentCtx: AgentContext) {
|
|||||||
prompt,
|
prompt,
|
||||||
system:
|
system:
|
||||||
systemPrompt +
|
systemPrompt +
|
||||||
`\n你必须使用如下XML格式写入工作区:\nXML不得添加任何额外标签<scriptItem name="剧本名称">剧本内容</scriptItem><scriptItem name="剧本名称">剧本内容</scriptItem><scriptItem name="剧本名称">剧本内容</scriptItem>`,
|
`\n你必须使用如下XML格式写入工作区:\nXML不得添加任何额外标签<scriptItem name="剧本名称">剧本内容</scriptItem><item name="剧本名称">剧本内容</item><item name="剧本名称">剧本内容</item>`,
|
||||||
name: "编剧",
|
name: "编剧",
|
||||||
memoryKey: "assistant:execution:script",
|
memoryKey: "assistant:execution:script",
|
||||||
});
|
});
|
||||||
|
|||||||
@ -11,6 +11,7 @@ export const ScriptSchema = z.object({
|
|||||||
export const planData = z.object({
|
export const planData = z.object({
|
||||||
storySkeleton: z.string().describe("故事骨架"),
|
storySkeleton: z.string().describe("故事骨架"),
|
||||||
adaptationStrategy: z.string().describe("改编策略"),
|
adaptationStrategy: z.string().describe("改编策略"),
|
||||||
|
script: z.string().describe("剧本内容"),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type planData = z.infer<typeof planData>;
|
export type planData = z.infer<typeof planData>;
|
||||||
@ -60,12 +61,10 @@ export default (toolCpnfig: ToolConfig) => {
|
|||||||
console.log("[tools] get_planData", key);
|
console.log("[tools] get_planData", key);
|
||||||
const thinking = msg.thinking(`正在获取${planDataKeyLabels[key]}工作区数据...`);
|
const thinking = msg.thinking(`正在获取${planDataKeyLabels[key]}工作区数据...`);
|
||||||
const planData: planData = await new Promise((resolve) => socket.emit("getPlanData", { key }, (res: any) => resolve(res)));
|
const planData: planData = await new Promise((resolve) => socket.emit("getPlanData", { key }, (res: any) => resolve(res)));
|
||||||
const value = planData[key];
|
thinking.appendText(`获取到${planDataKeyLabels[key]}:\n` + planData[key]);
|
||||||
const valueStr = typeof value === "object" ? JSON.stringify(value, null, 2) : String(value ?? "");
|
|
||||||
thinking.appendText(`获取到${planDataKeyLabels[key]}:\n` + valueStr);
|
|
||||||
thinking.updateTitle(`获取${planDataKeyLabels[key]}完成`);
|
thinking.updateTitle(`获取${planDataKeyLabels[key]}完成`);
|
||||||
thinking.complete();
|
thinking.complete();
|
||||||
return valueStr || "无数据";
|
return planData[key] ?? "无数据";
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
get_novel_text: tool({
|
get_novel_text: tool({
|
||||||
|
|||||||
@ -480,22 +480,13 @@ description: 专注于从剧本内容中提取所使用的资产(角色、场
|
|||||||
builder: (table) => {
|
builder: (table) => {
|
||||||
table.integer("id").notNullable();
|
table.integer("id").notNullable();
|
||||||
table.integer("scriptId");
|
table.integer("scriptId");
|
||||||
table.text("title");
|
|
||||||
table.text("prompt");
|
table.text("prompt");
|
||||||
table.text("videoPrompt");
|
|
||||||
table.text("description");
|
|
||||||
table.text("filePath");
|
table.text("filePath");
|
||||||
table.text("model");
|
|
||||||
table.text("mode");
|
|
||||||
table.text("duration");
|
table.text("duration");
|
||||||
table.text("resolution");
|
|
||||||
table.text("frameMode");
|
|
||||||
table.text("camera");
|
|
||||||
table.text("sound");
|
|
||||||
table.text("lines");
|
|
||||||
table.text("state");
|
table.text("state");
|
||||||
table.text("group");
|
table.integer("trackId");
|
||||||
table.text("reason");
|
table.text("reason");
|
||||||
|
table.integer("projectId");
|
||||||
table.integer("index");
|
table.integer("index");
|
||||||
table.integer("createTime");
|
table.integer("createTime");
|
||||||
table.primary(["id"]);
|
table.primary(["id"]);
|
||||||
|
|||||||
@ -14,9 +14,10 @@ export default router.post(
|
|||||||
id: z.number().nullable().optional(),
|
id: z.number().nullable().optional(),
|
||||||
type: z.enum(["role", "scene", "storyboard", "clip", "tool"]),
|
type: z.enum(["role", "scene", "storyboard", "clip", "tool"]),
|
||||||
episodesId: z.number(),
|
episodesId: z.number(),
|
||||||
|
projectId: z.number(),
|
||||||
}),
|
}),
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
const { edges, nodes, imageUrl, id, type, episodesId } = req.body;
|
const { edges, nodes, imageUrl, id, type, episodesId, projectId } = req.body;
|
||||||
let imagePath = "";
|
let imagePath = "";
|
||||||
try {
|
try {
|
||||||
imagePath = new URL(imageUrl).pathname;
|
imagePath = new URL(imageUrl).pathname;
|
||||||
@ -59,6 +60,7 @@ export default router.post(
|
|||||||
filePath: imagePath,
|
filePath: imagePath,
|
||||||
scriptId: episodesId,
|
scriptId: episodesId,
|
||||||
createTime: Date.now(),
|
createTime: Date.now(),
|
||||||
|
projectId,
|
||||||
});
|
});
|
||||||
insertFlowId = storyboardId;
|
insertFlowId = storyboardId;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -73,24 +73,7 @@ export default router.post(
|
|||||||
storyboard: [],
|
storyboard: [],
|
||||||
//todo:矫正workbench数据
|
//todo:矫正workbench数据
|
||||||
workbench: {
|
workbench: {
|
||||||
videoList: [
|
videoList: [],
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
prompt: "动起来",
|
|
||||||
filePath: await u.oss.getFileUrl("/artStyle/5d96256a-1610-43a6-a469-c2385cc2287e.jpg"),
|
|
||||||
duration: 4,
|
|
||||||
scriptId: 1,
|
|
||||||
selectedVideoId: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
prompt: "跳起来",
|
|
||||||
filePath: await u.oss.getFileUrl("/artStyle/5d96256a-1610-43a6-a469-c2385cc2287e.jpg"),
|
|
||||||
duration: 4,
|
|
||||||
scriptId: 1,
|
|
||||||
selectedVideoId: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
//todo:矫正封面数据
|
//todo:矫正封面数据
|
||||||
poster: {
|
poster: {
|
||||||
@ -178,14 +161,8 @@ export default router.post(
|
|||||||
...existing,
|
...existing,
|
||||||
id: i.id,
|
id: i.id,
|
||||||
index: i.index,
|
index: i.index,
|
||||||
title: i.title,
|
|
||||||
description: i.description,
|
|
||||||
camera: i.camera,
|
|
||||||
duration: i.duration ? +i.duration : 0,
|
duration: i.duration ? +i.duration : 0,
|
||||||
frameMode: i.frameMode,
|
|
||||||
prompt: i.prompt,
|
prompt: i.prompt,
|
||||||
lines: i.lines,
|
|
||||||
sound: i.sound,
|
|
||||||
associateAssetsIds: assets2StoryboardMap[i.id!] ?? [],
|
associateAssetsIds: assets2StoryboardMap[i.id!] ?? [],
|
||||||
src: i.filePath,
|
src: i.filePath,
|
||||||
state: i.state,
|
state: i.state,
|
||||||
|
|||||||
@ -17,7 +17,6 @@ export default router.post(
|
|||||||
storyboardData.map(async (i) => {
|
storyboardData.map(async (i) => {
|
||||||
return {
|
return {
|
||||||
...i,
|
...i,
|
||||||
title: i.title,
|
|
||||||
filePath: i.filePath ? await u.oss.getFileUrl(i.filePath!) : "",
|
filePath: i.filePath ? await u.oss.getFileUrl(i.filePath!) : "",
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
@ -66,19 +65,11 @@ export default router.post(
|
|||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
id: String(item.id),
|
id: String(item.id),
|
||||||
camera: item.camera ? Number(item.camera) : undefined,
|
|
||||||
createTime: item.createTime ?? undefined,
|
createTime: item.createTime ?? undefined,
|
||||||
description: item.description ?? undefined,
|
|
||||||
duration: item.duration ? Number(item.duration) : undefined,
|
duration: item.duration ? Number(item.duration) : undefined,
|
||||||
filePath: item.filePath || undefined,
|
filePath: item.filePath || undefined,
|
||||||
frameMode: item.frameMode ? Number(item.frameMode) : undefined,
|
|
||||||
mode: item.mode ?? "",
|
|
||||||
model: item.model ?? "",
|
|
||||||
prompt: item.prompt ?? undefined,
|
prompt: item.prompt ?? undefined,
|
||||||
resolution: item.resolution ?? undefined,
|
|
||||||
scriptId: item.scriptId ?? undefined,
|
scriptId: item.scriptId ?? undefined,
|
||||||
sound: item.sound ? Number(item.sound) : undefined,
|
|
||||||
title: item.title ?? undefined,
|
|
||||||
characters: charactersWithUrl,
|
characters: charactersWithUrl,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -1,10 +1,17 @@
|
|||||||
import express from "express";
|
import express from "express";
|
||||||
import u from "@/utils";
|
import u from "@/utils";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { success } from "@/lib/responseFormat";
|
import { error, success } from "@/lib/responseFormat";
|
||||||
import { validateFields } from "@/middleware/middleware";
|
import { validateFields } from "@/middleware/middleware";
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
interface Storyboard {
|
||||||
|
id: number;
|
||||||
|
track: string;
|
||||||
|
src: string | null;
|
||||||
|
associateAssetsIds: number[];
|
||||||
|
duration: number;
|
||||||
|
state: string;
|
||||||
|
}
|
||||||
export default router.post(
|
export default router.post(
|
||||||
"/",
|
"/",
|
||||||
validateFields({
|
validateFields({
|
||||||
@ -12,24 +19,25 @@ export default router.post(
|
|||||||
z.object({
|
z.object({
|
||||||
prompt: z.string(),
|
prompt: z.string(),
|
||||||
duration: z.number(),
|
duration: z.number(),
|
||||||
group: z.number(),
|
track: z.string(),
|
||||||
state: z.string(),
|
state: z.string(),
|
||||||
src: z.string().nullable(),
|
src: z.string().nullable(),
|
||||||
associateAssetsIds: z.array(z.number()),
|
associateAssetsIds: z.array(z.number()),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
scriptId: z.number(),
|
scriptId: z.number(),
|
||||||
|
projectId: z.number(),
|
||||||
}),
|
}),
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
const { data, scriptId } = req.body;
|
const { data, scriptId, projectId } = req.body;
|
||||||
if (!data.length) return res.status(400).send({ success: false, message: "数据不能为空" });
|
if (!data.length) return res.status(400).send({ success: false, message: "数据不能为空" });
|
||||||
for (const item of data) {
|
for (const item of data) {
|
||||||
const [id] = await u.db("o_storyboard").insert({
|
const [id] = await u.db("o_storyboard").insert({
|
||||||
prompt: item.prompt,
|
prompt: item.prompt,
|
||||||
duration: String(item.duration),
|
duration: String(item.duration),
|
||||||
group: String(item.group),
|
|
||||||
state: item.state,
|
state: item.state,
|
||||||
scriptId,
|
scriptId,
|
||||||
|
projectId,
|
||||||
createTime: Date.now(),
|
createTime: Date.now(),
|
||||||
});
|
});
|
||||||
if (item.associateAssetsIds?.length) {
|
if (item.associateAssetsIds?.length) {
|
||||||
@ -40,8 +48,46 @@ export default router.post(
|
|||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
item.id = id;
|
||||||
}
|
}
|
||||||
const lastStoryboard = await u.db("o_storyboard").where("scriptId", scriptId);
|
//根据track分组
|
||||||
return res.status(200).send(success(lastStoryboard));
|
const storyboardGroupByTrack: Record<string, number[]> = {};
|
||||||
|
data.forEach((item: any) => {
|
||||||
|
if (!storyboardGroupByTrack[item.track]) {
|
||||||
|
storyboardGroupByTrack[item.track] = [];
|
||||||
|
}
|
||||||
|
storyboardGroupByTrack[item.track].push(item.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
//循环
|
||||||
|
for (const track in storyboardGroupByTrack) {
|
||||||
|
const [trackId] = await u.db("o_videoTrack").insert({
|
||||||
|
scriptId,
|
||||||
|
projectId,
|
||||||
|
});
|
||||||
|
const storyboardIds = storyboardGroupByTrack[track] ?? [];
|
||||||
|
await u.db("o_storyboard").whereIn("id", storyboardIds).update({ trackId });
|
||||||
|
}
|
||||||
|
const lastStoryboard = await u
|
||||||
|
.db("o_storyboard")
|
||||||
|
.where("scriptId", scriptId)
|
||||||
|
.select("id", "trackId", "prompt", "duration", "state", "scriptId", "reason", "filePath");
|
||||||
|
if (!lastStoryboard || !lastStoryboard.length) return res.status(400).send(error("为查到分镜数据"));
|
||||||
|
const storyboardData = await Promise.all(
|
||||||
|
lastStoryboard.map(async (i) => {
|
||||||
|
return {
|
||||||
|
associateAssetsIds: await u.db("o_assets2Storyboard").where("storyboardId", i.id).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));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@ -31,12 +31,7 @@ export default router.post(
|
|||||||
storyboardData.map(async (i: any) => {
|
storyboardData.map(async (i: any) => {
|
||||||
return {
|
return {
|
||||||
id: i.id,
|
id: i.id,
|
||||||
title: i.title,
|
|
||||||
prompt: i.prompt,
|
prompt: i.prompt,
|
||||||
description: i.description,
|
|
||||||
camera: i.camera,
|
|
||||||
lines: i.lines,
|
|
||||||
sound: i.sound,
|
|
||||||
state: i.state,
|
state: i.state,
|
||||||
src: i.filePath ? await u.oss.getFileUrl(i.filePath!) : "",
|
src: i.filePath ? await u.oss.getFileUrl(i.filePath!) : "",
|
||||||
};
|
};
|
||||||
|
|||||||
78
src/types/database.d.ts
vendored
78
src/types/database.d.ts
vendored
@ -1,6 +1,49 @@
|
|||||||
// @db-hash c2029b55b7dcdcf64788dafc34799fea
|
// @db-hash c145f43374602285beea82bbd51eaec8
|
||||||
//该文件由脚本自动生成,请勿手动修改
|
//该文件由脚本自动生成,请勿手动修改
|
||||||
|
|
||||||
|
export interface _o_storyboard_old_20260331 {
|
||||||
|
'camera'?: string | null;
|
||||||
|
'createTime'?: number | null;
|
||||||
|
'description'?: string | null;
|
||||||
|
'duration'?: string | null;
|
||||||
|
'filePath'?: string | null;
|
||||||
|
'frameMode'?: string | null;
|
||||||
|
'id'?: number;
|
||||||
|
'index'?: number | null;
|
||||||
|
'lines'?: string | null;
|
||||||
|
'mode'?: string | null;
|
||||||
|
'model'?: string | null;
|
||||||
|
'prompt'?: string | null;
|
||||||
|
'reason'?: string | null;
|
||||||
|
'resolution'?: string | null;
|
||||||
|
'scriptId'?: number | null;
|
||||||
|
'sound'?: string | null;
|
||||||
|
'state'?: string | null;
|
||||||
|
'title'?: string | null;
|
||||||
|
'videoPrompt'?: string | null;
|
||||||
|
}
|
||||||
|
export interface _o_storyboard_old_20260331_1 {
|
||||||
|
'camera'?: string | null;
|
||||||
|
'createTime'?: number | null;
|
||||||
|
'description'?: string | null;
|
||||||
|
'duration'?: string | null;
|
||||||
|
'filePath'?: string | null;
|
||||||
|
'frameMode'?: string | null;
|
||||||
|
'id'?: number;
|
||||||
|
'index'?: number | null;
|
||||||
|
'lines'?: string | null;
|
||||||
|
'mode'?: string | null;
|
||||||
|
'model'?: string | null;
|
||||||
|
'prompt'?: string | null;
|
||||||
|
'reason'?: string | null;
|
||||||
|
'resolution'?: string | null;
|
||||||
|
'scriptId'?: number | null;
|
||||||
|
'sound'?: string | null;
|
||||||
|
'state'?: string | null;
|
||||||
|
'title'?: string | null;
|
||||||
|
'track'?: string | null;
|
||||||
|
'videoPrompt'?: string | null;
|
||||||
|
}
|
||||||
export interface memories {
|
export interface memories {
|
||||||
'content': string;
|
'content': string;
|
||||||
'createTime': number;
|
'createTime': number;
|
||||||
@ -114,7 +157,6 @@ export interface o_project {
|
|||||||
'imageModel'?: string | null;
|
'imageModel'?: string | null;
|
||||||
'imageQuality'?: string | null;
|
'imageQuality'?: string | null;
|
||||||
'intro'?: string | null;
|
'intro'?: string | null;
|
||||||
'mode'?: string | null;
|
|
||||||
'name'?: string | null;
|
'name'?: string | null;
|
||||||
'projectType'?: string | null;
|
'projectType'?: string | null;
|
||||||
'type'?: string | null;
|
'type'?: string | null;
|
||||||
@ -162,26 +204,17 @@ export interface o_skillList {
|
|||||||
'updateTime': number;
|
'updateTime': number;
|
||||||
}
|
}
|
||||||
export interface o_storyboard {
|
export interface o_storyboard {
|
||||||
'camera'?: string | null;
|
|
||||||
'createTime'?: number | null;
|
'createTime'?: number | null;
|
||||||
'description'?: string | null;
|
|
||||||
'duration'?: string | null;
|
'duration'?: string | null;
|
||||||
'filePath'?: string | null;
|
'filePath'?: string | null;
|
||||||
'frameMode'?: string | null;
|
|
||||||
'group'?: string | null;
|
|
||||||
'id'?: number;
|
'id'?: number;
|
||||||
'index'?: number | null;
|
'index'?: number | null;
|
||||||
'lines'?: string | null;
|
'projectId'?: number | null;
|
||||||
'mode'?: string | null;
|
|
||||||
'model'?: string | null;
|
|
||||||
'prompt'?: string | null;
|
'prompt'?: string | null;
|
||||||
'reason'?: string | null;
|
'reason'?: string | null;
|
||||||
'resolution'?: string | null;
|
|
||||||
'scriptId'?: number | null;
|
'scriptId'?: number | null;
|
||||||
'sound'?: string | null;
|
|
||||||
'state'?: string | null;
|
'state'?: string | null;
|
||||||
'title'?: string | null;
|
'trackId'?: number | null;
|
||||||
'videoPrompt'?: string | null;
|
|
||||||
}
|
}
|
||||||
export interface o_tasks {
|
export interface o_tasks {
|
||||||
'describe'?: string | null;
|
'describe'?: string | null;
|
||||||
@ -218,8 +251,22 @@ export interface o_video {
|
|||||||
'projectId'?: number | null;
|
'projectId'?: number | null;
|
||||||
'scriptId'?: number | null;
|
'scriptId'?: number | null;
|
||||||
'state'?: string | null;
|
'state'?: string | null;
|
||||||
|
'storyboardId'?: number | null;
|
||||||
'time'?: number | null;
|
'time'?: number | null;
|
||||||
'videoTrackId'?: number | null;
|
}
|
||||||
|
export interface o_videoConfig {
|
||||||
|
'audio'?: number | null;
|
||||||
|
'createTime'?: number | null;
|
||||||
|
'data'?: string | null;
|
||||||
|
'duration'?: number | null;
|
||||||
|
'id'?: number;
|
||||||
|
'mode'?: string | null;
|
||||||
|
'model'?: string | null;
|
||||||
|
'prompt'?: string | null;
|
||||||
|
'resolution'?: string | null;
|
||||||
|
'storyboardId'?: number | null;
|
||||||
|
'updateTime'?: number | null;
|
||||||
|
'videoId'?: number | null;
|
||||||
}
|
}
|
||||||
export interface o_videoTrack {
|
export interface o_videoTrack {
|
||||||
'id'?: number;
|
'id'?: number;
|
||||||
@ -229,6 +276,8 @@ export interface o_videoTrack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface DB {
|
export interface DB {
|
||||||
|
"_o_storyboard_old_20260331": _o_storyboard_old_20260331;
|
||||||
|
"_o_storyboard_old_20260331_1": _o_storyboard_old_20260331_1;
|
||||||
"memories": memories;
|
"memories": memories;
|
||||||
"o_agentDeploy": o_agentDeploy;
|
"o_agentDeploy": o_agentDeploy;
|
||||||
"o_agentWorkData": o_agentWorkData;
|
"o_agentWorkData": o_agentWorkData;
|
||||||
@ -254,5 +303,6 @@ export interface DB {
|
|||||||
"o_user": o_user;
|
"o_user": o_user;
|
||||||
"o_vendorConfig": o_vendorConfig;
|
"o_vendorConfig": o_vendorConfig;
|
||||||
"o_video": o_video;
|
"o_video": o_video;
|
||||||
|
"o_videoConfig": o_videoConfig;
|
||||||
"o_videoTrack": o_videoTrack;
|
"o_videoTrack": o_videoTrack;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user