修复 删除视频配置 导致图片丢失,增加魔塔配置,分镜提示词添加台词(待测试)
This commit is contained in:
parent
06beb62324
commit
fea860e1bb
@ -58,7 +58,7 @@
|
||||
"jsonwebtoken": "^9.0.3",
|
||||
"knex": "^3.1.0",
|
||||
"morgan": "^1.10.1",
|
||||
"qwen-ai-provider": "^0.1.1",
|
||||
"qwen-ai-provider-v5": "^2.1.0",
|
||||
"serialize-error": "^13.0.1",
|
||||
"sharp": "^0.34.5",
|
||||
"sqlite3": "^5.1.7",
|
||||
|
||||
@ -242,11 +242,10 @@ ${sections.join("\n\n")}
|
||||
const skipped: number[] = [];
|
||||
|
||||
for (const item of shots) {
|
||||
const resultIndex = item.segmentIndex - 1;
|
||||
|
||||
const exists = this.shots.some((f) => f.segmentId === resultIndex);
|
||||
const exists = this.shots.some((f) => f.segmentId === item.segmentIndex);
|
||||
if (exists) {
|
||||
skipped.push(resultIndex);
|
||||
skipped.push(item.segmentIndex);
|
||||
continue;
|
||||
}
|
||||
// 分配独立的分镜ID
|
||||
@ -254,15 +253,15 @@ ${sections.join("\n\n")}
|
||||
const shotId = this.shotIdCounter;
|
||||
this.shots.push({
|
||||
id: shotId,
|
||||
segmentId: resultIndex,
|
||||
segmentId: item.segmentIndex,
|
||||
title: `分镜 ${shotId}`,
|
||||
x: 0,
|
||||
y: 0,
|
||||
cells: item.prompts.map((prompt) => ({ id: u.uuid(), prompt })),
|
||||
fragmentContent: this.segments[resultIndex]?.description,
|
||||
fragmentContent: this.segments[item.segmentIndex - 1]?.description,
|
||||
assetsTags: item.assetsTags,
|
||||
});
|
||||
added.push({ id: shotId, segmentIndex: resultIndex });
|
||||
added.push({ id: shotId, segmentIndex: item.segmentIndex });
|
||||
}
|
||||
|
||||
const addedInfo = added.map((a) => `分镜${a.id}(片段${a.segmentIndex})`).join(", ");
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -436,7 +436,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: "system",
|
||||
parentCode: null,
|
||||
defaultValue:
|
||||
'# 角色定位\\n你是一名专业的视频分镜图片提示词设计师,根据用户提供的分镜信息,生成具象化的中文图片描述提示词。\\n## 核心任务\\n将分镜名称和描述转化为一条完整、具象化的中文图片提示词,供后续AI图像生成使用。\\n---\\n## 描述要素(按优先级排列)\\n### 核心要素(必须包含)\\n1. **镜头语言**:镜头类型(特写/近景/中景/全景/远景)、视角(平视/俯视/仰视)、构图方式\\n2. **场景环境**:场所类型、室内外、时间段、天气、季节氛围\\n3. **人物特征**:数量、性别、年龄、外貌特点、服饰细节、发型、表情状态\\n4. **人物动作**:具体姿态、动态描述、肢体语言、互动行为\\n### 辅助要素(丰富画面)\\n5. **空间布局**:前景中景背景层次、物品摆放、景深关系\\n6. **光影色彩**:光源方向、明暗对比、主色调、情绪氛围\\n7. **道具细节**:重要道具的外观、材质、位置\\n8. **材质质感**:环境或物品的材质特征\\n---\\n## 镜头类型参考\\n- **特写**:局部细节放大,强调情绪或关键物件\\n- **近景**:胸部以上,聚焦面部表情\\n- **中景**:腰部以上,平衡角色与环境\\n- **全景**:全身入镜,展现完整动作姿态\\n- **远景**:人物与环境关系,空间感\\n- **大远景**:环境主导,史诗感或孤独感\\n## 视角参考\\n- **平视**:客观中立的观察视角\\n- **俯视**:表现渺小、脆弱、被压迫\\n- **仰视**:表现威严、力量、崇敬\\n- **斜角**:不安、紧张、失衡感\\n- **肩后视角**:增强代入感和互动感\\n---\\n## 输出规范\\n### 必须遵守\\n- 纯中文描述,一段式连贯输出\\n- 使用具象化、可视化的具体描述,避免抽象词汇\\n- 涵盖镜头语言、场景、人物、光影等关键要素\\n- 只输出提示词本身,不包含任何解释说明\\n### 严格禁止在提示词中包含\\n- 分镜编号、镜号标记(如"场景1"、"镜头5")\\n- 技术注释(如"推镜头"、"淡入淡出")\\n- 时长标记、帧数说明\\n- 任何画外解释性文字\\n- 水印、Logo相关描述\\n---\\n## 输出示例\\n用户输入:分镜名称"少年奔跑",描述"主角在校园操场上奔跑"\\n输出:\\n全景镜头平视角度,阳光明媚的午后校园操场,身穿白色运动服的少年正在向前奔跑,短发随风飘动,侧脸表情专注而坚定,双臂有力摆动,背景是清晰可见的红色教学楼,翠绿草坪平整开阔,银色篮球架立于画面右侧,整体暖黄色调,自然光从左侧照射形成柔和投影,充满青春活力氛围\\n---\\n请等待用户提供分镜信息后开始生成提示词。',
|
||||
'# 角色定位\\n你是一名专业的视频分镜图片提示词设计师,根据用户提供的分镜信息,生成具象化的中文图片描述提示词,如果剧本中包含对话要把对话加入到提示词中。\\n## 核心任务\\n将分镜名称和描述转化为一条完整、具象化的中文图片提示词,供后续AI图像生成使用。\\n---\\n## 描述要素(按优先级排列)\\n### 核心要素(必须包含)\\n1. **镜头语言**:镜头类型(特写/近景/中景/全景/远景)、视角(平视/俯视/仰视)、构图方式\\n2. **场景环境**:场所类型、室内外、时间段、天气、季节氛围\\n3. **人物特征**:数量、性别、年龄、外貌特点、服饰细节、发型、表情状态\\n4. **人物动作**:具体姿态、动态描述、肢体语言、互动行为\\n### 辅助要素(丰富画面)\\n5. **空间布局**:前景中景背景层次、物品摆放、景深关系\\n6. **光影色彩**:光源方向、明暗对比、主色调、情绪氛围\\n7. **道具细节**:重要道具的外观、材质、位置\\n8. **材质质感**:环境或物品的材质特征\\n---\\n## 镜头类型参考\\n- **特写**:局部细节放大,强调情绪或关键物件\\n- **近景**:胸部以上,聚焦面部表情\\n- **中景**:腰部以上,平衡角色与环境\\n- **全景**:全身入镜,展现完整动作姿态\\n- **远景**:人物与环境关系,空间感\\n- **大远景**:环境主导,史诗感或孤独感\\n## 视角参考\\n- **平视**:客观中立的观察视角\\n- **俯视**:表现渺小、脆弱、被压迫\\n- **仰视**:表现威严、力量、崇敬\\n- **斜角**:不安、紧张、失衡感\\n- **肩后视角**:增强代入感和互动感\\n---\\n## 输出规范\\n### 必须遵守\\n- 纯中文描述,一段式连贯输出\\n- 使用具象化、可视化的具体描述,避免抽象词汇\\n- 涵盖镜头语言、场景、人物、光影等关键要素\\n- 只输出提示词本身,不包含任何解释说明\\n### 严格禁止在提示词中包含\\n- 分镜编号、镜号标记(如"场景1"、"镜头5")\\n- 技术注释(如"推镜头"、"淡入淡出")\\n- 时长标记、帧数说明\\n- 任何画外解释性文字\\n- 水印、Logo相关描述\\n---\\n## 输出示例\\n用户输入:分镜名称"少年奔跑",描述"主角在校园操场上奔跑"\\n输出:\\n全景镜头平视角度,阳光明媚的午后校园操场,身穿白色运动服的少年正在向前奔跑,短发随风飘动,侧脸表情专注而坚定,双臂有力摆动,背景是清晰可见的红色教学楼,翠绿草坪平整开阔,银色篮球架立于画面右侧,整体暖黄色调,自然光从左侧照射形成柔和投影,充满青春活力氛围\\n---\\n请等待用户提供分镜信息后开始生成提示词。',
|
||||
customValue: null,
|
||||
},
|
||||
{
|
||||
@ -634,15 +634,16 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
},
|
||||
initData: async (knex) => {
|
||||
await knex("t_imageModel").insert([
|
||||
{ id: 1, manufacturer: "volcengine", model: "doubao-seedream-4-5-251128", grid: 0, type: "ti2i" },
|
||||
{ id: 2, manufacturer: "volcengine", model: "doubao-seedream-4-0-250828", grid: 0, type: "ti2i" },
|
||||
{ id: 3, manufacturer: "kling", model: "kling-image-o1", grid: 0, type: "ti2i" },
|
||||
{ id: 4, manufacturer: "gemini", model: "gemini-2.5-flash-image", grid: 1, type: "ti2i" },
|
||||
{ id: 5, manufacturer: "gemini", model: "gemini-3-pro-image-preview", grid: 1, type: "ti2i" },
|
||||
{ id: 6, manufacturer: "vidu", model: "viduq1", grid: 0, type: "i2i" },
|
||||
{ id: 7, manufacturer: "vidu", model: "viduq2", grid: 0, type: "ti2i" },
|
||||
{ id: 8, manufacturer: "runninghub", model: "nanobanana", grid: 1, type: "ti2i" },
|
||||
{ id: 9, manufacturer: "modelScope", model: "Qwen/Qwen-Image", grid: 1, type: "ti2i" },
|
||||
{ manufacturer: "volcengine", model: "doubao-seedream-5-0-260128", grid: 1, type: "ti2i" },
|
||||
{ manufacturer: "volcengine", model: "doubao-seedream-4-5-251128", grid: 0, type: "ti2i" },
|
||||
{ manufacturer: "volcengine", model: "doubao-seedream-4-0-250828", grid: 0, type: "ti2i" },
|
||||
{ manufacturer: "kling", model: "kling-image-o1", grid: 0, type: "ti2i" },
|
||||
{ manufacturer: "gemini", model: "gemini-2.5-flash-image", grid: 1, type: "ti2i" },
|
||||
{ manufacturer: "gemini", model: "gemini-3-pro-image-preview", grid: 1, type: "ti2i" },
|
||||
{ manufacturer: "vidu", model: "viduq1", grid: 0, type: "i2i" },
|
||||
{ manufacturer: "vidu", model: "viduq2", grid: 0, type: "ti2i" },
|
||||
{ manufacturer: "runninghub", model: "nanobanana", grid: 1, type: "ti2i" },
|
||||
{ manufacturer: "modelScope", model: "Qwen/Qwen-Image", grid: 1, type: "ti2i" },
|
||||
]);
|
||||
},
|
||||
},
|
||||
|
||||
136
src/router.ts
136
src/router.ts
@ -1,4 +1,4 @@
|
||||
// @routes-hash bf59be4347a649430bc8b6067c3cf9ef
|
||||
// @routes-hash c97cf72361299980ea4b0c43549a0de8
|
||||
import { Express } from "express";
|
||||
|
||||
import route1 from "./routes/assets/addAssets";
|
||||
@ -48,38 +48,41 @@ import route44 from "./routes/script/geScriptApi";
|
||||
import route45 from "./routes/setting/addModel";
|
||||
import route46 from "./routes/setting/configurationModel";
|
||||
import route47 from "./routes/setting/delModel";
|
||||
import route48 from "./routes/setting/getAiModelMap";
|
||||
import route49 from "./routes/setting/getLog";
|
||||
import route50 from "./routes/setting/getSetting";
|
||||
import route51 from "./routes/setting/getVideoModelList";
|
||||
import route52 from "./routes/setting/updateModel";
|
||||
import route53 from "./routes/setting/updeteModel";
|
||||
import route54 from "./routes/storyboard/batchSuperScoreImage";
|
||||
import route55 from "./routes/storyboard/chatStoryboard";
|
||||
import route56 from "./routes/storyboard/delStoryboard";
|
||||
import route57 from "./routes/storyboard/generateShotImage";
|
||||
import route58 from "./routes/storyboard/generateStoryboardApi";
|
||||
import route59 from "./routes/storyboard/generateVideoPrompt";
|
||||
import route60 from "./routes/storyboard/getStoryboard";
|
||||
import route61 from "./routes/storyboard/keepStoryboard";
|
||||
import route62 from "./routes/storyboard/saveStoryboard";
|
||||
import route63 from "./routes/storyboard/uploadImage";
|
||||
import route64 from "./routes/task/getTaskApi";
|
||||
import route65 from "./routes/task/taskDetails";
|
||||
import route66 from "./routes/user/getUser";
|
||||
import route67 from "./routes/video/addVideo";
|
||||
import route68 from "./routes/video/addVideoConfig";
|
||||
import route69 from "./routes/video/deleteVideoConfig";
|
||||
import route70 from "./routes/video/generatePrompt";
|
||||
import route71 from "./routes/video/generateVideo";
|
||||
import route72 from "./routes/video/getManufacturer";
|
||||
import route73 from "./routes/video/getVideo";
|
||||
import route74 from "./routes/video/getVideoConfigs";
|
||||
import route75 from "./routes/video/getVideoModel";
|
||||
import route76 from "./routes/video/getVideoStoryboards";
|
||||
import route77 from "./routes/video/reviseVideoStoryboards";
|
||||
import route78 from "./routes/video/saveVideo";
|
||||
import route79 from "./routes/video/upDateVideoConfig";
|
||||
import route48 from "./routes/setting/getAiModelList";
|
||||
import route49 from "./routes/setting/getAiModelMap";
|
||||
import route50 from "./routes/setting/getLog";
|
||||
import route51 from "./routes/setting/getSetting";
|
||||
import route52 from "./routes/setting/getVideoModelDetail";
|
||||
import route53 from "./routes/setting/getVideoModelList";
|
||||
import route54 from "./routes/setting/updateModel";
|
||||
import route55 from "./routes/setting/updeteModel";
|
||||
import route56 from "./routes/storyboard/batchSuperScoreImage";
|
||||
import route57 from "./routes/storyboard/chatStoryboard";
|
||||
import route58 from "./routes/storyboard/delStoryboard";
|
||||
import route59 from "./routes/storyboard/generateShotImage";
|
||||
import route60 from "./routes/storyboard/generateStoryboardApi";
|
||||
import route61 from "./routes/storyboard/generateVideoPrompt";
|
||||
import route62 from "./routes/storyboard/getStoryboard";
|
||||
import route63 from "./routes/storyboard/keepStoryboard";
|
||||
import route64 from "./routes/storyboard/saveStoryboard";
|
||||
import route65 from "./routes/storyboard/uploadImage";
|
||||
import route66 from "./routes/task/getTaskApi";
|
||||
import route67 from "./routes/task/taskDetails";
|
||||
import route68 from "./routes/user/getUser";
|
||||
import route69 from "./routes/user/saveUser";
|
||||
import route70 from "./routes/video/addVideo";
|
||||
import route71 from "./routes/video/addVideoConfig";
|
||||
import route72 from "./routes/video/deleteVideoConfig";
|
||||
import route73 from "./routes/video/generatePrompt";
|
||||
import route74 from "./routes/video/generateVideo";
|
||||
import route75 from "./routes/video/getManufacturer";
|
||||
import route76 from "./routes/video/getVideo";
|
||||
import route77 from "./routes/video/getVideoConfigs";
|
||||
import route78 from "./routes/video/getVideoModel";
|
||||
import route79 from "./routes/video/getVideoStoryboards";
|
||||
import route80 from "./routes/video/reviseVideoStoryboards";
|
||||
import route81 from "./routes/video/saveVideo";
|
||||
import route82 from "./routes/video/upDateVideoConfig";
|
||||
|
||||
export default async (app: Express) => {
|
||||
app.use("/assets/addAssets", route1);
|
||||
@ -129,36 +132,39 @@ export default async (app: Express) => {
|
||||
app.use("/setting/addModel", route45);
|
||||
app.use("/setting/configurationModel", route46);
|
||||
app.use("/setting/delModel", route47);
|
||||
app.use("/setting/getAiModelMap", route48);
|
||||
app.use("/setting/getLog", route49);
|
||||
app.use("/setting/getSetting", route50);
|
||||
app.use("/setting/getVideoModelList", route51);
|
||||
app.use("/setting/updateModel", route52);
|
||||
app.use("/setting/updeteModel", route53);
|
||||
app.use("/storyboard/batchSuperScoreImage", route54);
|
||||
app.use("/storyboard/chatStoryboard", route55);
|
||||
app.use("/storyboard/delStoryboard", route56);
|
||||
app.use("/storyboard/generateShotImage", route57);
|
||||
app.use("/storyboard/generateStoryboardApi", route58);
|
||||
app.use("/storyboard/generateVideoPrompt", route59);
|
||||
app.use("/storyboard/getStoryboard", route60);
|
||||
app.use("/storyboard/keepStoryboard", route61);
|
||||
app.use("/storyboard/saveStoryboard", route62);
|
||||
app.use("/storyboard/uploadImage", route63);
|
||||
app.use("/task/getTaskApi", route64);
|
||||
app.use("/task/taskDetails", route65);
|
||||
app.use("/user/getUser", route66);
|
||||
app.use("/video/addVideo", route67);
|
||||
app.use("/video/addVideoConfig", route68);
|
||||
app.use("/video/deleteVideoConfig", route69);
|
||||
app.use("/video/generatePrompt", route70);
|
||||
app.use("/video/generateVideo", route71);
|
||||
app.use("/video/getManufacturer", route72);
|
||||
app.use("/video/getVideo", route73);
|
||||
app.use("/video/getVideoConfigs", route74);
|
||||
app.use("/video/getVideoModel", route75);
|
||||
app.use("/video/getVideoStoryboards", route76);
|
||||
app.use("/video/reviseVideoStoryboards", route77);
|
||||
app.use("/video/saveVideo", route78);
|
||||
app.use("/video/upDateVideoConfig", route79);
|
||||
app.use("/setting/getAiModelList", route48);
|
||||
app.use("/setting/getAiModelMap", route49);
|
||||
app.use("/setting/getLog", route50);
|
||||
app.use("/setting/getSetting", route51);
|
||||
app.use("/setting/getVideoModelDetail", route52);
|
||||
app.use("/setting/getVideoModelList", route53);
|
||||
app.use("/setting/updateModel", route54);
|
||||
app.use("/setting/updeteModel", route55);
|
||||
app.use("/storyboard/batchSuperScoreImage", route56);
|
||||
app.use("/storyboard/chatStoryboard", route57);
|
||||
app.use("/storyboard/delStoryboard", route58);
|
||||
app.use("/storyboard/generateShotImage", route59);
|
||||
app.use("/storyboard/generateStoryboardApi", route60);
|
||||
app.use("/storyboard/generateVideoPrompt", route61);
|
||||
app.use("/storyboard/getStoryboard", route62);
|
||||
app.use("/storyboard/keepStoryboard", route63);
|
||||
app.use("/storyboard/saveStoryboard", route64);
|
||||
app.use("/storyboard/uploadImage", route65);
|
||||
app.use("/task/getTaskApi", route66);
|
||||
app.use("/task/taskDetails", route67);
|
||||
app.use("/user/getUser", route68);
|
||||
app.use("/user/saveUser", route69);
|
||||
app.use("/video/addVideo", route70);
|
||||
app.use("/video/addVideoConfig", route71);
|
||||
app.use("/video/deleteVideoConfig", route72);
|
||||
app.use("/video/generatePrompt", route73);
|
||||
app.use("/video/generateVideo", route74);
|
||||
app.use("/video/getManufacturer", route75);
|
||||
app.use("/video/getVideo", route76);
|
||||
app.use("/video/getVideoConfigs", route77);
|
||||
app.use("/video/getVideoModel", route78);
|
||||
app.use("/video/getVideoStoryboards", route79);
|
||||
app.use("/video/reviseVideoStoryboards", route80);
|
||||
app.use("/video/saveVideo", route81);
|
||||
app.use("/video/upDateVideoConfig", route82);
|
||||
}
|
||||
|
||||
@ -48,6 +48,7 @@ export default router.post(
|
||||
);
|
||||
res.status(200).send(success(reply));
|
||||
} catch (err) {
|
||||
console.log("%c Line:51 🥟 err", "background:#e41a6a", err);
|
||||
const msg = u.error(err).message;
|
||||
console.error(msg);
|
||||
res.status(500).send(error(msg));
|
||||
|
||||
@ -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 { generateScript } from "@/utils/generateScript";
|
||||
const router = express.Router();
|
||||
@ -43,14 +43,18 @@ export default router.post(
|
||||
if (novelData.length == 0) return res.status(500).send(success({ message: "原文为空" }));
|
||||
|
||||
const result: string = mergeNovelText(novelData);
|
||||
try {
|
||||
const data = await generateScript(parameter ?? "", result ?? "");
|
||||
if (!data) return res.status(500).send({ message: "生成剧本失败" });
|
||||
|
||||
const data = await generateScript(parameter ?? "", result ?? "");
|
||||
if (!data) return res.status(500).send({ message: "生成剧本失败" });
|
||||
await u.db("t_script").where("id", scriptId).update({
|
||||
content: data,
|
||||
});
|
||||
|
||||
await u.db("t_script").where("id", scriptId).update({
|
||||
content: data,
|
||||
});
|
||||
|
||||
res.status(200).send(success({ message: "生成剧本成功" }));
|
||||
res.status(200).send(success({ message: "生成剧本成功" }));
|
||||
} catch (e) {
|
||||
const errMsg = u.error(e).message || "生成剧本失败";
|
||||
res.status(500).send(error(errMsg));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
24
src/routes/user/saveUser.ts
Normal file
24
src/routes/user/saveUser.ts
Normal file
@ -0,0 +1,24 @@
|
||||
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(),
|
||||
password: z.string(),
|
||||
id: z.number(),
|
||||
}),
|
||||
async (req, res) => {
|
||||
const { name, password, id } = req.body;
|
||||
await u.db("t_user").where("id", id).update({
|
||||
name,
|
||||
password,
|
||||
});
|
||||
res.status(200).send(success("保存设置成功"));
|
||||
},
|
||||
);
|
||||
@ -33,9 +33,9 @@ export default router.post(
|
||||
if (result.filePath) {
|
||||
filesToDelete.push(result.filePath);
|
||||
}
|
||||
if (result.firstFrame) {
|
||||
filesToDelete.push(result.firstFrame);
|
||||
}
|
||||
// if (result.firstFrame) {
|
||||
// filesToDelete.push(result.firstFrame);
|
||||
// }
|
||||
}
|
||||
|
||||
// 删除文件
|
||||
|
||||
35
src/types/database.d.ts
vendored
35
src/types/database.d.ts
vendored
@ -1,20 +1,6 @@
|
||||
// @db-hash ab4e3e93bfba304164daa7d28c804eaf
|
||||
// @db-hash 0f9789bd5ad2eebd79bd502988efcb4e
|
||||
//该文件由脚本自动生成,请勿手动修改
|
||||
|
||||
export interface _t_video_old_20260210 {
|
||||
'aiConfigId'?: number | null;
|
||||
'configId'?: number | null;
|
||||
'filePath'?: string | null;
|
||||
'firstFrame'?: string | null;
|
||||
'id'?: number;
|
||||
'model'?: string | null;
|
||||
'prompt'?: string | null;
|
||||
'resolution'?: string | null;
|
||||
'scriptId'?: number | null;
|
||||
'state'?: number | null;
|
||||
'storyboardImgs'?: string | null;
|
||||
'time'?: number | null;
|
||||
}
|
||||
export interface t_aiModelMap {
|
||||
'configId'?: number | null;
|
||||
'id'?: number;
|
||||
@ -66,13 +52,6 @@ export interface t_image {
|
||||
'type'?: string | null;
|
||||
'videoId'?: number | null;
|
||||
}
|
||||
export interface t_imageConfig {
|
||||
'grid'?: number | null;
|
||||
'id'?: number;
|
||||
'manufacturer'?: string | null;
|
||||
'model'?: string | null;
|
||||
'type'?: string | null;
|
||||
}
|
||||
export interface t_imageModel {
|
||||
'grid'?: number | null;
|
||||
'id'?: number;
|
||||
@ -145,15 +124,6 @@ export interface t_taskList {
|
||||
'startTime'?: string | null;
|
||||
'state'?: string | null;
|
||||
}
|
||||
export interface t_textConfig {
|
||||
'id'?: number;
|
||||
'image'?: number | null;
|
||||
'manufacturer'?: string | null;
|
||||
'model'?: string | null;
|
||||
'responseFormat'?: string | null;
|
||||
'think'?: number | null;
|
||||
'tool'?: number | null;
|
||||
}
|
||||
export interface t_textModel {
|
||||
'id'?: number;
|
||||
'image'?: number | null;
|
||||
@ -212,13 +182,11 @@ export interface t_videoModel {
|
||||
}
|
||||
|
||||
export interface DB {
|
||||
"_t_video_old_20260210": _t_video_old_20260210;
|
||||
"t_aiModelMap": t_aiModelMap;
|
||||
"t_assets": t_assets;
|
||||
"t_chatHistory": t_chatHistory;
|
||||
"t_config": t_config;
|
||||
"t_image": t_image;
|
||||
"t_imageConfig": t_imageConfig;
|
||||
"t_imageModel": t_imageModel;
|
||||
"t_novel": t_novel;
|
||||
"t_outline": t_outline;
|
||||
@ -228,7 +196,6 @@ export interface DB {
|
||||
"t_setting": t_setting;
|
||||
"t_storyline": t_storyline;
|
||||
"t_taskList": t_taskList;
|
||||
"t_textConfig": t_textConfig;
|
||||
"t_textModel": t_textModel;
|
||||
"t_user": t_user;
|
||||
"t_video": t_video;
|
||||
|
||||
@ -69,26 +69,28 @@ export default async (input: ImageConfig, config: AIConfig): Promise<string> =>
|
||||
console.error(JSON.stringify(result.response, null, 2));
|
||||
throw new Error("图片生成失败");
|
||||
}
|
||||
const mdMatch = result.text.match(/^!\[.*?\]\((.+?)\)$/);
|
||||
if (mdMatch) {
|
||||
const imgInfo = mdMatch[1];
|
||||
const base64InMd = imgInfo.match(/data:image\/[a-z]+;base64,(.+)/);
|
||||
// 匹配所有 markdown 图片 
|
||||
const mdImgPattern = /!\[.*?\]\((.+?)\)/g;
|
||||
const matches = [...result.text.matchAll(mdImgPattern)];
|
||||
for (const match of matches) {
|
||||
const imgInfo = match[1];
|
||||
// 检查是否已是 base64
|
||||
const base64InMd = imgInfo.match(/data:image\/[a-z]+;base64,.+/);
|
||||
if (base64InMd) {
|
||||
return imgInfo;
|
||||
return imgInfo; // 已经是base64,直接返回
|
||||
} else {
|
||||
return await urlToBase64(imgInfo);
|
||||
return await urlToBase64(imgInfo); // 否则尝试转base64
|
||||
}
|
||||
}
|
||||
// 检查纯base64字符串
|
||||
const base64Match = result.text.match(/base64,([A-Za-z0-9+/=]+)/);
|
||||
|
||||
if (base64Match) {
|
||||
return "data:image/jpeg;base64," + base64Match[1];
|
||||
}
|
||||
// 检查是否为图片直链 url
|
||||
// 检查是否为图片直链接
|
||||
if (/^https?:\/\/.*\.(png|jpg|jpeg|gif|webp|bmp)$/i.test(result.text)) {
|
||||
return await urlToBase64(result.text);
|
||||
}
|
||||
|
||||
// 默认情况
|
||||
return result.text;
|
||||
}
|
||||
|
||||
@ -8,18 +8,26 @@ export default async (input: ImageConfig, config: AIConfig): Promise<string> =>
|
||||
|
||||
const apiKey = "Bearer " + config.apiKey.replace(/Bearer\s+/g, "").trim();
|
||||
const size = input.size === "1K" ? "2K" : input.size;
|
||||
|
||||
const sizeMap: Record<string, Record<string, string>> = {
|
||||
"16:9": {
|
||||
"2K": "2848x1600",
|
||||
"4K": "4096x2304",
|
||||
},
|
||||
"9:16": {
|
||||
"2K": "1600x2848",
|
||||
"4K": "2304x4096",
|
||||
},
|
||||
};
|
||||
const body: Record<string, any> = {
|
||||
model: config.model,
|
||||
prompt: input.prompt,
|
||||
size,
|
||||
size: sizeMap[input.aspectRatio][size],
|
||||
response_format: "url",
|
||||
sequential_image_generation: "disabled",
|
||||
stream: false,
|
||||
watermark: false,
|
||||
...(input.imageBase64 && { image: input.imageBase64 }),
|
||||
};
|
||||
|
||||
const url = config.baseURL ?? "https://ark.cn-beijing.volces.com/api/v3/images/generations";
|
||||
try {
|
||||
const { data } = await axios.post(url, body, { headers: { Authorization: apiKey } });
|
||||
@ -28,4 +36,4 @@ export default async (input: ImageConfig, config: AIConfig): Promise<string> =>
|
||||
const msg = u.error(error).message || "Volcengine 图片生成失败";
|
||||
throw new Error(msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -34,7 +34,6 @@ const buildOptions = async (input: AIInput<any>, config: AIConfig = {}) => {
|
||||
if (!owned) owned = modelList.find((m) => m.manufacturer === manufacturer);
|
||||
}
|
||||
if (!owned) throw new Error("不支持的厂商");
|
||||
console.log("%c Line:36 🥛 owned", "background:#6ec1c2", owned);
|
||||
|
||||
const modelInstance = owned.instance({ apiKey, baseURL: baseURL!, name: "xixixi" });
|
||||
|
||||
@ -55,8 +54,9 @@ const buildOptions = async (input: AIInput<any>, config: AIConfig = {}) => {
|
||||
};
|
||||
|
||||
const output = input.output ? (outputBuilders[owned.responseFormat]?.(input.output) ?? null) : null;
|
||||
const chatModelManufacturer = ["volcengine", "other", "openai"];
|
||||
const chatModelManufacturer = ["volcengine", "other", "openai", "modelScope"];
|
||||
const modelFn = chatModelManufacturer.includes(owned.manufacturer) ? (modelInstance as OpenAIProvider).chat(model!) : modelInstance(model!);
|
||||
|
||||
return {
|
||||
config: {
|
||||
model: modelFn as LanguageModel,
|
||||
@ -79,7 +79,7 @@ const ai = Object.create({}) as {
|
||||
|
||||
ai.invoke = async (input: AIInput<any>, config: AIConfig) => {
|
||||
const options = await buildOptions(input, config);
|
||||
console.log("%c Line:81 🍧 options", "background:#93c0a4", options);
|
||||
|
||||
const result = await generateText(options.config);
|
||||
if (options.responseFormat === "object" && input.output) {
|
||||
const pattern = /{[^{}]*}|{(?:[^{}]*|{[^{}]*})*}/g;
|
||||
@ -96,7 +96,7 @@ ai.invoke = async (input: AIInput<any>, config: AIConfig) => {
|
||||
|
||||
ai.stream = async (input: AIInput, config: AIConfig) => {
|
||||
const options = await buildOptions(input, config);
|
||||
console.log("%c Line:98 🍬 options", "background:#fca650", options);
|
||||
|
||||
return streamText(options.config);
|
||||
};
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { createOpenAI, OpenAIProviderSettings } from "@ai-sdk/openai";
|
||||
import { createDeepSeek } from "@ai-sdk/deepseek";
|
||||
import { createZhipu } from "zhipu-ai-provider";
|
||||
import { createQwen } from "qwen-ai-provider";
|
||||
import { createQwen } from "qwen-ai-provider-v5";
|
||||
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
||||
import { createAnthropic } from "@ai-sdk/anthropic";
|
||||
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
||||
|
||||
50
yarn.lock
50
yarn.lock
@ -74,15 +74,6 @@
|
||||
"@standard-schema/spec" "^1.1.0"
|
||||
eventsource-parser "^3.0.6"
|
||||
|
||||
"@ai-sdk/provider-utils@^2.1.6":
|
||||
version "2.2.8"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/provider-utils/-/provider-utils-2.2.8.tgz#ad11b92d5a1763ab34ba7b5fc42494bfe08b76d1"
|
||||
integrity sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==
|
||||
dependencies:
|
||||
"@ai-sdk/provider" "1.1.3"
|
||||
nanoid "^3.3.8"
|
||||
secure-json-parse "^2.7.0"
|
||||
|
||||
"@ai-sdk/provider-utils@^3.0.0":
|
||||
version "3.0.20"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/provider-utils/-/provider-utils-3.0.20.tgz#61d7741065550833eae3ac6440d943e9d3d25120"
|
||||
@ -92,12 +83,14 @@
|
||||
"@standard-schema/spec" "^1.0.0"
|
||||
eventsource-parser "^3.0.6"
|
||||
|
||||
"@ai-sdk/provider@1.1.3", "@ai-sdk/provider@^1.0.7":
|
||||
version "1.1.3"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/provider/-/provider-1.1.3.tgz#ebdda8077b8d2b3f290dcba32c45ad19b2704681"
|
||||
integrity sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==
|
||||
"@ai-sdk/provider-utils@^4.0.0":
|
||||
version "4.0.15"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/provider-utils/-/provider-utils-4.0.15.tgz#d585c7c89cfdf13697a40be5768ecd907a251585"
|
||||
integrity sha512-8XiKWbemmCbvNN0CLR9u3PQiet4gtEVIrX4zzLxnCj06AwsEDJwJVBbKrEI4t6qE8XRSIvU2irka0dcpziKW6w==
|
||||
dependencies:
|
||||
json-schema "^0.4.0"
|
||||
"@ai-sdk/provider" "3.0.8"
|
||||
"@standard-schema/spec" "^1.1.0"
|
||||
eventsource-parser "^3.0.6"
|
||||
|
||||
"@ai-sdk/provider@2.0.1", "@ai-sdk/provider@^2.0.0":
|
||||
version "2.0.1"
|
||||
@ -113,6 +106,13 @@
|
||||
dependencies:
|
||||
json-schema "^0.4.0"
|
||||
|
||||
"@ai-sdk/provider@3.0.8", "@ai-sdk/provider@^3.0.0":
|
||||
version "3.0.8"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/provider/-/provider-3.0.8.tgz#fd7fac7533c03534ac1d3fb710a6b96e2aa00263"
|
||||
integrity sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==
|
||||
dependencies:
|
||||
json-schema "^0.4.0"
|
||||
|
||||
"@ai-sdk/xai@^3.0.47":
|
||||
version "3.0.47"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/xai/-/xai-3.0.47.tgz#a8d3e08603865c5e401e19c801c7a80c3f31b890"
|
||||
@ -3160,11 +3160,6 @@ ms@^2.0.0, ms@^2.1.1, ms@^2.1.3:
|
||||
resolved "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
nanoid@^3.3.8:
|
||||
version "3.3.11"
|
||||
resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b"
|
||||
integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==
|
||||
|
||||
napi-build-utils@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmmirror.com/napi-build-utils/-/napi-build-utils-2.0.0.tgz#13c22c0187fcfccce1461844136372a47ddc027e"
|
||||
@ -3614,13 +3609,13 @@ quick-lru@^5.1.1:
|
||||
resolved "https://registry.npmmirror.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
|
||||
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
|
||||
|
||||
qwen-ai-provider@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.npmmirror.com/qwen-ai-provider/-/qwen-ai-provider-0.1.1.tgz#f854379514eed919fe01de20007f6238a8ad2b41"
|
||||
integrity sha512-7dVu97U7fbOGgCYdaOunC4NQqC+7Or3/Gsbx+P16+Ny4VxST7WJxfUCogQl6D2EDxIJdHGz4akHm+5fyEulmyw==
|
||||
qwen-ai-provider-v5@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmmirror.com/qwen-ai-provider-v5/-/qwen-ai-provider-v5-2.1.0.tgz#8672871135bb4a5fda32409c00b70d10637f8a50"
|
||||
integrity sha512-I+Iv45ymrez1wieZFu0n/lc/lSkbAQMlujWBCfUWBUOf6DizYfvPKaydsojXM7CU8TcqJbYJuN3ofnaxFIwBZA==
|
||||
dependencies:
|
||||
"@ai-sdk/provider" "^1.0.7"
|
||||
"@ai-sdk/provider-utils" "^2.1.6"
|
||||
"@ai-sdk/provider" "^3.0.0"
|
||||
"@ai-sdk/provider-utils" "^4.0.0"
|
||||
|
||||
range-parser@^1.2.1:
|
||||
version "1.2.1"
|
||||
@ -3846,11 +3841,6 @@ sax@^1.2.4:
|
||||
resolved "https://registry.npmmirror.com/sax/-/sax-1.4.4.tgz#f29c2bba80ce5b86f4343b4c2be9f2b96627cf8b"
|
||||
integrity sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==
|
||||
|
||||
secure-json-parse@^2.7.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.npmmirror.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862"
|
||||
integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==
|
||||
|
||||
semver-compare@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmmirror.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user