Merge branch 'develop' of https://github.com/HBAI-Ltd/Toonflow-app into develop
# Conflicts: # src/router.ts # src/types/database.d.ts
This commit is contained in:
commit
2a15c144ae
13
README.md
13
README.md
@ -103,8 +103,8 @@ https://www.bilibili.com/video/BV1na6wB6Ea2
|
|||||||
| 操作系统 | GitHub 下载 | 夸克网盘下载 | 说明 |
|
| 操作系统 | GitHub 下载 | 夸克网盘下载 | 说明 |
|
||||||
| :------: | :----------------------------------------------------------- | :---------------------------------------------- | :------------- |
|
| :------: | :----------------------------------------------------------- | :---------------------------------------------- | :------------- |
|
||||||
| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [夸克网盘](https://pan.quark.cn/s/94ef07509df0) | 官方发布安装包 |
|
| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [夸克网盘](https://pan.quark.cn/s/94ef07509df0) | 官方发布安装包 |
|
||||||
| Linux | ⚙️ 敬请期待 | ⚙️ 敬请期待 | 即将发布 |
|
| Linux | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [夸克网盘](https://pan.quark.cn/s/94ef07509df0) | 官方发布安装包 |
|
||||||
| macOS | ⚙️ 敬请期待 | ⚙️ 敬请期待 | 即将发布 |
|
| macOS | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [夸克网盘](https://pan.quark.cn/s/94ef07509df0) | 官方发布安装包 |
|
||||||
|
|
||||||
> 目前仅支持 Windows 版本,其他系统将陆续开放。
|
> 目前仅支持 Windows 版本,其他系统将陆续开放。
|
||||||
|
|
||||||
@ -530,10 +530,11 @@ pm2 monit # 监控面板
|
|||||||
|
|
||||||
~~交流群 12~~
|
~~交流群 12~~
|
||||||
|
|
||||||
交流群 13:
|
~~交流群 13~~
|
||||||
|
|
||||||
<img src="./docs/chat13QR.jpg?r=2" alt="Toonflow Logo" height="400"/>
|
拉群小助手:
|
||||||
<p>使用微信扫码添加,二维码过期可提交 Issues 提醒更新</p>
|
|
||||||
|
<img src="./docs/QR.png" alt="Toonflow Logo" height="400"/>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -555,7 +556,7 @@ Toonflow 基于 AGPL-3.0 协议开源发布,许可证详情:https://www.gnu.
|
|||||||
|
|
||||||
# ⭐️ 星标历史
|
# ⭐️ 星标历史
|
||||||
|
|
||||||
[](https://www.star-history.com/#HBAI-Ltd/Toonflow-app&type=date&legend=top-left)
|
[](https://www.star-history.com/#HBAI-Ltd/Toonflow-app&type=timeline&legend=top-left)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
BIN
docs/QR.png
Normal file
BIN
docs/QR.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 139 KiB |
BIN
docs/chat12QR.jpg
Normal file
BIN
docs/chat12QR.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 254 KiB |
BIN
docs/chat13QR.jpg
Normal file
BIN
docs/chat13QR.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 172 KiB |
1411
output.json
Normal file
1411
output.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -317,6 +317,10 @@ export default async (cells: { prompt: string }[], scriptId: number, projectId:
|
|||||||
size: "4K",
|
size: "4K",
|
||||||
aspectRatio: projectInfo?.videoRatio ? (projectInfo.videoRatio as any) : "16:9",
|
aspectRatio: projectInfo?.videoRatio ? (projectInfo.videoRatio as any) : "16:9",
|
||||||
imageBase64: processedImages.map((buf) => buf.toString("base64")),
|
imageBase64: processedImages.map((buf) => buf.toString("base64")),
|
||||||
|
taskClass: "分镜图生成",
|
||||||
|
name: `分镜图-${outline?.title || "未知剧集"}`,
|
||||||
|
describe: prompts,
|
||||||
|
projectId,
|
||||||
},
|
},
|
||||||
apiConfig,
|
apiConfig,
|
||||||
);
|
);
|
||||||
|
|||||||
1411
src/lib/artStyle.ts
Normal file
1411
src/lib/artStyle.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
|||||||
import { Knex } from "knex";
|
import { Knex } from "knex";
|
||||||
import { v4 as uuid } from "uuid";
|
import { v4 as uuid } from "uuid";
|
||||||
|
import { artStyle } from "./artStyle";
|
||||||
interface TableSchema {
|
interface TableSchema {
|
||||||
name: string;
|
name: string;
|
||||||
builder: (table: Knex.CreateTableBuilder) => void;
|
builder: (table: Knex.CreateTableBuilder) => void;
|
||||||
@ -96,6 +97,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
|||||||
name: "t_project",
|
name: "t_project",
|
||||||
builder: (table) => {
|
builder: (table) => {
|
||||||
table.integer("id");
|
table.integer("id");
|
||||||
|
table.string("projectType");
|
||||||
table.text("name");
|
table.text("name");
|
||||||
table.text("intro");
|
table.text("intro");
|
||||||
table.text("type");
|
table.text("type");
|
||||||
@ -160,20 +162,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
|||||||
table.unique(["id"]);
|
table.unique(["id"]);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "t_taskList",
|
|
||||||
builder: (table) => {
|
|
||||||
table.integer("id").notNullable();
|
|
||||||
table.integer("projectName");
|
|
||||||
table.text("name");
|
|
||||||
table.text("prompt");
|
|
||||||
table.text("state");
|
|
||||||
table.text("startTime");
|
|
||||||
table.text("endTime");
|
|
||||||
table.primary(["id"]);
|
|
||||||
table.unique(["id"]);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "t_image",
|
name: "t_image",
|
||||||
builder: (table) => {
|
builder: (table) => {
|
||||||
@ -207,6 +195,36 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
|||||||
},
|
},
|
||||||
initData: async (knex) => {},
|
initData: async (knex) => {},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "t_myTasks",
|
||||||
|
builder: (table) => {
|
||||||
|
table.integer("id").notNullable();
|
||||||
|
table.integer("projectId");
|
||||||
|
table.string("taskClass");
|
||||||
|
table.string("relatedObjects");
|
||||||
|
table.string("model");
|
||||||
|
table.text("describe");
|
||||||
|
table.string("state");
|
||||||
|
table.integer("startTime");
|
||||||
|
table.string("reason");
|
||||||
|
table.primary(["id"]);
|
||||||
|
table.unique(["id"]);
|
||||||
|
},
|
||||||
|
initData: async (knex) => {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "t_artStyle",
|
||||||
|
builder: (table) => {
|
||||||
|
table.integer("id").notNullable();
|
||||||
|
table.string("name");
|
||||||
|
table.text("styles");
|
||||||
|
table.primary(["id"]);
|
||||||
|
table.unique(["id"]);
|
||||||
|
},
|
||||||
|
initData: async (knex) => {
|
||||||
|
await knex("t_artStyle").insert(artStyle.map((item, index) => ({ id: index + 1, name: item.name, styles: JSON.stringify(item.styles) })));
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "t_videoConfig",
|
name: "t_videoConfig",
|
||||||
builder: (table) => {
|
builder: (table) => {
|
||||||
|
|||||||
19
src/routes/artStyle/getArtStyle.ts
Normal file
19
src/routes/artStyle/getArtStyle.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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({
|
||||||
|
name: z.string(),
|
||||||
|
}),
|
||||||
|
async (req, res) => {
|
||||||
|
const { name } = req.body;
|
||||||
|
const data = await u.db("t_artStyle").where("name", name).select("styles").first();
|
||||||
|
const styles = data?.styles ? JSON.parse(data.styles) : [];
|
||||||
|
res.status(200).send(success(styles));
|
||||||
|
},
|
||||||
|
);
|
||||||
@ -123,8 +123,13 @@ export default router.post(
|
|||||||
state: "生成中",
|
state: "生成中",
|
||||||
assetsId: id,
|
assetsId: id,
|
||||||
});
|
});
|
||||||
const apiConfig = await u.getPromptAi("assetsImage");
|
let taskClass = "";
|
||||||
|
if (type == "role") taskClass = "角色图生成";
|
||||||
|
if (type == "scene") taskClass = "场景图生成";
|
||||||
|
if (type == "props") taskClass = "道具图生成";
|
||||||
|
if (type == "storyboard") taskClass = "分镜图生成";
|
||||||
|
|
||||||
|
const apiConfig = await u.getPromptAi("assetsImage");
|
||||||
try {
|
try {
|
||||||
const contentStr = await u.ai.image(
|
const contentStr = await u.ai.image(
|
||||||
{
|
{
|
||||||
@ -133,6 +138,10 @@ export default router.post(
|
|||||||
imageBase64: base64 ? [base64] : [],
|
imageBase64: base64 ? [base64] : [],
|
||||||
size: "2K",
|
size: "2K",
|
||||||
aspectRatio: "16:9",
|
aspectRatio: "16:9",
|
||||||
|
taskClass: taskClass,
|
||||||
|
name: name,
|
||||||
|
describe: prompt,
|
||||||
|
projectId: projectId,
|
||||||
},
|
},
|
||||||
apiConfig,
|
apiConfig,
|
||||||
);
|
);
|
||||||
@ -171,7 +180,6 @@ export default router.post(
|
|||||||
filePath: imagePath,
|
filePath: imagePath,
|
||||||
type: insertType,
|
type: insertType,
|
||||||
});
|
});
|
||||||
|
|
||||||
const path = await u.oss.getFileUrl(imagePath!);
|
const path = await u.oss.getFileUrl(imagePath!);
|
||||||
|
|
||||||
// const state = await u.db("t_assets").where("id", id).select("state").first();
|
// const state = await u.db("t_assets").where("id", id).select("state").first();
|
||||||
|
|||||||
@ -24,6 +24,10 @@ export default router.post(
|
|||||||
imageBase64: [],
|
imageBase64: [],
|
||||||
aspectRatio: "16:9",
|
aspectRatio: "16:9",
|
||||||
size: "1K",
|
size: "1K",
|
||||||
|
taskClass: "测试任务",
|
||||||
|
name: "测试图片生成",
|
||||||
|
describe: "测试语言模型生成图片",
|
||||||
|
projectId: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
model: modelName,
|
model: modelName,
|
||||||
|
|||||||
@ -28,6 +28,10 @@ export default router.post(
|
|||||||
aspectRatio: "16:9",
|
aspectRatio: "16:9",
|
||||||
audio: false,
|
audio: false,
|
||||||
mode: "single",
|
mode: "single",
|
||||||
|
taskClass: "测试视频生成",
|
||||||
|
name: "测试视频生成",
|
||||||
|
describe: "测试视频生成",
|
||||||
|
projectId: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
model: modelName,
|
model: modelName,
|
||||||
|
|||||||
@ -9,6 +9,7 @@ const router = express.Router();
|
|||||||
export default router.post(
|
export default router.post(
|
||||||
"/",
|
"/",
|
||||||
validateFields({
|
validateFields({
|
||||||
|
projectType: z.string(),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
intro: z.string(),
|
intro: z.string(),
|
||||||
type: z.string(),
|
type: z.string(),
|
||||||
@ -16,9 +17,10 @@ export default router.post(
|
|||||||
videoRatio: z.string(),
|
videoRatio: z.string(),
|
||||||
}),
|
}),
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
const { name, intro, type, artStyle, videoRatio } = req.body;
|
const { projectType, name, intro, type, artStyle, videoRatio } = req.body;
|
||||||
|
|
||||||
await u.db("t_project").insert({
|
await u.db("t_project").insert({
|
||||||
|
projectType,
|
||||||
name,
|
name,
|
||||||
intro,
|
intro,
|
||||||
type,
|
type,
|
||||||
@ -29,5 +31,5 @@ export default router.post(
|
|||||||
});
|
});
|
||||||
|
|
||||||
res.status(200).send(success({ message: "新增项目成功" }));
|
res.status(200).send(success({ message: "新增项目成功" }));
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@ -27,6 +27,7 @@ export default router.post(
|
|||||||
await u.db("t_novel").where("projectId", id).delete();
|
await u.db("t_novel").where("projectId", id).delete();
|
||||||
await u.db("t_storyline").where("projectId", id).delete();
|
await u.db("t_storyline").where("projectId", id).delete();
|
||||||
await u.db("t_outline").where("projectId", id).delete();
|
await u.db("t_outline").where("projectId", id).delete();
|
||||||
|
await u.db("t_myTasks").where("projectId", id).delete();
|
||||||
|
|
||||||
await u.db("t_script").where("projectId", id).delete();
|
await u.db("t_script").where("projectId", id).delete();
|
||||||
await u.db("t_assets").where("projectId", id).delete();
|
await u.db("t_assets").where("projectId", id).delete();
|
||||||
@ -55,5 +56,5 @@ export default router.post(
|
|||||||
}
|
}
|
||||||
|
|
||||||
res.status(200).send(success({ message: "删除项目成功" }));
|
res.status(200).send(success({ message: "删除项目成功" }));
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@ -14,17 +14,19 @@ export default router.post(
|
|||||||
type: z.string().optional().nullable(),
|
type: z.string().optional().nullable(),
|
||||||
artStyle: z.string().optional().nullable(),
|
artStyle: z.string().optional().nullable(),
|
||||||
videoRatio: z.string().optional().nullable(),
|
videoRatio: z.string().optional().nullable(),
|
||||||
|
projectType: z.string().optional().nullable(),
|
||||||
}),
|
}),
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
const { id, intro, type, artStyle, videoRatio } = req.body;
|
const { id, intro, type, artStyle, videoRatio, projectType } = req.body;
|
||||||
|
|
||||||
await u.db("t_project").where("id", id).update({
|
await u.db("t_project").where("id", id).update({
|
||||||
intro,
|
intro,
|
||||||
type,
|
type,
|
||||||
artStyle,
|
artStyle,
|
||||||
videoRatio,
|
videoRatio,
|
||||||
|
projectType,
|
||||||
});
|
});
|
||||||
|
|
||||||
res.status(200).send(success({ message: "修改成功" }));
|
res.status(200).send(success({ message: "修改成功" }));
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@ -27,6 +27,10 @@ async function superResolutionAndSave(src: string, projectId: number, videoRatio
|
|||||||
systemPrompt: "你的核心任务是将所给的图片超分到 1K ,不改变图片任何内容,仅改变分辨率",
|
systemPrompt: "你的核心任务是将所给的图片超分到 1K ,不改变图片任何内容,仅改变分辨率",
|
||||||
prompt: "你的核心任务是将所给的图片超分到 1K ,不改变图片任何内容,仅改变分辨率",
|
prompt: "你的核心任务是将所给的图片超分到 1K ,不改变图片任何内容,仅改变分辨率",
|
||||||
imageBase64: [await urlToBase64(src)],
|
imageBase64: [await urlToBase64(src)],
|
||||||
|
taskClass: "分镜图超分",
|
||||||
|
name: `分镜图超分-${v4()}`,
|
||||||
|
describe: `原始图片链接: ${src}`,
|
||||||
|
projectId,
|
||||||
},
|
},
|
||||||
apiConfig,
|
apiConfig,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -4,50 +4,45 @@ import { success } from "@/lib/responseFormat";
|
|||||||
import { validateFields } from "@/middleware/middleware";
|
import { validateFields } from "@/middleware/middleware";
|
||||||
import { number, z } from "zod";
|
import { number, z } from "zod";
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
export default router.post(
|
||||||
export default router.get(
|
|
||||||
"/",
|
"/",
|
||||||
validateFields({
|
validateFields({
|
||||||
projectName: z.string(),
|
state: z.string().optional().nullable(),
|
||||||
taskName: z.string(),
|
taskClass: z.string().optional().nullable(),
|
||||||
state: z.string(),
|
|
||||||
page: z.number(),
|
page: z.number(),
|
||||||
limit: z.number(),
|
limit: z.number(),
|
||||||
|
projectId: z.number(),
|
||||||
}),
|
}),
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
const { projectName, taskName, state, page = 1, limit = 10 }: any = req.query;
|
const { taskClass, state, page = 1, limit = 10, projectId }: any = req.body;
|
||||||
const offset = (page - 1) * limit;
|
const offset = (page - 1) * limit;
|
||||||
const data = await u
|
const data = await u
|
||||||
.db("t_taskList")
|
.db("t_myTasks")
|
||||||
|
.where("projectId", projectId)
|
||||||
.andWhere((qb) => {
|
.andWhere((qb) => {
|
||||||
if (projectName) {
|
if (taskClass) {
|
||||||
qb.andWhere("t_taskList.projectName", projectName);
|
qb.andWhere("t_myTasks.taskClass", taskClass);
|
||||||
}
|
|
||||||
if (taskName) {
|
|
||||||
qb.andWhere("t_taskList.name", taskName);
|
|
||||||
}
|
}
|
||||||
if (state) {
|
if (state) {
|
||||||
qb.andWhere("t_taskList.state", state);
|
qb.andWhere("t_myTasks.state", state);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.select("*")
|
.select("*")
|
||||||
.offset(offset)
|
.offset(offset)
|
||||||
.limit(limit);
|
.limit(limit);
|
||||||
const totalQuery = (await u
|
const totalQuery = (await u
|
||||||
.db("t_taskList")
|
.db("t_myTasks")
|
||||||
|
.where("projectId", projectId)
|
||||||
.andWhere((qb) => {
|
.andWhere((qb) => {
|
||||||
if (projectName) {
|
if (taskClass) {
|
||||||
qb.andWhere("t_taskList.projectName", projectName);
|
qb.andWhere("t_myTasks.taskClass", taskClass);
|
||||||
}
|
|
||||||
if (taskName) {
|
|
||||||
qb.andWhere("t_taskList.name", taskName);
|
|
||||||
}
|
}
|
||||||
if (state) {
|
if (state) {
|
||||||
qb.andWhere("t_taskList.state", state);
|
qb.andWhere("t_myTasks.state", state);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.count("* as total")
|
.count("* as total")
|
||||||
.first()) as any;
|
.first()) as any;
|
||||||
res.status(200).send(success({ data, total: totalQuery?.total }));
|
res.status(200).send(success({ data, total: totalQuery?.total }));
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
17
src/routes/task/getTaskCategories.ts
Normal file
17
src/routes/task/getTaskCategories.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import express from "express";
|
||||||
|
import u from "@/utils";
|
||||||
|
import { success } from "@/lib/responseFormat";
|
||||||
|
import { validateFields } from "@/middleware/middleware";
|
||||||
|
import { number, z } from "zod";
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
export default router.post(
|
||||||
|
"/",
|
||||||
|
validateFields({
|
||||||
|
projectId: z.number(),
|
||||||
|
}),
|
||||||
|
async (req, res) => {
|
||||||
|
const data = await u.db("t_myTasks").where("projectId", req.body.projectId).select("taskClass").groupBy("taskClass");
|
||||||
|
res.status(200).send(success(data));
|
||||||
|
},
|
||||||
|
);
|
||||||
@ -177,6 +177,10 @@ ${prompt}
|
|||||||
resolution: resolution as any,
|
resolution: resolution as any,
|
||||||
audio: audioEnabled,
|
audio: audioEnabled,
|
||||||
mode: mode as any,
|
mode: mode as any,
|
||||||
|
taskClass: "视频生成",
|
||||||
|
name: `视频生成-${videoId}`,
|
||||||
|
describe: `视频生成,时长${duration}秒,分辨率${resolution}`,
|
||||||
|
projectId,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
baseURL: aiConfigData?.baseUrl!,
|
baseURL: aiConfigData?.baseUrl!,
|
||||||
|
|||||||
33
src/types/database.d.ts
vendored
33
src/types/database.d.ts
vendored
@ -1,4 +1,4 @@
|
|||||||
// @db-hash bdfbb3a599198f1e91b2e5d7930ccd96
|
// @db-hash 8171d26b6ac1f411a6ec46a0381b821a
|
||||||
//该文件由脚本自动生成,请勿手动修改
|
//该文件由脚本自动生成,请勿手动修改
|
||||||
|
|
||||||
export interface t_aiModelMap {
|
export interface t_aiModelMap {
|
||||||
@ -7,8 +7,12 @@ export interface t_aiModelMap {
|
|||||||
'key'?: string | null;
|
'key'?: string | null;
|
||||||
'name'?: string | null;
|
'name'?: string | null;
|
||||||
}
|
}
|
||||||
|
export interface t_artStyle {
|
||||||
|
'id'?: number;
|
||||||
|
'name'?: string | null;
|
||||||
|
'styles'?: string | null;
|
||||||
|
}
|
||||||
export interface t_assets {
|
export interface t_assets {
|
||||||
'dialogue'?: string | null;
|
|
||||||
'duration'?: string | null;
|
'duration'?: string | null;
|
||||||
'episode'?: string | null;
|
'episode'?: string | null;
|
||||||
'filePath'?: string | null;
|
'filePath'?: string | null;
|
||||||
@ -60,6 +64,17 @@ export interface t_imageModel {
|
|||||||
'model'?: string | null;
|
'model'?: string | null;
|
||||||
'type'?: string | null;
|
'type'?: string | null;
|
||||||
}
|
}
|
||||||
|
export interface t_myTasks {
|
||||||
|
'describe'?: string | null;
|
||||||
|
'id'?: number;
|
||||||
|
'model'?: string | null;
|
||||||
|
'projectId'?: number | null;
|
||||||
|
'reason'?: string | null;
|
||||||
|
'relatedObjects'?: string | null;
|
||||||
|
'startTime'?: number | null;
|
||||||
|
'state'?: string | null;
|
||||||
|
'taskClass'?: string | null;
|
||||||
|
}
|
||||||
export interface t_novel {
|
export interface t_novel {
|
||||||
'chapter'?: string | null;
|
'chapter'?: string | null;
|
||||||
'chapterData'?: string | null;
|
'chapterData'?: string | null;
|
||||||
@ -81,6 +96,7 @@ export interface t_project {
|
|||||||
'id'?: number | null;
|
'id'?: number | null;
|
||||||
'intro'?: string | null;
|
'intro'?: string | null;
|
||||||
'name'?: string | null;
|
'name'?: string | null;
|
||||||
|
'projectType'?: string | null;
|
||||||
'type'?: string | null;
|
'type'?: string | null;
|
||||||
'userId'?: number | null;
|
'userId'?: number | null;
|
||||||
'videoRatio'?: string | null;
|
'videoRatio'?: string | null;
|
||||||
@ -116,15 +132,6 @@ export interface t_storyline {
|
|||||||
'novelIds'?: string | null;
|
'novelIds'?: string | null;
|
||||||
'projectId'?: number | null;
|
'projectId'?: number | null;
|
||||||
}
|
}
|
||||||
export interface t_taskList {
|
|
||||||
'endTime'?: string | null;
|
|
||||||
'id'?: number;
|
|
||||||
'name'?: string | null;
|
|
||||||
'projectName'?: number | null;
|
|
||||||
'prompt'?: string | null;
|
|
||||||
'startTime'?: string | null;
|
|
||||||
'state'?: string | null;
|
|
||||||
}
|
|
||||||
export interface t_textModel {
|
export interface t_textModel {
|
||||||
'id'?: number;
|
'id'?: number;
|
||||||
'image'?: number | null;
|
'image'?: number | null;
|
||||||
@ -158,7 +165,6 @@ export interface t_videoConfig {
|
|||||||
'aiConfigId'?: number | null;
|
'aiConfigId'?: number | null;
|
||||||
'audioEnabled'?: number | null;
|
'audioEnabled'?: number | null;
|
||||||
'createTime'?: number | null;
|
'createTime'?: number | null;
|
||||||
'dialogue'?: string | null;
|
|
||||||
'duration'?: number | null;
|
'duration'?: number | null;
|
||||||
'endFrame'?: string | null;
|
'endFrame'?: string | null;
|
||||||
'id'?: number;
|
'id'?: number;
|
||||||
@ -185,11 +191,13 @@ export interface t_videoModel {
|
|||||||
|
|
||||||
export interface DB {
|
export interface DB {
|
||||||
"t_aiModelMap": t_aiModelMap;
|
"t_aiModelMap": t_aiModelMap;
|
||||||
|
"t_artStyle": t_artStyle;
|
||||||
"t_assets": t_assets;
|
"t_assets": t_assets;
|
||||||
"t_chatHistory": t_chatHistory;
|
"t_chatHistory": t_chatHistory;
|
||||||
"t_config": t_config;
|
"t_config": t_config;
|
||||||
"t_image": t_image;
|
"t_image": t_image;
|
||||||
"t_imageModel": t_imageModel;
|
"t_imageModel": t_imageModel;
|
||||||
|
"t_myTasks": t_myTasks;
|
||||||
"t_novel": t_novel;
|
"t_novel": t_novel;
|
||||||
"t_outline": t_outline;
|
"t_outline": t_outline;
|
||||||
"t_project": t_project;
|
"t_project": t_project;
|
||||||
@ -197,7 +205,6 @@ export interface DB {
|
|||||||
"t_script": t_script;
|
"t_script": t_script;
|
||||||
"t_setting": t_setting;
|
"t_setting": t_setting;
|
||||||
"t_storyline": t_storyline;
|
"t_storyline": t_storyline;
|
||||||
"t_taskList": t_taskList;
|
|
||||||
"t_textModel": t_textModel;
|
"t_textModel": t_textModel;
|
||||||
"t_user": t_user;
|
"t_user": t_user;
|
||||||
"t_video": t_video;
|
"t_video": t_video;
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import other from "./owned/other";
|
|||||||
import gemini from "./owned/gemini";
|
import gemini from "./owned/gemini";
|
||||||
import modelScope from "./owned/modelScope";
|
import modelScope from "./owned/modelScope";
|
||||||
import grsai from "./owned/grsai";
|
import grsai from "./owned/grsai";
|
||||||
|
import { tr } from "zod/locales";
|
||||||
|
|
||||||
const urlToBase64 = async (url: string): Promise<string> => {
|
const urlToBase64 = async (url: string): Promise<string> => {
|
||||||
const res = await axios.get(url, { responseType: "arraybuffer" });
|
const res = await axios.get(url, { responseType: "arraybuffer" });
|
||||||
@ -29,20 +30,31 @@ const modelInstance = {
|
|||||||
// apimart: apimart,
|
// apimart: apimart,
|
||||||
modelScope,
|
modelScope,
|
||||||
other,
|
other,
|
||||||
grsai
|
grsai,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default async (input: ImageConfig, config: AIConfig) => {
|
export default async (input: ImageConfig, config: AIConfig) => {
|
||||||
const { model, apiKey, baseURL, manufacturer } = { ...config };
|
const { model, apiKey, baseURL, manufacturer } = { ...config };
|
||||||
|
|
||||||
if (!config || !config?.model || !config?.apiKey || !config?.manufacturer) throw new Error("请检查模型配置是否正确");
|
if (!config || !config?.model || !config?.apiKey || !config?.manufacturer) throw new Error("请检查模型配置是否正确");
|
||||||
|
|
||||||
const manufacturerFn = modelInstance[manufacturer as keyof typeof modelInstance];
|
const manufacturerFn = modelInstance[manufacturer as keyof typeof modelInstance];
|
||||||
if (!manufacturerFn) if (!manufacturerFn) throw new Error("不支持的图片厂商");
|
if (!manufacturerFn) if (!manufacturerFn) throw new Error("不支持的图片厂商");
|
||||||
|
|
||||||
// if (manufacturer !== "other") {
|
// if (manufacturer !== "other") {
|
||||||
// const owned = modelList.find((m) => m.model === model);
|
// const owned = modelList.find((m) => m.model === model);
|
||||||
// if (!owned) throw new Error("不支持的模型");
|
// if (!owned) throw new Error("不支持的模型");
|
||||||
// }
|
// }
|
||||||
|
//添加到任务中心
|
||||||
|
const [taskId] = await u.db("t_myTasks").insert({
|
||||||
|
taskClass: input.taskClass,
|
||||||
|
relatedObjects: input.name,
|
||||||
|
model: config?.model ? config.model : "未知模型",
|
||||||
|
describe: input.describe ? input.describe : "无",
|
||||||
|
state: "进行中",
|
||||||
|
startTime: Date.now(),
|
||||||
|
projectId: input.projectId,
|
||||||
|
});
|
||||||
// 补充图片的 base64 内容类型字符串
|
// 补充图片的 base64 内容类型字符串
|
||||||
if (input.imageBase64 && input.imageBase64.length > 0) {
|
if (input.imageBase64 && input.imageBase64.length > 0) {
|
||||||
input.imageBase64 = input.imageBase64.map((img) => {
|
input.imageBase64 = input.imageBase64.map((img) => {
|
||||||
@ -66,9 +78,19 @@ export default async (input: ImageConfig, config: AIConfig) => {
|
|||||||
return `data:image/png;base64,${img}`;
|
return `data:image/png;base64,${img}`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
let imageUrl = await manufacturerFn(input, { model, apiKey, baseURL });
|
let imageUrl = await manufacturerFn(input, { model, apiKey, baseURL });
|
||||||
if (!input.resType) input.resType = "b64";
|
if (!input.resType) input.resType = "b64";
|
||||||
if (input.resType === "b64" && imageUrl.startsWith("http")) imageUrl = await urlToBase64(imageUrl);
|
if (input.resType === "b64" && imageUrl.startsWith("http")) imageUrl = await urlToBase64(imageUrl);
|
||||||
return imageUrl;
|
await u.db("t_myTasks").where("id", taskId).update({
|
||||||
|
state: "已完成",
|
||||||
|
});
|
||||||
|
return imageUrl;
|
||||||
|
} catch (error: any) {
|
||||||
|
await u.db("t_myTasks").where("id", taskId).update({
|
||||||
|
state: "生成失败",
|
||||||
|
reason: error.message,
|
||||||
|
});
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,6 +5,10 @@ interface ImageConfig {
|
|||||||
size: "1K" | "2K" | "4K";
|
size: "1K" | "2K" | "4K";
|
||||||
aspectRatio: string;
|
aspectRatio: string;
|
||||||
resType?: "url" | "b64";
|
resType?: "url" | "b64";
|
||||||
|
taskClass: string;
|
||||||
|
name: string;
|
||||||
|
describe: string;
|
||||||
|
projectId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AIConfig {
|
interface AIConfig {
|
||||||
|
|||||||
@ -21,7 +21,7 @@ const modelInstance = {
|
|||||||
runninghub: runninghub,
|
runninghub: runninghub,
|
||||||
apimart: apimart,
|
apimart: apimart,
|
||||||
other: other,
|
other: other,
|
||||||
grsai:grsai
|
grsai: grsai,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export default async (input: VideoConfig, config?: AIConfig) => {
|
export default async (input: VideoConfig, config?: AIConfig) => {
|
||||||
@ -32,7 +32,16 @@ export default async (input: VideoConfig, config?: AIConfig) => {
|
|||||||
if (!manufacturerFn) if (!manufacturerFn) throw new Error("不支持的视频厂商");
|
if (!manufacturerFn) if (!manufacturerFn) throw new Error("不支持的视频厂商");
|
||||||
// const owned = modelList.find((m) => m.model === model);
|
// const owned = modelList.find((m) => m.model === model);
|
||||||
// if (!owned) throw new Error("不支持的模型");
|
// if (!owned) throw new Error("不支持的模型");
|
||||||
|
//添加到任务中心
|
||||||
|
const [taskId] = await u.db("t_myTasks").insert({
|
||||||
|
taskClass: input.taskClass,
|
||||||
|
relatedObjects: input.name,
|
||||||
|
model: config?.model ? config.model : "未知模型",
|
||||||
|
describe: input.describe ? input.describe : "无",
|
||||||
|
state: "进行中",
|
||||||
|
startTime: Date.now(),
|
||||||
|
projectId: input.projectId,
|
||||||
|
});
|
||||||
// 补充图片的 base64 内容类型字符串
|
// 补充图片的 base64 内容类型字符串
|
||||||
if (input.imageBase64 && input.imageBase64.length > 0) {
|
if (input.imageBase64 && input.imageBase64.length > 0) {
|
||||||
input.imageBase64 = input.imageBase64.map((img) => {
|
input.imageBase64 = input.imageBase64.map((img) => {
|
||||||
@ -59,9 +68,20 @@ export default async (input: VideoConfig, config?: AIConfig) => {
|
|||||||
|
|
||||||
let videoUrl = await manufacturerFn(input, { model, apiKey, baseURL });
|
let videoUrl = await manufacturerFn(input, { model, apiKey, baseURL });
|
||||||
if (videoUrl) {
|
if (videoUrl) {
|
||||||
const response = await axios.get(videoUrl, { responseType: "stream" });
|
try {
|
||||||
await u.oss.writeFile(input.savePath, response.data);
|
const response = await axios.get(videoUrl, { responseType: "stream" });
|
||||||
return input.savePath;
|
await u.oss.writeFile(input.savePath, response.data);
|
||||||
|
await u.db("t_myTasks").where("id", taskId).update({
|
||||||
|
state: "已完成",
|
||||||
|
});
|
||||||
|
return input.savePath;
|
||||||
|
} catch (err: any) {
|
||||||
|
await u.db("t_myTasks").where("id", taskId).update({
|
||||||
|
state: "生成失败",
|
||||||
|
reason: err.message,
|
||||||
|
});
|
||||||
|
return videoUrl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return videoUrl;
|
return videoUrl;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -7,6 +7,10 @@ interface VideoConfig {
|
|||||||
imageBase64?: string[];
|
imageBase64?: string[];
|
||||||
audio?: boolean;
|
audio?: boolean;
|
||||||
mode: "startEnd" | "multi" | "single" | "text";
|
mode: "startEnd" | "multi" | "single" | "text";
|
||||||
|
taskClass: string;
|
||||||
|
name: string;
|
||||||
|
projectId: number;
|
||||||
|
describe?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AIConfig {
|
interface AIConfig {
|
||||||
|
|||||||
@ -88,6 +88,10 @@ export default async (images: Record<string, string>, directive: string, project
|
|||||||
imageBase64: base64Images,
|
imageBase64: base64Images,
|
||||||
aspectRatio: aspectRatio ? aspectRatio : "16:9",
|
aspectRatio: aspectRatio ? aspectRatio : "16:9",
|
||||||
size: "1K",
|
size: "1K",
|
||||||
|
taskClass: "图片编辑",
|
||||||
|
name: `图片编辑-${uuid()}`,
|
||||||
|
describe: `编辑指令: ${directive}`,
|
||||||
|
projectId,
|
||||||
},
|
},
|
||||||
apiConfig,
|
apiConfig,
|
||||||
);
|
);
|
||||||
|
|||||||
2454
tempCodeRunnerFile.javascript
Normal file
2454
tempCodeRunnerFile.javascript
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user