diff --git a/data/version.txt b/data/version.txt index 8cfbc90..8428158 100644 --- a/data/version.txt +++ b/data/version.txt @@ -1 +1 @@ -1.1.1 \ No newline at end of file +1.1.2 \ No newline at end of file diff --git a/package.json b/package.json index 0e4cd44..7e84ac7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "toonflow", - "version": "1.1.1", + "version": "1.1.2", "description": "Toonflow 是一款 AI 短剧漫剧工具,能够利用 AI 技术将小说自动转化为剧本,并结合 AI 生成的图片和视频,实现高效的短剧创作。", "author": "HBAI-Ltd ", "license": "Apache-2.0", @@ -97,7 +97,6 @@ "overrides": { "@rmp135/sql-ts": { "better-sqlite3": "^12.8.0" - }, - "sqlite3": "^6.0.1" + } } } diff --git a/src/router.ts b/src/router.ts index 6babdd6..e04828c 100644 --- a/src/router.ts +++ b/src/router.ts @@ -1,4 +1,4 @@ -// @routes-hash a06e43d398afaba14e067c04a027c18a +// @routes-hash 5f94013d5d29facaed754713858ed40b import { Express } from "express"; import route1 from "./routes/agents/clearMemory"; @@ -58,30 +58,30 @@ import route54 from "./routes/production/editImage/getImageFlow"; import route55 from "./routes/production/editImage/saveImageFlow"; import route56 from "./routes/production/editImage/updateImageFlow"; import route57 from "./routes/production/editImage/uploadImage"; -import route58 from "./routes/production/exportImage"; -import route59 from "./routes/production/getFlowData"; -import route60 from "./routes/production/getProductionData"; -import route61 from "./routes/production/getStoryboardData"; -import route62 from "./routes/production/saveFlowData"; -import route63 from "./routes/production/storyboard/addStoryboard"; -import route64 from "./routes/production/storyboard/batchAddStoryboardInfo"; -import route65 from "./routes/production/storyboard/batchGenerateImage"; -import route66 from "./routes/production/storyboard/downPreviewImage"; -import route67 from "./routes/production/storyboard/editStoryboardInfo"; -import route68 from "./routes/production/storyboard/getStoryboardData"; -import route69 from "./routes/production/storyboard/pollingImage"; -import route70 from "./routes/production/storyboard/previewImage"; -import route71 from "./routes/production/storyboard/removeFrame"; -import route72 from "./routes/production/storyboard/updateStoryboardUrl"; -import route73 from "./routes/production/workbench/addTrack"; -import route74 from "./routes/production/workbench/deleteTrack"; -import route75 from "./routes/production/workbench/delVideo"; -import route76 from "./routes/production/workbench/generateVideo"; -import route77 from "./routes/production/workbench/generateVideoPrompt"; -import route78 from "./routes/production/workbench/getGenerateData"; -import route79 from "./routes/production/workbench/getVideoList"; -import route80 from "./routes/production/workbench/getVideoModelDetail"; -import route81 from "./routes/production/workbench/selectVideo"; +import route58 from "./routes/production/getFlowData"; +import route59 from "./routes/production/getProductionData"; +import route60 from "./routes/production/getStoryboardData"; +import route61 from "./routes/production/saveFlowData"; +import route62 from "./routes/production/storyboard/addStoryboard"; +import route63 from "./routes/production/storyboard/batchAddStoryboardInfo"; +import route64 from "./routes/production/storyboard/batchGenerateImage"; +import route65 from "./routes/production/storyboard/downPreviewImage"; +import route66 from "./routes/production/storyboard/editStoryboardInfo"; +import route67 from "./routes/production/storyboard/getStoryboardData"; +import route68 from "./routes/production/storyboard/pollingImage"; +import route69 from "./routes/production/storyboard/previewImage"; +import route70 from "./routes/production/storyboard/removeFrame"; +import route71 from "./routes/production/storyboard/updateStoryboardUrl"; +import route72 from "./routes/production/workbench/addTrack"; +import route73 from "./routes/production/workbench/deleteTrack"; +import route74 from "./routes/production/workbench/delVideo"; +import route75 from "./routes/production/workbench/generateVideo"; +import route76 from "./routes/production/workbench/generateVideoPrompt"; +import route77 from "./routes/production/workbench/getGenerateData"; +import route78 from "./routes/production/workbench/getVideoList"; +import route79 from "./routes/production/workbench/getVideoModelDetail"; +import route80 from "./routes/production/workbench/selectVideo"; +import route81 from "./routes/production/workbench/updateVideoPrompt"; import route82 from "./routes/project/addDirectorManual"; import route83 from "./routes/project/addProject"; import route84 from "./routes/project/addVisualManual"; @@ -198,30 +198,30 @@ export default async (app: Express) => { app.use("/api/production/editImage/saveImageFlow", route55); app.use("/api/production/editImage/updateImageFlow", route56); app.use("/api/production/editImage/uploadImage", route57); - app.use("/api/production/exportImage", route58); - app.use("/api/production/getFlowData", route59); - app.use("/api/production/getProductionData", route60); - app.use("/api/production/getStoryboardData", route61); - app.use("/api/production/saveFlowData", route62); - app.use("/api/production/storyboard/addStoryboard", route63); - app.use("/api/production/storyboard/batchAddStoryboardInfo", route64); - app.use("/api/production/storyboard/batchGenerateImage", route65); - app.use("/api/production/storyboard/downPreviewImage", route66); - app.use("/api/production/storyboard/editStoryboardInfo", route67); - app.use("/api/production/storyboard/getStoryboardData", route68); - app.use("/api/production/storyboard/pollingImage", route69); - app.use("/api/production/storyboard/previewImage", route70); - app.use("/api/production/storyboard/removeFrame", route71); - app.use("/api/production/storyboard/updateStoryboardUrl", route72); - app.use("/api/production/workbench/addTrack", route73); - app.use("/api/production/workbench/deleteTrack", route74); - app.use("/api/production/workbench/delVideo", route75); - app.use("/api/production/workbench/generateVideo", route76); - app.use("/api/production/workbench/generateVideoPrompt", route77); - app.use("/api/production/workbench/getGenerateData", route78); - app.use("/api/production/workbench/getVideoList", route79); - app.use("/api/production/workbench/getVideoModelDetail", route80); - app.use("/api/production/workbench/selectVideo", route81); + app.use("/api/production/getFlowData", route58); + app.use("/api/production/getProductionData", route59); + app.use("/api/production/getStoryboardData", route60); + app.use("/api/production/saveFlowData", route61); + app.use("/api/production/storyboard/addStoryboard", route62); + app.use("/api/production/storyboard/batchAddStoryboardInfo", route63); + app.use("/api/production/storyboard/batchGenerateImage", route64); + app.use("/api/production/storyboard/downPreviewImage", route65); + app.use("/api/production/storyboard/editStoryboardInfo", route66); + app.use("/api/production/storyboard/getStoryboardData", route67); + app.use("/api/production/storyboard/pollingImage", route68); + app.use("/api/production/storyboard/previewImage", route69); + app.use("/api/production/storyboard/removeFrame", route70); + app.use("/api/production/storyboard/updateStoryboardUrl", route71); + app.use("/api/production/workbench/addTrack", route72); + app.use("/api/production/workbench/deleteTrack", route73); + app.use("/api/production/workbench/delVideo", route74); + app.use("/api/production/workbench/generateVideo", route75); + app.use("/api/production/workbench/generateVideoPrompt", route76); + app.use("/api/production/workbench/getGenerateData", route77); + app.use("/api/production/workbench/getVideoList", route78); + app.use("/api/production/workbench/getVideoModelDetail", route79); + app.use("/api/production/workbench/selectVideo", route80); + app.use("/api/production/workbench/updateVideoPrompt", route81); app.use("/api/project/addDirectorManual", route82); app.use("/api/project/addProject", route83); app.use("/api/project/addVisualManual", route84); diff --git a/src/routes/assets/addAssets.ts b/src/routes/assets/addAssets.ts index 4ff53e5..a4d6879 100644 --- a/src/routes/assets/addAssets.ts +++ b/src/routes/assets/addAssets.ts @@ -13,7 +13,7 @@ export default router.post( describe: z.string(), type: z.string(), projectId: z.number(), - remark: z.string(), + remark: z.string().optional().nullable(), prompt: z.string().optional().nullable(), }), async (req, res) => { diff --git a/src/routes/assets/updateAssets.ts b/src/routes/assets/updateAssets.ts index efabd83..7cb98b3 100644 --- a/src/routes/assets/updateAssets.ts +++ b/src/routes/assets/updateAssets.ts @@ -8,22 +8,22 @@ const router = express.Router(); // 更新资产 export default router.post( - "/", - validateFields({ - id: z.number(), - name: z.string(), - describe: z.string(), - remark: z.string(), - prompt: z.string().optional().nullable(), - }), - async (req, res) => { - const { id, name, describe, remark, prompt } = req.body; - await u.db("o_assets").where({ id }).update({ - name, - describe, - remark, - prompt, - }); - res.status(200).send(success({ message: "更新资产成功" })); - }, + "/", + validateFields({ + id: z.number(), + name: z.string(), + describe: z.string(), + remark: z.string().optional().nullable(), + prompt: z.string().optional().nullable(), + }), + async (req, res) => { + const { id, name, describe, remark, prompt } = req.body; + await u.db("o_assets").where({ id }).update({ + name, + describe, + remark, + prompt, + }); + res.status(200).send(success({ message: "更新资产成功" })); + }, ); diff --git a/src/routes/production/exportImage.ts b/src/routes/production/exportImage.ts deleted file mode 100644 index 71a5e99..0000000 --- a/src/routes/production/exportImage.ts +++ /dev/null @@ -1,40 +0,0 @@ -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(); -import compressing from "compressing"; -import path from "path"; -import getPath from "@/utils/getPath"; - -export default router.post( - "/", - validateFields({ - shotId: z.array( - z.object({ - id: z.string(), - }), - ), - }), - async (req, res) => { - const { shotId } = req.body; - const id = shotId.map((item: { id: string }) => item.id); - const data = await u.db("o_storyboard").whereIn("id", id); - const result = await Promise.all( - data.map(async (item) => { - const url = await u.oss.getFileUrl(item.filePath!); - return { ...item, url }; - }), - ); - const zipStream = new compressing.zip.Stream(); - result.forEach((item, index) => { - const ext = (item.filePath?.split(".").pop() || "png").toLowerCase(); - const absPath = path.join(getPath("oss"), item.filePath!); - zipStream.addEntry(absPath, { relativePath: `${index}.${ext}` }); - }); - res.setHeader("Content-Type", "application/zip"); - res.setHeader("Content-Disposition", "attachment; filename=export.zip"); - zipStream.pipe(res); - }, -); diff --git a/src/routes/production/workbench/addTrack.ts b/src/routes/production/workbench/addTrack.ts index e465209..17e346e 100644 --- a/src/routes/production/workbench/addTrack.ts +++ b/src/routes/production/workbench/addTrack.ts @@ -9,12 +9,14 @@ export default router.post( validateFields({ projectId: z.number(), scriptId: z.number(), + duration: z.number().optional(), }), async (req, res) => { - const { projectId, scriptId } = req.body; + const { projectId, scriptId, duration } = req.body; const [id] = await u.db("o_videoTrack").insert({ projectId, scriptId, + duration, }); res.status(200).send(success(id)); }, diff --git a/src/routes/production/workbench/generateVideo.ts b/src/routes/production/workbench/generateVideo.ts index c24c12b..9587fd2 100644 --- a/src/routes/production/workbench/generateVideo.ts +++ b/src/routes/production/workbench/generateVideo.ts @@ -38,6 +38,13 @@ export default router.post( }), async (req, res) => { const { scriptId, projectId, prompt, uploadData, model, duration, resolution, audio, mode, trackId } = 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(); const videoPath = `/${projectId}/video/${uuidv4()}.mp4`; //视频保存路径 @@ -89,7 +96,7 @@ export default router.post( { prompt, imageBase64: base64.filter((item) => item !== null) as string[], - mode, + mode: modeData.length > 0 ? modeData : mode, duration, aspectRatio: (ratio?.videoRatio as `${number}:${number}`) || "16:9", resolution, diff --git a/src/routes/production/workbench/getGenerateData.ts b/src/routes/production/workbench/getGenerateData.ts index 07dd843..7647e09 100644 --- a/src/routes/production/workbench/getGenerateData.ts +++ b/src/routes/production/workbench/getGenerateData.ts @@ -38,6 +38,9 @@ export default router.post( async (req, res) => { const { projectId, scriptId } = req.body; const projectData = await u.db("o_project").where("id", projectId).select("id", "videoModel").first(); + if (!projectData?.videoModel) { + return res.status(400).json(success("项目未配置视频模型")); + } const [videoId, videoModelName] = projectData.videoModel.split(":"); const vendorData = await u.db("o_vendorConfig").where("id", videoId).select("models").first(); const models = JSON.parse(vendorData!.models!); @@ -135,7 +138,7 @@ export default router.post( .map(async (v) => ({ id: v.id!, src: v.filePath ? await u.oss.getFileUrl(v.filePath) : "", - state: v.state === "done" ? "已完成" : v.state === "generating" ? "生成中" : v.state === "error" ? "生成失败" : "未生成", + state: v.state === "已完成" ? "已完成" : v.state === "生成中" ? "生成中" : v.state === "生成失败" ? "生成失败" : "未生成", })), ), }); diff --git a/src/routes/production/workbench/updateVideoPrompt.ts b/src/routes/production/workbench/updateVideoPrompt.ts new file mode 100644 index 0000000..5124875 --- /dev/null +++ b/src/routes/production/workbench/updateVideoPrompt.ts @@ -0,0 +1,22 @@ +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({ + id: z.number(), + prompt: z.string().optional(), + duration: z.number().optional(), + }), + async (req, res) => { + const { id, prompt, duration } = req.body; + await u.db("o_videoTrack").where("id", id).update({ + prompt, + duration, + }); + res.status(200).send(success("更新成功")); + }, +);