diff --git a/src/agents/productionAgent/index.ts b/src/agents/productionAgent/index.ts index 924cd4c..0678d30 100644 --- a/src/agents/productionAgent/index.ts +++ b/src/agents/productionAgent/index.ts @@ -61,10 +61,9 @@ export async function runDecisionAI(ctx: AgentContext) { videoMode = projectInfo.mode ?? ""; } const isRef = Array.isArray(videoMode) ? true : false; - // console.log("%c Line:64 🍯 isRef", "background:#b03734", isRef); // const findData = models.find((i: any) => i.modelName == videoModelName); // const isRef = findData.mode.every((i: any) => Array.isArray(i)); - console.log("%c Line:67 🍪 isRef", "background:#fca650", isRef); + const modelInfo = `项目使用的模型如下:\n图像模型:${imageModelName}\n视频模型:${videoModelName}\n多参:${isRef ? "是" : "否"}`; const mem = buildMemPrompt(await memory.get(text)); @@ -153,7 +152,7 @@ async function createSubAgent(parentCtx: AgentContext) { const models = await u.vendor.getModelList(id); if (!models.length) throw new Error(`项目使用的模型不存在,ID: ${projectInfo.videoModel}`); // const findData = models.find((i: any) => i.modelName == videoModelName); - // console.log("%c Line:153 🍿 findData.mode", "background:#93c0a4", findData.mode); + // let videoMode = ""; try { videoMode = JSON.parse(projectInfo.mode ?? ""); @@ -161,7 +160,7 @@ async function createSubAgent(parentCtx: AgentContext) { videoMode = projectInfo.mode ?? ""; } const isRef = Array.isArray(videoMode) ? true : false; - console.log("%c Line:153 🥤 isRef", "background:#42b983", isRef); + const modelInfo = `项目使用的模型如下:\n图像模型:${imageModelName}\n视频模型:${videoModelName}\n多参:${isRef ? "是" : "否"}`; // const run_sub_agent_execution = tool({ diff --git a/src/lib/fixDB.ts b/src/lib/fixDB.ts index 49e0da8..9c0307c 100644 --- a/src/lib/fixDB.ts +++ b/src/lib/fixDB.ts @@ -65,6 +65,7 @@ export default async (knex: Knex): Promise => { await addColumn("o_agentDeploy", "temperature", "integer"); // 添加新字段 await addColumn("o_agentDeploy", "maxOutputTokens", "integer"); + await addColumn("o_assets", "audioBindState", "integer"); //添加数据高级配置 const advancedAgentList = [ diff --git a/src/lib/initDB.ts b/src/lib/initDB.ts index bc7a73b..aa47b6f 100644 --- a/src/lib/initDB.ts +++ b/src/lib/initDB.ts @@ -58,7 +58,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => table.primary(["id"]); table.unique(["id"]); }, - initData: async (knex) => { }, + initData: async (knex) => {}, }, //Agent配置表 { @@ -258,7 +258,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => maxOutputTokens: 0, disabled: false, }, - ]); }, }, @@ -332,7 +331,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => table.primary(["id"]); table.unique(["id"]); }, - initData: async (knex) => { }, + initData: async (knex) => {}, }, //提示词表 { @@ -377,7 +376,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => table.primary(["id"]); table.unique(["id"]); }, - initData: async (knex) => { }, + initData: async (knex) => {}, }, //小说原文表 { @@ -452,11 +451,12 @@ export default async (knex: Knex, forceInit: boolean = false): Promise => table.integer("flowId"); //工作流id table.integer("startTime"); table.string("promptState"); + table.integer("audioBindState"); table.text("promptErrorReason"); table.primary(["id"]); table.unique(["id"]); }, - initData: async (knex) => { }, + initData: async (knex) => {}, }, //生成图片表 { diff --git a/src/router.ts b/src/router.ts index 9f999b3..513cb0a 100644 --- a/src/router.ts +++ b/src/router.ts @@ -1,4 +1,4 @@ -// @routes-hash 8fa7db9525fe2ff96ba91e9bd6c22b65 +// @routes-hash 902e3917f4bdb484fea4ea9219071a06 import { Express } from "express"; import route1 from "./routes/agents/clearMemory"; @@ -30,130 +30,134 @@ import route26 from "./routes/assetsGenerate/polishAssetsPrompt"; import route27 from "./routes/common/getBigImage"; import route28 from "./routes/cornerScape/batchBindAudio"; import route29 from "./routes/cornerScape/getAllAssets"; -import route30 from "./routes/cornerScape/updateAssetsAudio"; -import route31 from "./routes/general/generalStatistics"; -import route32 from "./routes/general/getSingleProject"; -import route33 from "./routes/general/updateProject"; -import route34 from "./routes/login/login"; -import route35 from "./routes/modelSelect/getModelDetail"; -import route36 from "./routes/modelSelect/getModelList"; -import route37 from "./routes/novel/addNovel"; -import route38 from "./routes/novel/batchDeleteNovel"; -import route39 from "./routes/novel/delNovel"; -import route40 from "./routes/novel/event/batchDeleteEvent"; -import route41 from "./routes/novel/event/deletEvent"; -import route42 from "./routes/novel/event/generateEvents"; -import route43 from "./routes/novel/event/getEvent"; -import route44 from "./routes/novel/getNovel"; -import route45 from "./routes/novel/getNovelData"; -import route46 from "./routes/novel/getNovelEventState"; -import route47 from "./routes/novel/getNovelIndex"; -import route48 from "./routes/novel/updateNovel"; -import route49 from "./routes/other/deleteAllData"; -import route50 from "./routes/other/getVersion"; -import route51 from "./routes/production/assets/batchGenerateAssetsImage"; -import route52 from "./routes/production/assets/deleteAssetsDireve"; -import route53 from "./routes/production/assets/pollingImage"; -import route54 from "./routes/production/assets/updateAssetsUrl"; -import route55 from "./routes/production/editImage/generateFlowImage"; -import route56 from "./routes/production/editImage/getImageDefaultModle"; -import route57 from "./routes/production/editImage/getImageFlow"; -import route58 from "./routes/production/editImage/saveImageFlow"; -import route59 from "./routes/production/editImage/updateImageFlow"; -import route60 from "./routes/production/editImage/uploadImage"; -import route61 from "./routes/production/getFlowData"; -import route62 from "./routes/production/getStoryboardData"; -import route63 from "./routes/production/saveFlowData"; -import route64 from "./routes/production/storyboard/addStoryboard"; -import route65 from "./routes/production/storyboard/batchAddStoryboardInfo"; -import route66 from "./routes/production/storyboard/batchGenerateImage"; -import route67 from "./routes/production/storyboard/downPreviewImage"; -import route68 from "./routes/production/storyboard/editStoryboardInfo"; -import route69 from "./routes/production/storyboard/getStoryboardData"; -import route70 from "./routes/production/storyboard/pollingImage"; -import route71 from "./routes/production/storyboard/previewImage"; -import route72 from "./routes/production/storyboard/removeFrame"; -import route73 from "./routes/production/storyboard/updateStoryboardUrl"; -import route74 from "./routes/production/workbench/addTrack"; -import route75 from "./routes/production/workbench/checkVideoStateList"; -import route76 from "./routes/production/workbench/deleteTrack"; -import route77 from "./routes/production/workbench/delVideo"; -import route78 from "./routes/production/workbench/generateVideo"; -import route79 from "./routes/production/workbench/generateVideoPrompt"; -import route80 from "./routes/production/workbench/getFileUrl"; -import route81 from "./routes/production/workbench/getGenerateData"; -import route82 from "./routes/production/workbench/getVideoList"; -import route83 from "./routes/production/workbench/selectVideo"; -import route84 from "./routes/production/workbench/updateVideoDuration"; -import route85 from "./routes/production/workbench/updateVideoPrompt"; -import route86 from "./routes/project/addDirectorManual"; -import route87 from "./routes/project/addProject"; -import route88 from "./routes/project/addVisualManual"; -import route89 from "./routes/project/deleteDirectorManual"; -import route90 from "./routes/project/deleteVisualManual"; -import route91 from "./routes/project/delProject"; -import route92 from "./routes/project/editDirectorlManual"; -import route93 from "./routes/project/editProject"; -import route94 from "./routes/project/editVisualManual"; -import route95 from "./routes/project/getModelDetails"; -import route96 from "./routes/project/getProject"; -import route97 from "./routes/project/getVisualManual"; -import route98 from "./routes/project/queryDirectorManual"; -import route99 from "./routes/project/visualManual"; -import route100 from "./routes/script/addScript"; -import route101 from "./routes/script/batchAddScript"; -import route102 from "./routes/script/delScript"; -import route103 from "./routes/script/exportScript"; -import route104 from "./routes/script/extractAssets"; -import route105 from "./routes/script/getAiRegex"; -import route106 from "./routes/script/getScrptApi"; -import route107 from "./routes/script/pollScriptAssets"; -import route108 from "./routes/script/updateScript"; -import route109 from "./routes/scriptAgent/getPlanData"; -import route110 from "./routes/scriptAgent/setPlanData"; -import route111 from "./routes/scriptAgent/updateData"; -import route112 from "./routes/setting/about/checkUpdate"; -import route113 from "./routes/setting/about/downloadApp"; -import route114 from "./routes/setting/agentDeploy/agentSetKey"; -import route115 from "./routes/setting/agentDeploy/deployAgentModel"; -import route116 from "./routes/setting/agentDeploy/getAgentDeploy"; -import route117 from "./routes/setting/dbConfig/clearData"; -import route118 from "./routes/setting/dbConfig/clearTable"; -import route119 from "./routes/setting/dbConfig/dbInfo"; -import route120 from "./routes/setting/dbConfig/exportData"; -import route121 from "./routes/setting/dbConfig/importData"; -import route122 from "./routes/setting/dev/getSwitchAiDevTool"; -import route123 from "./routes/setting/dev/updateSwitchAiDevTool"; -import route124 from "./routes/setting/fileManagement/openFolder"; -import route125 from "./routes/setting/getTextModel"; -import route126 from "./routes/setting/loginConfig/getUser"; -import route127 from "./routes/setting/loginConfig/updateUserPwd"; -import route128 from "./routes/setting/memoryConfig/delAllMemory"; -import route129 from "./routes/setting/memoryConfig/getMemory"; -import route130 from "./routes/setting/memoryConfig/sureMemory"; -import route131 from "./routes/setting/modelMap/bindingPrompt"; -import route132 from "./routes/setting/modelMap/getImageAndVideoModel"; -import route133 from "./routes/setting/promptManage/getPrompt"; -import route134 from "./routes/setting/promptManage/updatePrompt"; -import route135 from "./routes/setting/skillManagement/getSkillContent"; -import route136 from "./routes/setting/skillManagement/getSkillList"; -import route137 from "./routes/setting/skillManagement/saveSkillContent"; -import route138 from "./routes/setting/vendorConfig/addVendor"; -import route139 from "./routes/setting/vendorConfig/addVendorModel"; -import route140 from "./routes/setting/vendorConfig/deleteVendor"; -import route141 from "./routes/setting/vendorConfig/delVendorModel"; -import route142 from "./routes/setting/vendorConfig/enableVendor"; -import route143 from "./routes/setting/vendorConfig/getCodeByLink"; -import route144 from "./routes/setting/vendorConfig/getVendorList"; -import route145 from "./routes/setting/vendorConfig/modelTest"; -import route146 from "./routes/setting/vendorConfig/updateCode"; -import route147 from "./routes/setting/vendorConfig/updateVendorInputs"; -import route148 from "./routes/setting/vendorConfig/upVendorModel"; -import route149 from "./routes/task/getProject"; -import route150 from "./routes/task/getTaskApi"; -import route151 from "./routes/task/getTaskCategories"; -import route152 from "./routes/task/taskDetails"; -import route153 from "./routes/test/test"; +import route30 from "./routes/cornerScape/pollingAudio"; +import route31 from "./routes/cornerScape/updateAssetsAudio"; +import route32 from "./routes/general/generalStatistics"; +import route33 from "./routes/general/getSingleProject"; +import route34 from "./routes/general/updateProject"; +import route35 from "./routes/login/login"; +import route36 from "./routes/modelSelect/getModelDetail"; +import route37 from "./routes/modelSelect/getModelList"; +import route38 from "./routes/novel/addNovel"; +import route39 from "./routes/novel/batchDeleteNovel"; +import route40 from "./routes/novel/delNovel"; +import route41 from "./routes/novel/event/batchDeleteEvent"; +import route42 from "./routes/novel/event/deletEvent"; +import route43 from "./routes/novel/event/generateEvents"; +import route44 from "./routes/novel/event/getEvent"; +import route45 from "./routes/novel/getNovel"; +import route46 from "./routes/novel/getNovelData"; +import route47 from "./routes/novel/getNovelEventState"; +import route48 from "./routes/novel/getNovelIndex"; +import route49 from "./routes/novel/updateNovel"; +import route50 from "./routes/other/deleteAllData"; +import route51 from "./routes/other/getVersion"; +import route52 from "./routes/production/assets/batchGenerateAssetsImage"; +import route53 from "./routes/production/assets/deleteAssetsDireve"; +import route54 from "./routes/production/assets/pollingImage"; +import route55 from "./routes/production/assets/updateAssetsUrl"; +import route56 from "./routes/production/editImage/generateFlowImage"; +import route57 from "./routes/production/editImage/getImageDefaultModle"; +import route58 from "./routes/production/editImage/getImageFlow"; +import route59 from "./routes/production/editImage/saveImageFlow"; +import route60 from "./routes/production/editImage/updateImageFlow"; +import route61 from "./routes/production/editImage/uploadImage"; +import route62 from "./routes/production/getFlowData"; +import route63 from "./routes/production/getStoryboardData"; +import route64 from "./routes/production/saveFlowData"; +import route65 from "./routes/production/storyboard/addStoryboard"; +import route66 from "./routes/production/storyboard/batchAddStoryboardInfo"; +import route67 from "./routes/production/storyboard/batchDelete"; +import route68 from "./routes/production/storyboard/batchGenerateImage"; +import route69 from "./routes/production/storyboard/downPreviewImage"; +import route70 from "./routes/production/storyboard/editStoryboardInfo"; +import route71 from "./routes/production/storyboard/getStoryboardData"; +import route72 from "./routes/production/storyboard/pollingImage"; +import route73 from "./routes/production/storyboard/previewImage"; +import route74 from "./routes/production/storyboard/removeFrame"; +import route75 from "./routes/production/storyboard/updateStoryboardUrl"; +import route76 from "./routes/production/workbench/addTrack"; +import route77 from "./routes/production/workbench/batchGeneratePrompt"; +import route78 from "./routes/production/workbench/batchGenerateVideo"; +import route79 from "./routes/production/workbench/checkVideoStateList"; +import route80 from "./routes/production/workbench/deleteTrack"; +import route81 from "./routes/production/workbench/delVideo"; +import route82 from "./routes/production/workbench/generateVideo"; +import route83 from "./routes/production/workbench/generateVideoPrompt"; +import route84 from "./routes/production/workbench/getFileUrl"; +import route85 from "./routes/production/workbench/getGenerateData"; +import route86 from "./routes/production/workbench/getVideoList"; +import route87 from "./routes/production/workbench/selectVideo"; +import route88 from "./routes/production/workbench/updateVideoDuration"; +import route89 from "./routes/production/workbench/updateVideoPrompt"; +import route90 from "./routes/project/addDirectorManual"; +import route91 from "./routes/project/addProject"; +import route92 from "./routes/project/addVisualManual"; +import route93 from "./routes/project/deleteDirectorManual"; +import route94 from "./routes/project/deleteVisualManual"; +import route95 from "./routes/project/delProject"; +import route96 from "./routes/project/editDirectorlManual"; +import route97 from "./routes/project/editProject"; +import route98 from "./routes/project/editVisualManual"; +import route99 from "./routes/project/getModelDetails"; +import route100 from "./routes/project/getProject"; +import route101 from "./routes/project/getVisualManual"; +import route102 from "./routes/project/queryDirectorManual"; +import route103 from "./routes/project/visualManual"; +import route104 from "./routes/script/addScript"; +import route105 from "./routes/script/batchAddScript"; +import route106 from "./routes/script/delScript"; +import route107 from "./routes/script/exportScript"; +import route108 from "./routes/script/extractAssets"; +import route109 from "./routes/script/getAiRegex"; +import route110 from "./routes/script/getScrptApi"; +import route111 from "./routes/script/pollScriptAssets"; +import route112 from "./routes/script/updateScript"; +import route113 from "./routes/scriptAgent/getPlanData"; +import route114 from "./routes/scriptAgent/setPlanData"; +import route115 from "./routes/scriptAgent/updateData"; +import route116 from "./routes/setting/about/checkUpdate"; +import route117 from "./routes/setting/about/downloadApp"; +import route118 from "./routes/setting/agentDeploy/agentSetKey"; +import route119 from "./routes/setting/agentDeploy/deployAgentModel"; +import route120 from "./routes/setting/agentDeploy/getAgentDeploy"; +import route121 from "./routes/setting/dbConfig/clearData"; +import route122 from "./routes/setting/dbConfig/clearTable"; +import route123 from "./routes/setting/dbConfig/dbInfo"; +import route124 from "./routes/setting/dbConfig/exportData"; +import route125 from "./routes/setting/dbConfig/importData"; +import route126 from "./routes/setting/dev/getSwitchAiDevTool"; +import route127 from "./routes/setting/dev/updateSwitchAiDevTool"; +import route128 from "./routes/setting/fileManagement/openFolder"; +import route129 from "./routes/setting/getTextModel"; +import route130 from "./routes/setting/loginConfig/getUser"; +import route131 from "./routes/setting/loginConfig/updateUserPwd"; +import route132 from "./routes/setting/memoryConfig/delAllMemory"; +import route133 from "./routes/setting/memoryConfig/getMemory"; +import route134 from "./routes/setting/memoryConfig/sureMemory"; +import route135 from "./routes/setting/modelMap/bindingPrompt"; +import route136 from "./routes/setting/modelMap/getImageAndVideoModel"; +import route137 from "./routes/setting/promptManage/getPrompt"; +import route138 from "./routes/setting/promptManage/updatePrompt"; +import route139 from "./routes/setting/skillManagement/getSkillContent"; +import route140 from "./routes/setting/skillManagement/getSkillList"; +import route141 from "./routes/setting/skillManagement/saveSkillContent"; +import route142 from "./routes/setting/vendorConfig/addVendor"; +import route143 from "./routes/setting/vendorConfig/addVendorModel"; +import route144 from "./routes/setting/vendorConfig/deleteVendor"; +import route145 from "./routes/setting/vendorConfig/delVendorModel"; +import route146 from "./routes/setting/vendorConfig/enableVendor"; +import route147 from "./routes/setting/vendorConfig/getCodeByLink"; +import route148 from "./routes/setting/vendorConfig/getVendorList"; +import route149 from "./routes/setting/vendorConfig/modelTest"; +import route150 from "./routes/setting/vendorConfig/updateCode"; +import route151 from "./routes/setting/vendorConfig/updateVendorInputs"; +import route152 from "./routes/setting/vendorConfig/upVendorModel"; +import route153 from "./routes/task/getProject"; +import route154 from "./routes/task/getTaskApi"; +import route155 from "./routes/task/getTaskCategories"; +import route156 from "./routes/task/taskDetails"; +import route157 from "./routes/test/test"; export default async (app: Express) => { app.use("/api/agents/clearMemory", route1); @@ -185,128 +189,132 @@ export default async (app: Express) => { app.use("/api/common/getBigImage", route27); app.use("/api/cornerScape/batchBindAudio", route28); app.use("/api/cornerScape/getAllAssets", route29); - app.use("/api/cornerScape/updateAssetsAudio", route30); - app.use("/api/general/generalStatistics", route31); - app.use("/api/general/getSingleProject", route32); - app.use("/api/general/updateProject", route33); - app.use("/api/login/login", route34); - app.use("/api/modelSelect/getModelDetail", route35); - app.use("/api/modelSelect/getModelList", route36); - app.use("/api/novel/addNovel", route37); - app.use("/api/novel/batchDeleteNovel", route38); - app.use("/api/novel/delNovel", route39); - app.use("/api/novel/event/batchDeleteEvent", route40); - app.use("/api/novel/event/deletEvent", route41); - app.use("/api/novel/event/generateEvents", route42); - app.use("/api/novel/event/getEvent", route43); - app.use("/api/novel/getNovel", route44); - app.use("/api/novel/getNovelData", route45); - app.use("/api/novel/getNovelEventState", route46); - app.use("/api/novel/getNovelIndex", route47); - app.use("/api/novel/updateNovel", route48); - app.use("/api/other/deleteAllData", route49); - app.use("/api/other/getVersion", route50); - app.use("/api/production/assets/batchGenerateAssetsImage", route51); - app.use("/api/production/assets/deleteAssetsDireve", route52); - app.use("/api/production/assets/pollingImage", route53); - app.use("/api/production/assets/updateAssetsUrl", route54); - app.use("/api/production/editImage/generateFlowImage", route55); - app.use("/api/production/editImage/getImageDefaultModle", route56); - app.use("/api/production/editImage/getImageFlow", route57); - app.use("/api/production/editImage/saveImageFlow", route58); - app.use("/api/production/editImage/updateImageFlow", route59); - app.use("/api/production/editImage/uploadImage", route60); - app.use("/api/production/getFlowData", route61); - app.use("/api/production/getStoryboardData", route62); - app.use("/api/production/saveFlowData", route63); - app.use("/api/production/storyboard/addStoryboard", route64); - app.use("/api/production/storyboard/batchAddStoryboardInfo", route65); - app.use("/api/production/storyboard/batchGenerateImage", route66); - app.use("/api/production/storyboard/downPreviewImage", route67); - app.use("/api/production/storyboard/editStoryboardInfo", route68); - app.use("/api/production/storyboard/getStoryboardData", route69); - app.use("/api/production/storyboard/pollingImage", route70); - app.use("/api/production/storyboard/previewImage", route71); - app.use("/api/production/storyboard/removeFrame", route72); - app.use("/api/production/storyboard/updateStoryboardUrl", route73); - app.use("/api/production/workbench/addTrack", route74); - app.use("/api/production/workbench/checkVideoStateList", route75); - app.use("/api/production/workbench/deleteTrack", route76); - app.use("/api/production/workbench/delVideo", route77); - app.use("/api/production/workbench/generateVideo", route78); - app.use("/api/production/workbench/generateVideoPrompt", route79); - app.use("/api/production/workbench/getFileUrl", route80); - app.use("/api/production/workbench/getGenerateData", route81); - app.use("/api/production/workbench/getVideoList", route82); - app.use("/api/production/workbench/selectVideo", route83); - app.use("/api/production/workbench/updateVideoDuration", route84); - app.use("/api/production/workbench/updateVideoPrompt", route85); - app.use("/api/project/addDirectorManual", route86); - app.use("/api/project/addProject", route87); - app.use("/api/project/addVisualManual", route88); - app.use("/api/project/deleteDirectorManual", route89); - app.use("/api/project/deleteVisualManual", route90); - app.use("/api/project/delProject", route91); - app.use("/api/project/editDirectorlManual", route92); - app.use("/api/project/editProject", route93); - app.use("/api/project/editVisualManual", route94); - app.use("/api/project/getModelDetails", route95); - app.use("/api/project/getProject", route96); - app.use("/api/project/getVisualManual", route97); - app.use("/api/project/queryDirectorManual", route98); - app.use("/api/project/visualManual", route99); - app.use("/api/script/addScript", route100); - app.use("/api/script/batchAddScript", route101); - app.use("/api/script/delScript", route102); - app.use("/api/script/exportScript", route103); - app.use("/api/script/extractAssets", route104); - app.use("/api/script/getAiRegex", route105); - app.use("/api/script/getScrptApi", route106); - app.use("/api/script/pollScriptAssets", route107); - app.use("/api/script/updateScript", route108); - app.use("/api/scriptAgent/getPlanData", route109); - app.use("/api/scriptAgent/setPlanData", route110); - app.use("/api/scriptAgent/updateData", route111); - app.use("/api/setting/about/checkUpdate", route112); - app.use("/api/setting/about/downloadApp", route113); - app.use("/api/setting/agentDeploy/agentSetKey", route114); - app.use("/api/setting/agentDeploy/deployAgentModel", route115); - app.use("/api/setting/agentDeploy/getAgentDeploy", route116); - app.use("/api/setting/dbConfig/clearData", route117); - app.use("/api/setting/dbConfig/clearTable", route118); - app.use("/api/setting/dbConfig/dbInfo", route119); - app.use("/api/setting/dbConfig/exportData", route120); - app.use("/api/setting/dbConfig/importData", route121); - app.use("/api/setting/dev/getSwitchAiDevTool", route122); - app.use("/api/setting/dev/updateSwitchAiDevTool", route123); - app.use("/api/setting/fileManagement/openFolder", route124); - app.use("/api/setting/getTextModel", route125); - app.use("/api/setting/loginConfig/getUser", route126); - app.use("/api/setting/loginConfig/updateUserPwd", route127); - app.use("/api/setting/memoryConfig/delAllMemory", route128); - app.use("/api/setting/memoryConfig/getMemory", route129); - app.use("/api/setting/memoryConfig/sureMemory", route130); - app.use("/api/setting/modelMap/bindingPrompt", route131); - app.use("/api/setting/modelMap/getImageAndVideoModel", route132); - app.use("/api/setting/promptManage/getPrompt", route133); - app.use("/api/setting/promptManage/updatePrompt", route134); - app.use("/api/setting/skillManagement/getSkillContent", route135); - app.use("/api/setting/skillManagement/getSkillList", route136); - app.use("/api/setting/skillManagement/saveSkillContent", route137); - app.use("/api/setting/vendorConfig/addVendor", route138); - app.use("/api/setting/vendorConfig/addVendorModel", route139); - app.use("/api/setting/vendorConfig/deleteVendor", route140); - app.use("/api/setting/vendorConfig/delVendorModel", route141); - app.use("/api/setting/vendorConfig/enableVendor", route142); - app.use("/api/setting/vendorConfig/getCodeByLink", route143); - app.use("/api/setting/vendorConfig/getVendorList", route144); - app.use("/api/setting/vendorConfig/modelTest", route145); - app.use("/api/setting/vendorConfig/updateCode", route146); - app.use("/api/setting/vendorConfig/updateVendorInputs", route147); - app.use("/api/setting/vendorConfig/upVendorModel", route148); - app.use("/api/task/getProject", route149); - app.use("/api/task/getTaskApi", route150); - app.use("/api/task/getTaskCategories", route151); - app.use("/api/task/taskDetails", route152); - app.use("/api/test/test", route153); + app.use("/api/cornerScape/pollingAudio", route30); + app.use("/api/cornerScape/updateAssetsAudio", route31); + app.use("/api/general/generalStatistics", route32); + app.use("/api/general/getSingleProject", route33); + app.use("/api/general/updateProject", route34); + app.use("/api/login/login", route35); + app.use("/api/modelSelect/getModelDetail", route36); + app.use("/api/modelSelect/getModelList", route37); + app.use("/api/novel/addNovel", route38); + app.use("/api/novel/batchDeleteNovel", route39); + app.use("/api/novel/delNovel", route40); + app.use("/api/novel/event/batchDeleteEvent", route41); + app.use("/api/novel/event/deletEvent", route42); + app.use("/api/novel/event/generateEvents", route43); + app.use("/api/novel/event/getEvent", route44); + app.use("/api/novel/getNovel", route45); + app.use("/api/novel/getNovelData", route46); + app.use("/api/novel/getNovelEventState", route47); + app.use("/api/novel/getNovelIndex", route48); + app.use("/api/novel/updateNovel", route49); + app.use("/api/other/deleteAllData", route50); + app.use("/api/other/getVersion", route51); + app.use("/api/production/assets/batchGenerateAssetsImage", route52); + app.use("/api/production/assets/deleteAssetsDireve", route53); + app.use("/api/production/assets/pollingImage", route54); + app.use("/api/production/assets/updateAssetsUrl", route55); + app.use("/api/production/editImage/generateFlowImage", route56); + app.use("/api/production/editImage/getImageDefaultModle", route57); + app.use("/api/production/editImage/getImageFlow", route58); + app.use("/api/production/editImage/saveImageFlow", route59); + app.use("/api/production/editImage/updateImageFlow", route60); + app.use("/api/production/editImage/uploadImage", route61); + app.use("/api/production/getFlowData", route62); + app.use("/api/production/getStoryboardData", route63); + app.use("/api/production/saveFlowData", route64); + app.use("/api/production/storyboard/addStoryboard", route65); + app.use("/api/production/storyboard/batchAddStoryboardInfo", route66); + app.use("/api/production/storyboard/batchDelete", route67); + app.use("/api/production/storyboard/batchGenerateImage", route68); + app.use("/api/production/storyboard/downPreviewImage", route69); + app.use("/api/production/storyboard/editStoryboardInfo", route70); + app.use("/api/production/storyboard/getStoryboardData", route71); + app.use("/api/production/storyboard/pollingImage", route72); + app.use("/api/production/storyboard/previewImage", route73); + app.use("/api/production/storyboard/removeFrame", route74); + app.use("/api/production/storyboard/updateStoryboardUrl", route75); + app.use("/api/production/workbench/addTrack", route76); + app.use("/api/production/workbench/batchGeneratePrompt", route77); + app.use("/api/production/workbench/batchGenerateVideo", route78); + app.use("/api/production/workbench/checkVideoStateList", route79); + app.use("/api/production/workbench/deleteTrack", route80); + app.use("/api/production/workbench/delVideo", route81); + app.use("/api/production/workbench/generateVideo", route82); + app.use("/api/production/workbench/generateVideoPrompt", route83); + app.use("/api/production/workbench/getFileUrl", route84); + app.use("/api/production/workbench/getGenerateData", route85); + app.use("/api/production/workbench/getVideoList", route86); + app.use("/api/production/workbench/selectVideo", route87); + app.use("/api/production/workbench/updateVideoDuration", route88); + app.use("/api/production/workbench/updateVideoPrompt", route89); + app.use("/api/project/addDirectorManual", route90); + app.use("/api/project/addProject", route91); + app.use("/api/project/addVisualManual", route92); + app.use("/api/project/deleteDirectorManual", route93); + app.use("/api/project/deleteVisualManual", route94); + app.use("/api/project/delProject", route95); + app.use("/api/project/editDirectorlManual", route96); + app.use("/api/project/editProject", route97); + app.use("/api/project/editVisualManual", route98); + app.use("/api/project/getModelDetails", route99); + app.use("/api/project/getProject", route100); + app.use("/api/project/getVisualManual", route101); + app.use("/api/project/queryDirectorManual", route102); + app.use("/api/project/visualManual", route103); + app.use("/api/script/addScript", route104); + app.use("/api/script/batchAddScript", route105); + app.use("/api/script/delScript", route106); + app.use("/api/script/exportScript", route107); + app.use("/api/script/extractAssets", route108); + app.use("/api/script/getAiRegex", route109); + app.use("/api/script/getScrptApi", route110); + app.use("/api/script/pollScriptAssets", route111); + app.use("/api/script/updateScript", route112); + app.use("/api/scriptAgent/getPlanData", route113); + app.use("/api/scriptAgent/setPlanData", route114); + app.use("/api/scriptAgent/updateData", route115); + app.use("/api/setting/about/checkUpdate", route116); + app.use("/api/setting/about/downloadApp", route117); + app.use("/api/setting/agentDeploy/agentSetKey", route118); + app.use("/api/setting/agentDeploy/deployAgentModel", route119); + app.use("/api/setting/agentDeploy/getAgentDeploy", route120); + app.use("/api/setting/dbConfig/clearData", route121); + app.use("/api/setting/dbConfig/clearTable", route122); + app.use("/api/setting/dbConfig/dbInfo", route123); + app.use("/api/setting/dbConfig/exportData", route124); + app.use("/api/setting/dbConfig/importData", route125); + app.use("/api/setting/dev/getSwitchAiDevTool", route126); + app.use("/api/setting/dev/updateSwitchAiDevTool", route127); + app.use("/api/setting/fileManagement/openFolder", route128); + app.use("/api/setting/getTextModel", route129); + app.use("/api/setting/loginConfig/getUser", route130); + app.use("/api/setting/loginConfig/updateUserPwd", route131); + app.use("/api/setting/memoryConfig/delAllMemory", route132); + app.use("/api/setting/memoryConfig/getMemory", route133); + app.use("/api/setting/memoryConfig/sureMemory", route134); + app.use("/api/setting/modelMap/bindingPrompt", route135); + app.use("/api/setting/modelMap/getImageAndVideoModel", route136); + app.use("/api/setting/promptManage/getPrompt", route137); + app.use("/api/setting/promptManage/updatePrompt", route138); + app.use("/api/setting/skillManagement/getSkillContent", route139); + app.use("/api/setting/skillManagement/getSkillList", route140); + app.use("/api/setting/skillManagement/saveSkillContent", route141); + app.use("/api/setting/vendorConfig/addVendor", route142); + app.use("/api/setting/vendorConfig/addVendorModel", route143); + app.use("/api/setting/vendorConfig/deleteVendor", route144); + app.use("/api/setting/vendorConfig/delVendorModel", route145); + app.use("/api/setting/vendorConfig/enableVendor", route146); + app.use("/api/setting/vendorConfig/getCodeByLink", route147); + app.use("/api/setting/vendorConfig/getVendorList", route148); + app.use("/api/setting/vendorConfig/modelTest", route149); + app.use("/api/setting/vendorConfig/updateCode", route150); + app.use("/api/setting/vendorConfig/updateVendorInputs", route151); + app.use("/api/setting/vendorConfig/upVendorModel", route152); + app.use("/api/task/getProject", route153); + app.use("/api/task/getTaskApi", route154); + app.use("/api/task/getTaskCategories", route155); + app.use("/api/task/taskDetails", route156); + app.use("/api/test/test", route157); } diff --git a/src/routes/assets/addAudioAssets.ts b/src/routes/assets/addAudioAssets.ts index 6b4b527..7cd89b0 100644 --- a/src/routes/assets/addAudioAssets.ts +++ b/src/routes/assets/addAudioAssets.ts @@ -26,8 +26,19 @@ export default router.post( await Promise.all( assetsItem.map(async (i: { src?: string; base64: string; prompt: string }) => { if (i.base64) { - const savePath = `/${projectId}/assets/audio/${u.uuid()}.mp4`; - await u.oss.writeFile(savePath, i.base64); + const mimeMatch = i.base64.match(/^data:audio\/([^;]+);base64,/); + const mimeExt = mimeMatch ? mimeMatch[1] : "mp3"; + const mimeToExt: Record = { + mpeg: "mp3", + "x-wav": "wav", + "x-aiff": "aiff", + "x-m4a": "m4a", + "x-flac": "flac", + }; + const ext = mimeToExt[mimeExt] ?? mimeExt; + const savePath = `/${projectId}/assets/audio/${u.uuid()}.${ext}`; + const base64Data = i.base64.replace(/^data:[^;]+;base64,/, ""); + await u.oss.writeFile(savePath, base64Data); i.src = savePath; } }), diff --git a/src/routes/assets/updateAudioAssets.ts b/src/routes/assets/updateAudioAssets.ts index 6d112ac..dd384a0 100644 --- a/src/routes/assets/updateAudioAssets.ts +++ b/src/routes/assets/updateAudioAssets.ts @@ -32,8 +32,19 @@ export default router.post( i.src = u.replaceUrl(i.src); } if (i.base64) { - const savePath = `/${projectId}/assets/audio/${u.uuid()}.mp4`; - await u.oss.writeFile(savePath, i.base64); + const mimeMatch = i.base64.match(/^data:audio\/([^;]+);base64,/); + const mimeExt = mimeMatch ? mimeMatch[1] : "mp3"; + const mimeToExt: Record = { + mpeg: "mp3", + "x-wav": "wav", + "x-aiff": "aiff", + "x-m4a": "m4a", + "x-flac": "flac", + }; + const ext = mimeToExt[mimeExt] ?? mimeExt; + const savePath = `/${projectId}/assets/audio/${u.uuid()}.${ext}`; + const base64Data = i.base64.replace(/^data:[^;]+;base64,/, ""); + await u.oss.writeFile(savePath, base64Data); i.src = savePath; } }), diff --git a/src/routes/assetsGenerate/batchGenerateImageAssets.ts b/src/routes/assetsGenerate/batchGenerateImageAssets.ts index b5d6f0c..a0827f6 100644 --- a/src/routes/assetsGenerate/batchGenerateImageAssets.ts +++ b/src/routes/assetsGenerate/batchGenerateImageAssets.ts @@ -130,7 +130,6 @@ export default router.post("/", validateFields(requestSchema), async (req, res) aiImage.save(imagePath); const imageData = await u.db("o_image").where("id", imageId).select("*").first(); - console.log("%c Line:133 🥒 imageData", "background:#465975", imageData); if (!imageData) return res.status(500).send("资产已被删除"); if (!imageData) return; if (imageData.state === "生成失败") return; diff --git a/src/routes/assetsGenerate/cancelGenerate.ts b/src/routes/assetsGenerate/cancelGenerate.ts index 21f21a1..ea4deae 100644 --- a/src/routes/assetsGenerate/cancelGenerate.ts +++ b/src/routes/assetsGenerate/cancelGenerate.ts @@ -13,7 +13,6 @@ export default router.post( }), async (req, res) => { const { id } = req.body; - console.log("%c Line:16 🌭 id", "background:#2eafb0", id); await u.db("o_image").where("id", id).update({ state: "生成失败", }); diff --git a/src/routes/assetsGenerate/generateAssets.ts b/src/routes/assetsGenerate/generateAssets.ts index 7c48412..dbee547 100644 --- a/src/routes/assetsGenerate/generateAssets.ts +++ b/src/routes/assetsGenerate/generateAssets.ts @@ -86,6 +86,8 @@ export default router.post("/", validateFields(requestSchema), async (req, res) type, state: "生成中", assetsId: id, + model: model.split(/:(.+)/)[1], + resolution, }); await u.db("o_assets").where("id", id).update({ imageId }); diff --git a/src/routes/cornerScape/batchBindAudio.ts b/src/routes/cornerScape/batchBindAudio.ts index dbf29a3..44b3e4f 100644 --- a/src/routes/cornerScape/batchBindAudio.ts +++ b/src/routes/cornerScape/batchBindAudio.ts @@ -1,7 +1,7 @@ import express from "express"; import u from "@/utils"; import { z } from "zod"; -import { success } from "@/lib/responseFormat"; +import { error, success } from "@/lib/responseFormat"; import { validateFields } from "@/middleware/middleware"; import { tool, jsonSchema } from "ai"; const router = express.Router(); @@ -16,12 +16,7 @@ export default router.post( }), async (req, res) => { const { projectId, assetsIds, concurrentCount } = req.body; - const assetsData = await u - .db("o_assets") - .where("type", "audio") - .whereIn("id", assetsIds) - .andWhere("projectId", projectId) - .select("id", "name", "describe"); + const assetsData = await u.db("o_assets").whereIn("id", assetsIds).andWhere("projectId", projectId).select("id", "name", "describe"); const audioData = await u .db("o_assets") @@ -29,57 +24,81 @@ export default router.post( .whereNull("assetsId") .andWhere("projectId", projectId) .select("id", "name", "describe"); - async function processGroup() { + + if (!audioData.length) return res.status(400).send(error("暂无设置音频,请先前往资产中心上传音频")); + + const batchSize = concurrentCount ?? 1; + + async function processAsset(asset: (typeof assetsData)[number]) { try { const resultTool = tool({ - description: "返回结果时必须调用这个工具", - inputSchema: jsonSchema<{ result: { id: number; audioIds: number[] }[] }>( + description: "匹配完成后必须调用此工具提交结果", + inputSchema: jsonSchema<{ id: number; audioId: number }>( z .object({ - result: z - .array( - z.object({ - id: z.number(), - audioIds: z.array(z.number()).describe("适配的音频id 无适配内容可以为 空数组"), - }), - ) - .describe("适配的音色列表,id为资产id,audioIds为适配的音频id 无适配内容可以为 空数组"), + id: z.number().describe("资产ID"), + audioId: z.number().nullable().optional().describe("与该资产匹配的音频ID列表,若无合适匹配则返回空数组"), }) .toJSONSchema(), ), - execute: async ({ result }) => { - console.log("[tools] extractAssets result", result); - for (const item of result) { - await u.db("o_assetsRole2Audio").where("assetsRoleId", item.id).delete(); - if (item.audioIds.length) - await u.db("o_assetsRole2Audio").insert(item.audioIds.map((i) => ({ assetsRoleId: item.id, assetsAudioId: i }))); - } + execute: async (result) => { + await u.db("o_assetsRole2Audio").where("assetsRoleId", asset.id).delete(); + if (result?.audioId) await u.db("o_assetsRole2Audio").insert({ assetsRoleId: asset.id, assetsAudioId: result.audioId }); + await u.db("o_assets").where("id", asset.id).update("audioBindState", "已完成"); return "无需回复用户任何内容"; }, }); + const audioList = audioData.map((i) => `- ID:${i.id} | 名称:${i.name} | 描述:${i.describe ?? "无"}`).join("\n"); + const { text } = await u.Ai.Text("universalAi").invoke({ messages: [ { role: "system", - content: `请根据提供的资产内容描述 与 提供的音色 进行匹配,返回适配的音色,结果必须调用 resultTool 工具返回, 调用工具之后你无需回复用户任何内容。`, + content: ` + 你是一个音色匹配助手。 + 你的任务是:根据给定角色资产的名称与描述,从候选音频列表中选出最合适的音色。 + 匹配规则: + 1. 优先根据角色性别、年龄、性格等特征与音色描述进行语义匹配; + 2. 可以为同一角色匹配多个音色(例如主备选); + 3. 若候选列表中没有合适的音色,则返回空数组; + 4. 匹配完成后必须调用 resultTool 工具提交结果,无需额外回复用户。 + `, }, { role: "user", - content: `音频内容:${audioData.map((i) => `Id:${i.id},音色名称:${i.name},描述:${i.describe}`).join("\n")}\n\n - 资产内容:${assetsData.map((i) => `ID:${i.id},名称:${i.name},描述:${i.describe}`).join("\n")}\n\n - 请根据提供的资产内容描述 与 对应已有的音色 进行匹配,返回适配的音色`, + content: ` + ## 候选音频列表 + ${audioList} + ## 待匹配资产 + - ID:${asset.id} | 名称:${asset.name} | 描述:${asset.describe ?? "无"} + 请从候选音频列表中为该资产选出来一个最符合该角色设定的音色,并调用 resultTool 提交结果。 + `, }, ], tools: { resultTool }, }); - console.log("%c Line:44 🍞 text", "background:#f5ce50", text); } catch (e) { - console.error(`提取失败:`, e); - return; + await u.db("o_assets").where("id", asset.id).update("audioBindState", "生成失败"); + console.error(`[bindAudio] 资产 ${asset.id} 处理失败:`, e); } } - await processGroup(); + + async function runWithConcurrency() { + for (let i = 0; i < assetsData.length; i += batchSize) { + const batch = assetsData.slice(i, i + batchSize); + + await Promise.all(batch.map((asset) => processAsset(asset))); + } + } + await u + .db("o_assets") + .whereIn( + "id", + assetsData.map((i) => i.id), + ) + .update("audioBindState", "生成中"); + runWithConcurrency(); res.status(200).send(success()); }, ); diff --git a/src/routes/cornerScape/pollingAudio.ts b/src/routes/cornerScape/pollingAudio.ts new file mode 100644 index 0000000..e195d94 --- /dev/null +++ b/src/routes/cornerScape/pollingAudio.ts @@ -0,0 +1,18 @@ +import express from "express"; +import u from "@/utils"; +import { z } from "zod"; +import { success } from "@/lib/responseFormat"; +import { validateFields } from "@/middleware/middleware"; +const router = express.Router(); + +export default router.post( + "/", + validateFields({ + ids: z.array(z.number()), + }), + async (req, res) => { + const { ids } = req.body; + const data = await u.db("o_assets").whereIn("id", ids).whereNot("audioBindState", "生成中").select("*"); + res.status(200).send(success(data)); + }, +); diff --git a/src/routes/cornerScape/updateAssetsAudio.ts b/src/routes/cornerScape/updateAssetsAudio.ts index a8f6b4d..16f644d 100644 --- a/src/routes/cornerScape/updateAssetsAudio.ts +++ b/src/routes/cornerScape/updateAssetsAudio.ts @@ -1,7 +1,7 @@ import express from "express"; import u from "@/utils"; import { z } from "zod"; -import { success } from "@/lib/responseFormat"; +import { error, success } from "@/lib/responseFormat"; import { validateFields } from "@/middleware/middleware"; const router = express.Router(); @@ -10,13 +10,14 @@ export default router.post( "/", validateFields({ assetsId: z.number(), - audioIds: z.array(z.number()), + audioIds: z.array(z.number()).optional(), }), async (req, res) => { const { assetsId, audioIds } = req.body; + if (audioIds && audioIds.length > 1) return res.status(400).send(error("仅可绑定一个音色")); await u.db("o_assetsRole2Audio").where("assetsRoleId", assetsId).delete(); - if (audioIds.length) { - await u.db("o_assetsRole2Audio").insert(audioIds.map((i: number) => ({ assetsRoleId: assetsId, assetsAudioId: i }))); + if (audioIds && audioIds.length) { + await u.db("o_assetsRole2Audio").insert({ assetsRoleId: assetsId, assetsAudioId: audioIds[0] }); } res.status(200).send(success({ message: "更新音频成功" })); }, diff --git a/src/routes/production/editImage/saveImageFlow.ts b/src/routes/production/editImage/saveImageFlow.ts index 0d3ff59..e7914b7 100644 --- a/src/routes/production/editImage/saveImageFlow.ts +++ b/src/routes/production/editImage/saveImageFlow.ts @@ -14,7 +14,6 @@ export default router.post( async (req, res) => { const { edges, nodes } = req.body; nodes.forEach((node: any) => { - console.log("%c Line:17 🌮 node", "background:#465975", node); if (node.type == "upload") { node.data.image = node.data.image ? u.replaceUrl(node.data.image) : ""; } diff --git a/src/routes/production/storyboard/batchDelete.ts b/src/routes/production/storyboard/batchDelete.ts new file mode 100644 index 0000000..b0c9993 --- /dev/null +++ b/src/routes/production/storyboard/batchDelete.ts @@ -0,0 +1,31 @@ +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({ + ids: z.array(z.number()), + projectId: z.number(), + }), + async (req, res) => { + const { ids, projectId } = req.body; + if (!ids.length) return res.status(400).send(error("请先选择分镜")); + const storyboardDataList = await u.db("o_storyboard").whereIn("id", ids).where("projectId", projectId).select("id", "track", "trackId", "flowId"); + if (!storyboardDataList.length) return res.status(400).send(error("当前选择分镜不存在")); + const flowIds = storyboardDataList.map((i) => i.flowId); + const storyBoardIds = storyboardDataList.map((i) => i.id); + if (flowIds.length) + await u + .db("o_imageFlow") + .whereIn("id", flowIds as number[]) + .delete(); + + await u.db("o_storyboard").whereIn("id", storyBoardIds).delete(); + await u.db("o_assets2Storyboard").whereIn("storyboardId", storyBoardIds).delete(); + res.status(200).send(success({ message: "视频删除成功" })); + }, +); diff --git a/src/routes/production/workbench/batchGeneratePrompt.ts b/src/routes/production/workbench/batchGeneratePrompt.ts new file mode 100644 index 0000000..02ff3fa --- /dev/null +++ b/src/routes/production/workbench/batchGeneratePrompt.ts @@ -0,0 +1,133 @@ +import express from "express"; +import u from "@/utils"; +import { z } from "zod"; +import { success, error } from "@/lib/responseFormat"; +import { validateFields } from "@/middleware/middleware"; +import { info } from "node:console"; +const router = express.Router(); + +export default router.post( + "/", + validateFields({ + projectId: z.number(), + trackData: z.array( + z.object({ + trackId: z.number(), + info: z.array( + z.object({ + id: z.number(), + sources: z.string(), + }), + ), + }), + ), + model: z.string(), + }), + async (req, res) => { + const { trackId, projectId, info, model } = req.body; + //查询参数 + const images = await Promise.all( + info.map(async (item: { id: number; sources: string }) => { + if (item.sources === "storyboard") { + // 查询分镜主信息 + const storyboard = await u + .db("o_storyboard") + .where("o_storyboard.id", item.id) + .select("videoDesc", "prompt", "track", "duration", "shouldGenerateImage") + .first(); + // 查询分镜关联的资产ID + const assetRows = await u.db("o_assets2Storyboard").where("storyboardId", item.id).orderBy("rowid").select("assetId"); + const associateAssetsIds = assetRows.map((row: any) => row.assetId); + return { + ...storyboard, + associateAssetsIds, + _type: "storyboard", // 标记类型,便于后续区分 + }; + } + if (item.sources === "assets") { + // 查询素材 + const assetsData = await u + .db("o_assets") + .leftJoin("o_image", "o_image.id", "o_assets.imageId") + .where("o_assets.id", item.id) + .select("o_assets.id", "o_assets.type", "o_assets.name", "o_image.filePath") + .first(); + return { + ...assetsData, + _type: "assets", // 标记类型 + }; + } + }), + ); + + // 拆分 assets 和 storyboard + const assets: any[] = []; + const storyboard: any[] = []; + for (const item of images) { + if (!item) continue; // 忽略空 + if (item._type === "assets") + assets.push({ + id: item.id, + type: item.type, + name: item.name, + filePath: item.filePath, + }); + if (item._type === "storyboard") + storyboard.push({ + videoDesc: item.videoDesc, + prompt: item.prompt, + track: item.track, + duration: item.duration, + associateAssetsIds: item.associateAssetsIds, + shouldGenerateImage: item.shouldGenerateImage, + }); + } + + const [id, modelData] = model.split(/:(.+)/); + const projectData = await u.db("o_project").select("*").where({ id: projectId }).first(); + const videoPrompt = await u.db("o_prompt").where("type", "videoPromptGeneration").first(); + let videoPromptGeneration = "" as string | undefined; + if (videoPrompt && videoPrompt.useData) { + videoPromptGeneration = videoPrompt.useData; + } else { + videoPromptGeneration = videoPrompt?.data ?? undefined; + } + const artStyle = projectData?.artStyle || "无"; + const visualManual = u.getArtPrompt(artStyle, "art_skills", "art_storyboard_video"); + const content = ` + **模型名称**:${modelData}, + **资产信息**(角色、场景、道具、音频):${assets + .filter((i) => i.filePath) + .map((i) => `[${i.id},${i.type},${i.name}]`) + .join(",")}, + **分镜信息**:${storyboard.map( + (i) => ``, + )}, + `; + + try { + const { text } = await u.Ai.Text("universalAi").invoke({ + system: videoPromptGeneration, + messages: [ + { + role: "assistant", + content: `${visualManual}`, + }, + { + role: "user", + content: content, + }, + ], + }); + await u.db("o_videoTrack").where({ id: trackId }).update({ + prompt: text, + }); + res.status(200).send(success(text)); + } catch (e) { + res.status(400).send(error(u.error(e).message)); + } + }, +); diff --git a/src/routes/production/workbench/batchGenerateVideo.ts b/src/routes/production/workbench/batchGenerateVideo.ts new file mode 100644 index 0000000..d36da55 --- /dev/null +++ b/src/routes/production/workbench/batchGenerateVideo.ts @@ -0,0 +1,148 @@ +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"; +import { ReferenceList } from "@/utils/ai"; +const router = express.Router(); + +type Type = "imageReference" | "startImage" | "endImage" | "videoReference" | "audioReference"; +interface UploadItem { + fileType: "image" | "video" | "audio"; + type: Type; + sources?: "assets" | "storyboard"; + id?: number; + src?: string; + label?: string; + prompt?: string; +} + +export default router.post( + "/", + validateFields({ + projectId: z.number(), + scriptId: z.number(), + trackData: z.array( + z.object({ + uploadData: z.array( + z.object({ + id: z.number(), + sources: z.string(), + }), + ), + trackId: z.number(), + prompt: z.string(), + duration: z.number(), + }), + ), + model: z.string(), + mode: z.string(), + resolution: z.string(), + audio: z.boolean().optional(), + }), + async (req, res) => { + const { scriptId, projectId, trackData, model, resolution, audio, mode } = req.body; + + let modeData = []; + if (Array.isArray(mode)) { + } else if (typeof mode === "string" && mode.startsWith('["') && mode.endsWith('"]')) { + try { + modeData = JSON.parse(mode); + } catch (e) {} + } + + // 获取生成视频比例 + const ratio = await u.db("o_project").select("videoRatio").where("id", projectId).first(); + + // 为每个 track 预处理数据并插入数据库,返回任务列表 + const tasks = await Promise.all( + (trackData as { uploadData: { id: number; sources: string }[]; trackId: number; prompt: string; duration: number }[]).map(async (track) => { + const { uploadData, trackId, prompt, duration } = track; + + // 查询出图片数据 + const images = await Promise.all( + uploadData.map(async (item) => { + if (item.sources === "storyboard") { + const filePath = await u.db("o_storyboard").where("id", item.id).select("filePath").first(); + return { path: filePath?.filePath, sources: "storyBoard" }; + } + if (item.sources === "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", "o_image.type") + .first(); + return { path: filePath?.filePath, sources: filePath.type }; + } + }), + ); + + const videoPath = `/${projectId}/video/${uuidv4()}.mp4`; + const [videoId] = await u.db("o_video").insert({ + filePath: videoPath, + time: Date.now(), + state: "生成中", + scriptId, + projectId, + videoTrackId: trackId, + }); + + return { videoId, videoPath, prompt, duration, images, trackId }; + }), + ); + + res.status(200).send(success(tasks.map((t) => ({ videoId: t.videoId, trackId: t.trackId })))); + + // 分批执行,3个一批 + (async () => { + const batchSize = 3; + for (let i = 0; i < tasks.length; i += batchSize) { + const batch = tasks.slice(i, i + batchSize); + await Promise.all( + batch.map(async ({ videoId, videoPath, prompt, duration, images }) => { + // 调用时再转 base64 + const base64 = await Promise.all( + images.map(async (item) => { + if (!item) return null; + return { base64: await u.oss.getImageBase64(item.path), type: item.sources == "audio" ? "audio" : "image" }; + }), + ); + const relatedObjects = { projectId, videoId, scriptId, type: "视频" }; + const aiVideo = u.Ai.Video(model); + return aiVideo + .run( + { + prompt, + referenceList: base64.filter(Boolean) as ReferenceList[], + mode: modeData.length > 0 ? modeData : mode, + duration, + aspectRatio: (ratio?.videoRatio as "16:9" | "9:16") || "16:9", + resolution, + audio, + }, + { + projectId, + taskClass: "视频生成", + describe: "根据提示词生成视频", + relatedObjects: JSON.stringify(relatedObjects), + }, + ) + .then(() => aiVideo.save(videoPath)) + .then(() => u.db("o_video").where("id", videoId).update({ state: "生成成功" })) + .catch(async (error: any) => { + await u + .db("o_video") + .where("id", videoId) + .update({ + state: "生成失败", + errorReason: u.error(error).message, + }); + }); + }), + ); + } + })(); + }, +); diff --git a/src/routes/production/workbench/generateVideo.ts b/src/routes/production/workbench/generateVideo.ts index a5e388d..53432b1 100644 --- a/src/routes/production/workbench/generateVideo.ts +++ b/src/routes/production/workbench/generateVideo.ts @@ -4,6 +4,7 @@ import { z } from "zod"; import { v4 as uuidv4 } from "uuid"; import { success } from "@/lib/responseFormat"; import { validateFields } from "@/middleware/middleware"; +import { ReferenceList } from "@/utils/ai"; const router = express.Router(); type Type = "imageReference" | "startImage" | "endImage" | "videoReference" | "audioReference"; @@ -43,7 +44,7 @@ export default router.post( } else if (typeof mode === "string" && mode.startsWith('["') && mode.endsWith('"]')) { try { modeData = JSON.parse(mode); - } catch (e) { } + } catch (e) {} } //获取生成视频比例 const ratio = await u.db("o_project").select("videoRatio").where("id", projectId).first(); @@ -53,16 +54,16 @@ export default router.post( uploadData.map(async (item: UploadItem) => { if (item.sources === "storyboard") { const filePath = await u.db("o_storyboard").where("id", item.id).select("filePath").first(); - return filePath?.filePath; + return { path: filePath?.filePath, sources: "storyBoard" }; } if (item.sources === "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") + .select("o_image.filePath", "o_image.type") .first(); - return filePath?.filePath; + return { path: filePath?.filePath, sources: filePath.type }; } }), ); @@ -70,7 +71,7 @@ export default router.post( const base64 = await Promise.all( images.map(async (item) => { if (!item) return null; - return await u.oss.getImageBase64(item); + return { base64: await u.oss.getImageBase64(item.path), type: item.sources == "audio" ? "audio" : "image" }; }), ); //新增 @@ -95,7 +96,7 @@ export default router.post( await aiVideo.run( { prompt, - referenceList: base64.filter((item) => item !== null).map((item) => ({ type: "image" as const, base64: item! })), + referenceList: base64.filter(Boolean) as ReferenceList[], mode: modeData.length > 0 ? modeData : mode, duration, aspectRatio: (ratio?.videoRatio as "16:9" | "9:16") || "16:9", diff --git a/src/routes/production/workbench/generateVideoPrompt.ts b/src/routes/production/workbench/generateVideoPrompt.ts index 51b09f1..f05761e 100644 --- a/src/routes/production/workbench/generateVideoPrompt.ts +++ b/src/routes/production/workbench/generateVideoPrompt.ts @@ -78,6 +78,7 @@ export default router.post( shouldGenerateImage: item.shouldGenerateImage, }); } + const [id, modelData] = model.split(/:(.+)/); const projectData = await u.db("o_project").select("*").where({ id: projectId }).first(); const videoPrompt = await u.db("o_prompt").where("type", "videoPromptGeneration").first(); @@ -91,7 +92,7 @@ export default router.post( const visualManual = u.getArtPrompt(artStyle, "art_skills", "art_storyboard_video"); const content = ` **模型名称**:${modelData}, - **资产信息**(角色、场景、道具):${assets + **资产信息**(角色、场景、道具、音频):${assets .filter((i) => i.filePath) .map((i) => `[${i.id},${i.type},${i.name}]`) .join(",")}, diff --git a/src/routes/production/workbench/getGenerateData.ts b/src/routes/production/workbench/getGenerateData.ts index 3492155..79e2536 100644 --- a/src/routes/production/workbench/getGenerateData.ts +++ b/src/routes/production/workbench/getGenerateData.ts @@ -82,8 +82,17 @@ export default router.post( }); // 按 storyboardId 分组的资产数据,key 为 storyboardId const otherDataMap: Record = {}; + // 解析 videoMode 中 audioReference 的数量,例如 'audioReference:3' => 3 + const audioReferenceCount = (() => { + if (!Array.isArray(videoMode)) return 0; + const item = (videoMode as string[]).find((v) => v.toLowerCase().startsWith("audioreference:")); + if (!item) return 0; + const num = parseInt(item.split(":")[1], 10); + return isNaN(num) ? 0 : num; + })(); if (isRef) { const storyIds = storyboardList.map((s) => s.id); + const assetDatas = await u .db("o_assets2Storyboard") .leftJoin("o_assets", "o_assets2Storyboard.assetId", "o_assets.id") @@ -91,6 +100,38 @@ export default router.post( .whereIn("o_assets2Storyboard.storyboardId", storyIds as number[]) .select("o_assets.*", "o_image.filePath", "o_assets2Storyboard.storyboardId"); + const queryAudioIds = [...assetDatas.map((i) => i.id!), ...assetDatas.map((i) => i.assetsId!)].filter(Boolean); + const assets2AudioData = await u + .db("o_assetsRole2Audio") + .leftJoin("o_assets", "o_assets.assetsId", "o_assetsRole2Audio.assetsAudioId") + .leftJoin("o_image", "o_image.id", "o_assets.imageId") + .whereIn("o_assetsRole2Audio.assetsRoleId", queryAudioIds) + .select( + "o_assets.id", + "o_assets.name", + "o_assetsRole2Audio.assetsRoleId", + "o_assets.describe", + "o_assets.type", + "o_assets.prompt", + "o_image.filePath", + ); + const audioRecord: Record = {}; + await Promise.all( + assets2AudioData.map(async (i) => { + if (!audioRecord[i.assetsRoleId]) audioRecord[i.assetsRoleId] = []; + audioRecord[i.assetsRoleId].push({ + id: i.id, + name: i.name, + describe: i.describe, + type: i.type, + fileType: "audio" as const, + sources: "assets", + prompt: i.prompt, + src: i.filePath ? await u.oss.getFileUrl(i.filePath) : "", + }); + }), + ); + await Promise.all( assetDatas.map(async (i) => { const item = { @@ -105,6 +146,8 @@ export default router.post( const sid = i.storyboardId as number; if (!otherDataMap[sid]) otherDataMap[sid] = []; otherDataMap[sid].push(item); + if (audioRecord[i.id]) otherDataMap[sid].push(...audioRecord[i.id]); + if (audioRecord[i.assetsId]) otherDataMap[sid].push(...audioRecord[i.assetsId]); }), ); } @@ -128,14 +171,27 @@ export default router.post( medias: (() => { const storyboardMedias = storyboardTrackRecord[trackId] ?? []; const assetMedias = storyboardMedias.flatMap((s) => otherDataMap[s.id] ?? []); + const seenAssetIds = new Set(); const uniqueAssets = assetMedias.filter((a) => { if (seenAssetIds.has(a.id)) return false; seenAssetIds.add(a.id); return true; }); - const hasImageAssetData = uniqueAssets.filter((i) => i.src); - const notHasImageAssetData = uniqueAssets.filter((i) => !i.src); + + // 有 audioReference 时,按数量截取 audio 类型资产 + const audioCountMap: Record = {}; + const filteredAssets = uniqueAssets.filter((a) => { + if (a.fileType !== "audio" || audioReferenceCount === 0) return true; + const key = String(a.id); + audioCountMap[key] = (audioCountMap[key] ?? 0) + 1; + // 统计当前 track 内 audio 总数,超过上限则过滤 + const totalAudio = Object.values(audioCountMap).reduce((s, n) => s + n, 0); + return totalAudio <= audioReferenceCount; + }); + + const hasImageAssetData = filteredAssets.filter((i) => i.src); + const notHasImageAssetData = filteredAssets.filter((i) => !i.src); return [...hasImageAssetData, ...storyboardMedias, ...notHasImageAssetData]; })(), diff --git a/src/routes/setting/fileManagement/openFolder.ts b/src/routes/setting/fileManagement/openFolder.ts index 6427534..23cd1ec 100644 --- a/src/routes/setting/fileManagement/openFolder.ts +++ b/src/routes/setting/fileManagement/openFolder.ts @@ -20,7 +20,6 @@ export default router.post( const { path: folderPath } = req.body; const platform = process.platform; const target = u.getPath(folderPath); - console.log("%c Line:23 🎂 target", "background:#fca650", target); const cmd = platform === "win32" ? `explorer "${target}"` : platform === "darwin" ? `open "${target}"` : `xdg-open "${target}"`; exec(cmd, (err) => { if (err) { diff --git a/src/types/database.d.ts b/src/types/database.d.ts index eb4d216..4ece20a 100644 --- a/src/types/database.d.ts +++ b/src/types/database.d.ts @@ -1,6 +1,22 @@ -// @db-hash 5364c2db0bf42b520761b813ce040489 +// @db-hash ef0c3cdd7111f4f5d87b82df06bdd72a //该文件由脚本自动生成,请勿手动修改 +export interface _o_assets_old_20260428 { + 'assetsId'?: number | null; + 'describe'?: string | null; + 'flowId'?: number | null; + 'id'?: number; + 'imageId'?: number | null; + 'name'?: string | null; + 'projectId'?: number | null; + 'prompt'?: string | null; + 'promptErrorReason'?: string | null; + 'promptState'?: string | null; + 'remark'?: string | null; + 'scriptId'?: number | null; + 'startTime'?: number | null; + 'type'?: string | null; +} export interface memories { 'content': string; 'createTime': number; @@ -23,7 +39,6 @@ export interface o_agentDeploy { 'modelName'?: string | null; 'name'?: string | null; 'temperature'?: number | null; - 'topP'?: number | null; 'type'?: string | null; 'vendorId'?: string | null; } @@ -45,6 +60,7 @@ export interface o_artStyle { } export interface o_assets { 'assetsId'?: number | null; + 'audioBindState'?: number | null; 'describe'?: string | null; 'flowId'?: number | null; 'id'?: number; @@ -211,6 +227,7 @@ export interface o_user { 'password'?: string | null; } export interface o_vendorConfig { + 'code'?: string | null; 'enable'?: number | null; 'id'?: string; 'inputValues'?: string | null; @@ -239,6 +256,7 @@ export interface o_videoTrack { } export interface DB { + "_o_assets_old_20260428": _o_assets_old_20260428; "memories": memories; "o_agentDeploy": o_agentDeploy; "o_agentWorkData": o_agentWorkData; diff --git a/src/utils/ai.ts b/src/utils/ai.ts index c0ee47b..eee8137 100644 --- a/src/utils/ai.ts +++ b/src/utils/ai.ts @@ -189,7 +189,7 @@ function referenceList2imageBase642(id: string, input: any) { return input; } -type ReferenceList = { type: "image"; base64: string } | { type: "audio"; base64: string } | { type: "video"; base64: string }; +export type ReferenceList = { type: "image"; base64: string } | { type: "audio"; base64: string } | { type: "video"; base64: string }; interface ImageConfig { prompt: string; diff --git a/src/utils/replaceUrl.ts b/src/utils/replaceUrl.ts index 4f95cb2..d9407c0 100644 --- a/src/utils/replaceUrl.ts +++ b/src/utils/replaceUrl.ts @@ -1,3 +1,5 @@ +import path from "node:path"; + export default function replaceUrl(url: string): string { if (typeof url !== 'string' || !url.trim()) return ''; let cleanedPath = ''; @@ -5,8 +7,19 @@ export default function replaceUrl(url: string): string { const pathname = new URL(url).pathname; cleanedPath = pathname.replace(/^\/oss/, '').replace(/^\/smallImage/, ''); } catch (e) { - // 如果不是有效的URL,则直接返回原字符串 + // 如果不是有效的URL,则直接使用原字符串 cleanedPath = url; } - return cleanedPath; + + // 防止路径穿越:对路径进行规范化后,确保不含上溯分量 + // 使用 posix 规范化(保持 / 分隔符),去除所有 .. 和 . + const normalized = path.posix.normalize(cleanedPath); + + // 规范化后若路径以 ../ 开头或等于 .. 则说明发生了路径穿越,拒绝并返回空字符串 + if (normalized.startsWith('../') || normalized === '..') { + return ''; + } + + // 去除前导斜杠,保证返回的是相对路径 + return normalized.replace(/^\/+/, ''); }