修复bug
This commit is contained in:
parent
f3928b8a4c
commit
1c65d00881
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "toonflow-app",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.7-patch2",
|
||||
"description": "Toonflow 是一款 AI 短剧漫剧工具,能够利用 AI 技术将小说自动转化为剧本,并结合 AI 生成的图片和视频,实现高效的短剧创作。",
|
||||
"author": "HBAI-Ltd <ltlctools@outlook.com>",
|
||||
"homepage": "https://github.com/HBAI-Ltd/Toonflow-app#readme",
|
||||
@ -37,7 +37,7 @@
|
||||
"@ai-sdk/anthropic": "^3.0.35",
|
||||
"@ai-sdk/deepseek": "^2.0.17",
|
||||
"@ai-sdk/devtools": "^0.0.11",
|
||||
"@ai-sdk/google": "^3.0.20",
|
||||
"@ai-sdk/google": "^3.0.43",
|
||||
"@ai-sdk/openai": "^3.0.25",
|
||||
"@ai-sdk/openai-compatible": "^2.0.27",
|
||||
"@ai-sdk/xai": "^3.0.47",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -175,14 +175,25 @@ async function processImages(images: ImageInfo[]): Promise<Buffer[]> {
|
||||
let processedBuffers: Buffer[];
|
||||
|
||||
if (images.length <= maxImages) {
|
||||
console.log("%c Line:178 🥤 images", "background:#ffdd4d", images);
|
||||
|
||||
console.log("%c Line:179 🍑", "background:#ed9ec7");
|
||||
const buffers = await Promise.all(images.map((img) => u.oss.getFile(img.filePath)));
|
||||
console.log("%c Line:179 🧀 buffers", "background:#ffdd4d", buffers);
|
||||
processedBuffers = await Promise.all(buffers.map((buffer) => compressImage(buffer)));
|
||||
console.log("%c Line:181 🍇 processedBuffers", "background:#e41a6a", processedBuffers);
|
||||
} else {
|
||||
const mergeStartIndex = maxImages - 1;
|
||||
|
||||
console.log("%c Line:183 🍖", "background:#6ec1c2");
|
||||
const firstBuffers = await Promise.all(images.slice(0, mergeStartIndex).map((img) => u.oss.getFile(img.filePath)));
|
||||
console.log("%c Line:183 🍉 firstBuffers", "background:#42b983", firstBuffers);
|
||||
const compressedFirstImages = await Promise.all(firstBuffers.map((buffer) => compressImage(buffer)));
|
||||
console.log("%c Line:185 🍺 compressedFirstImages", "background:#42b983", compressedFirstImages);
|
||||
const imagesToMergeList = images.slice(mergeStartIndex).map((img) => img.filePath);
|
||||
console.log("%c Line:187 🍿 imagesToMergeList", "background:#b03734", imagesToMergeList);
|
||||
const mergedImage = await mergeImages(imagesToMergeList);
|
||||
console.log("%c Line:189 🍉 mergedImage", "background:#ed9ec7", mergedImage);
|
||||
processedBuffers = [...compressedFirstImages, mergedImage];
|
||||
}
|
||||
|
||||
@ -288,6 +299,7 @@ export default async (cells: { prompt: string }[], scriptId: number, projectId:
|
||||
|
||||
// 使用 AI 过滤相关资产
|
||||
const filteredImages = await filterRelevantAssets(cellPrompts, resources, allImages);
|
||||
console.log("%c Line:291 🍇 filteredImages", "background:#4fff4B", filteredImages);
|
||||
|
||||
const resourcesMapPrompts = buildResourcesMapPrompts(filteredImages);
|
||||
console.log("====润色前:", cellPrompts);
|
||||
@ -324,6 +336,7 @@ export default async (cells: { prompt: string }[], scriptId: number, projectId:
|
||||
},
|
||||
apiConfig,
|
||||
);
|
||||
console.log("%c Line:315 🍊 contentStr", "background:#ffdd4d", contentStr);
|
||||
|
||||
const match = contentStr.match(/base64,([A-Za-z0-9+/=]+)/);
|
||||
const base64Str = match?.[1] ?? contentStr;
|
||||
|
||||
@ -98,7 +98,6 @@ export default class Storyboard {
|
||||
|
||||
private log(action: string, detail?: string) {
|
||||
const msg = detail ? `${action}: ${detail}` : action;
|
||||
console.log(`\n[${new Date().toLocaleTimeString()}] ${msg}\n`);
|
||||
}
|
||||
|
||||
// ==================== 剧本相关操作 ====================
|
||||
@ -242,7 +241,6 @@ ${sections.join("\n\n")}
|
||||
const skipped: number[] = [];
|
||||
|
||||
for (const item of shots) {
|
||||
|
||||
const exists = this.shots.some((f) => f.segmentId === item.segmentIndex);
|
||||
if (exists) {
|
||||
skipped.push(item.segmentIndex);
|
||||
@ -445,6 +443,7 @@ ${sections.join("\n\n")}
|
||||
this.scriptId,
|
||||
this.projectId,
|
||||
);
|
||||
|
||||
// 通知前端正在分割图片
|
||||
this.emit("shotImageGenerateProgress", { shotId, status: "splitting", message: "正在分割宫格图片为单张镜头图" });
|
||||
|
||||
@ -460,8 +459,10 @@ ${sections.join("\n\n")}
|
||||
|
||||
for (let i = 0; i < imageBuffers.length; i++) {
|
||||
const fileName = `${this.projectId}/chat/${this.scriptId}/storyboard/shot_${shotId}_take_${i}_${timestamp}.png`;
|
||||
|
||||
await u.oss.writeFile(fileName, imageBuffers[i]);
|
||||
const imageUrl = await u.oss.getFileUrl(fileName);
|
||||
|
||||
imagePaths.push(imageUrl);
|
||||
|
||||
// 每保存一张镜头图片通知进度
|
||||
|
||||
@ -97,7 +97,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
name: "t_project",
|
||||
builder: (table) => {
|
||||
table.integer("id");
|
||||
table.string("projectType");
|
||||
// table.string("projectType");
|
||||
table.text("name");
|
||||
table.text("intro");
|
||||
table.text("type");
|
||||
@ -195,23 +195,23 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
},
|
||||
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.text("reason");
|
||||
table.primary(["id"]);
|
||||
table.unique(["id"]);
|
||||
},
|
||||
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.text("reason");
|
||||
// table.primary(["id"]);
|
||||
// table.unique(["id"]);
|
||||
// },
|
||||
// initData: async (knex) => {},
|
||||
// },
|
||||
{
|
||||
name: "t_artStyle",
|
||||
builder: (table) => {
|
||||
@ -668,6 +668,7 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
{ manufacturer: "grsai", model: "nano-banana-pro", grid: 1, type: "ti2i" },
|
||||
{ manufacturer: "grsai", model: "nano-banana", grid: 1, type: "ti2i" },
|
||||
{ manufacturer: "grsai", model: "nano-banana-2", grid: 1, type: "ti2i" },
|
||||
{ manufacturer: "formal", model: "Qwen-Image", grid: 1, type: "ti2i" },
|
||||
]);
|
||||
},
|
||||
},
|
||||
@ -686,7 +687,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
initData: async (knex) => {
|
||||
await knex("t_videoModel").insert([
|
||||
{
|
||||
id: 1,
|
||||
manufacturer: "volcengine",
|
||||
model: "doubao-seedance-1-5-pro-251215",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [4, 5, 6, 7, 8, 9, 10, 11, 12], resolution: ["480p", "720p", "1080p"] }]),
|
||||
@ -695,7 +695,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["text", "endFrameOptional"]),
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
manufacturer: "volcengine",
|
||||
model: "doubao-seedance-1-0-pro-250528",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], resolution: ["480p", "720p", "1080p"] }]),
|
||||
@ -704,7 +703,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["text", "endFrameOptional"]),
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
manufacturer: "volcengine",
|
||||
model: "doubao-seedance-1-0-pro-fast-251015",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], resolution: ["480p", "720p", "1080p"] }]),
|
||||
@ -713,7 +711,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["text", "singleImage"]),
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
manufacturer: "volcengine",
|
||||
model: "doubao-seedance-1-0-lite-i2v-250428",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], resolution: ["480p", "720p", "1080p"] }]),
|
||||
@ -722,7 +719,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["endFrameOptional", "reference"]),
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
manufacturer: "volcengine",
|
||||
model: "doubao-seedance-1-0-lite-t2v-250428",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], resolution: ["480p", "720p", "1080p"] }]),
|
||||
@ -731,97 +727,46 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["text"]),
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
manufacturer: "kling",
|
||||
model: "kling-v1(STD)",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5, 10], resolution: ["720p"] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "1:1", "9:16"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["text"]),
|
||||
type: JSON.stringify(["text", "startEndRequired"]),
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
manufacturer: "kling",
|
||||
model: "kling-v1(STD)",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5, 10], resolution: ["720p"] }]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["startEndRequired"]),
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
manufacturer: "kling",
|
||||
model: "kling-v1(PRO)",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5, 10], resolution: ["1080p"] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "1:1", "9:16"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["text"]),
|
||||
type: JSON.stringify(["text", "startEndRequired"]),
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
manufacturer: "kling",
|
||||
model: "kling-v1(PRO)",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5, 10], resolution: ["1080p"] }]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["startEndRequired"]),
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
manufacturer: "kling",
|
||||
model: "kling-v1-6(PRO)",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5, 10], resolution: ["1080p"] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "1:1", "9:16"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["text"]),
|
||||
type: JSON.stringify(["text", "startEndRequired"]),
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
manufacturer: "kling",
|
||||
model: "kling-v1-6(PRO)",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5, 10], resolution: ["1080p"] }]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["startEndRequired"]),
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
manufacturer: "kling",
|
||||
model: "kling-v2-5-turbo(PRO)",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5, 10], resolution: ["1080p"] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "1:1", "9:16"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["text"]),
|
||||
type: JSON.stringify(["text", "startEndRequired"]),
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
manufacturer: "kling",
|
||||
model: "kling-v2-5-turbo(PRO)",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5, 10], resolution: ["1080p"] }]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["startEndRequired"]),
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
manufacturer: "kling",
|
||||
model: "kling-v2-6(PRO)",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5, 10], resolution: ["1080p"] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "1:1", "9:16"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["text"]),
|
||||
type: JSON.stringify(["text", "startEndRequired"]),
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
manufacturer: "kling",
|
||||
model: "kling-v2-6(PRO)",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5, 10], resolution: ["1080p"] }]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["startEndRequired"]),
|
||||
},
|
||||
{
|
||||
id: 16,
|
||||
manufacturer: "vidu",
|
||||
model: "viduq3-pro",
|
||||
durationResolutionMap: JSON.stringify([
|
||||
@ -829,21 +774,9 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16", "3:4", "4:3", "1:1"]),
|
||||
audio: 1,
|
||||
type: JSON.stringify(["text"]),
|
||||
type: JSON.stringify(["text", "singleImage"]),
|
||||
},
|
||||
{
|
||||
id: 17,
|
||||
manufacturer: "vidu",
|
||||
model: "viduq3-pro",
|
||||
durationResolutionMap: JSON.stringify([
|
||||
{ duration: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], resolution: ["540p", "720p", "1080p"] },
|
||||
]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 1,
|
||||
type: JSON.stringify(["singleImage"]),
|
||||
},
|
||||
{
|
||||
id: 18,
|
||||
manufacturer: "vidu",
|
||||
model: "viduq2-pro-fast",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], resolution: ["720p", "1080p"] }]),
|
||||
@ -852,61 +785,30 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["singleImage", "startEndRequired"]),
|
||||
},
|
||||
{
|
||||
id: 19,
|
||||
manufacturer: "vidu",
|
||||
model: "viduq2-pro",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], resolution: ["540p", "720p", "1080p"] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16", "3:4", "4:3", "1:1"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["text"]),
|
||||
},
|
||||
{
|
||||
id: 20,
|
||||
manufacturer: "vidu",
|
||||
model: "viduq2-pro",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], resolution: ["540p", "720p", "1080p"] }]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["singleImage", "reference", "startEndRequired"]),
|
||||
type: JSON.stringify(["singleImage", "reference", "startEndRequired", "text"]),
|
||||
},
|
||||
{
|
||||
id: 21,
|
||||
manufacturer: "vidu",
|
||||
model: "viduq2-turbo",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], resolution: ["540p", "720p", "1080p"] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16", "3:4", "4:3", "1:1"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["text"]),
|
||||
},
|
||||
{
|
||||
id: 22,
|
||||
manufacturer: "vidu",
|
||||
model: "viduq2-turbo",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], resolution: ["540p", "720p", "1080p"] }]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["singleImage", "reference", "startEndRequired"]),
|
||||
type: JSON.stringify(["singleImage", "reference", "startEndRequired", "text"]),
|
||||
},
|
||||
{
|
||||
id: 23,
|
||||
manufacturer: "vidu",
|
||||
model: "viduq1",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5], resolution: ["1080p"] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16", "1:1"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["text"]),
|
||||
},
|
||||
{
|
||||
id: 24,
|
||||
manufacturer: "vidu",
|
||||
model: "viduq1",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5], resolution: ["1080p"] }]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["singleImage", "reference", "startEndRequired"]),
|
||||
type: JSON.stringify(["singleImage", "reference", "startEndRequired", "text"]),
|
||||
},
|
||||
{
|
||||
id: 25,
|
||||
manufacturer: "vidu",
|
||||
model: "viduq1-classic",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5], resolution: ["1080p"] }]),
|
||||
@ -915,7 +817,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["singleImage", "startEndRequired"]),
|
||||
},
|
||||
{
|
||||
id: 26,
|
||||
manufacturer: "vidu",
|
||||
model: "vidu2.0",
|
||||
durationResolutionMap: JSON.stringify([
|
||||
@ -927,7 +828,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["singleImage", "reference", "startEndRequired"]),
|
||||
},
|
||||
{
|
||||
id: 27,
|
||||
manufacturer: "wan",
|
||||
model: "wan2.6-t2v",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], resolution: ["720p", "1080p"] }]),
|
||||
@ -936,7 +836,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["text"]),
|
||||
},
|
||||
{
|
||||
id: 28,
|
||||
manufacturer: "wan",
|
||||
model: "wan2.5-t2v-preview",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5, 10], resolution: ["480p", "720p", "1080p"] }]),
|
||||
@ -945,7 +844,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["text"]),
|
||||
},
|
||||
{
|
||||
id: 29,
|
||||
manufacturer: "wan",
|
||||
model: "wan2.2-t2v-plus",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5], resolution: ["480p", "1080p"] }]),
|
||||
@ -954,7 +852,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["text"]),
|
||||
},
|
||||
{
|
||||
id: 30,
|
||||
manufacturer: "wan",
|
||||
model: "wanx2.1-t2v-turbo",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5], resolution: ["480p", "720p"] }]),
|
||||
@ -963,7 +860,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["text"]),
|
||||
},
|
||||
{
|
||||
id: 31,
|
||||
manufacturer: "wan",
|
||||
model: "wanx2.1-t2v-plus",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5], resolution: ["720p"] }]),
|
||||
@ -972,7 +868,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["text"]),
|
||||
},
|
||||
{
|
||||
id: 32,
|
||||
manufacturer: "wan",
|
||||
model: "wan2.6-i2v-flash",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], resolution: ["720p", "1080p"] }]),
|
||||
@ -981,7 +876,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["singleImage"]),
|
||||
},
|
||||
{
|
||||
id: 33,
|
||||
manufacturer: "wan",
|
||||
model: "wan2.6-i2v",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], resolution: ["720p", "1080p"] }]),
|
||||
@ -990,7 +884,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["singleImage"]),
|
||||
},
|
||||
{
|
||||
id: 34,
|
||||
manufacturer: "wan",
|
||||
model: "wan2.5-i2v-preview",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5, 10], resolution: ["480p", "720p", "1080p"] }]),
|
||||
@ -999,7 +892,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["singleImage"]),
|
||||
},
|
||||
{
|
||||
id: 35,
|
||||
manufacturer: "wan",
|
||||
model: "wan2.2-i2v-flash",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5], resolution: ["480p", "720p", "1080p"] }]),
|
||||
@ -1008,7 +900,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["singleImage"]),
|
||||
},
|
||||
{
|
||||
id: 36,
|
||||
manufacturer: "wan",
|
||||
model: "wan2.2-i2v-plus",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5], resolution: ["480p", "1080p"] }]),
|
||||
@ -1017,7 +908,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["singleImage"]),
|
||||
},
|
||||
{
|
||||
id: 37,
|
||||
manufacturer: "wan",
|
||||
model: "wanx2.1-i2v-plus",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5], resolution: ["720p"] }]),
|
||||
@ -1026,7 +916,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["singleImage"]),
|
||||
},
|
||||
{
|
||||
id: 38,
|
||||
manufacturer: "wan",
|
||||
model: "wanx2.1-i2v-turbo",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [3, 4, 5], resolution: ["480p", "720p"] }]),
|
||||
@ -1035,7 +924,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["singleImage"]),
|
||||
},
|
||||
{
|
||||
id: 39,
|
||||
manufacturer: "wan",
|
||||
model: "wan2.2-kf2v-flash",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5], resolution: ["480p", "720p", "1080p"] }]),
|
||||
@ -1044,7 +932,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["startEndRequired"]),
|
||||
},
|
||||
{
|
||||
id: 40,
|
||||
manufacturer: "wan",
|
||||
model: "wanx2.1-kf2v-plus",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5], resolution: ["720p"] }]),
|
||||
@ -1053,7 +940,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["startEndRequired"]),
|
||||
},
|
||||
{
|
||||
id: 41,
|
||||
manufacturer: "gemini",
|
||||
model: "veo-3.1-generate-preview",
|
||||
durationResolutionMap: JSON.stringify([
|
||||
@ -1065,7 +951,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["text", "singleImage", "startEndRequired", "endFrameOptional", "reference"]),
|
||||
},
|
||||
{
|
||||
id: 42,
|
||||
manufacturer: "gemini",
|
||||
model: "veo-3.1-fast-generate-preview",
|
||||
durationResolutionMap: JSON.stringify([
|
||||
@ -1077,7 +962,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["text", "singleImage", "startEndRequired", "endFrameOptional", "reference"]),
|
||||
},
|
||||
{
|
||||
id: 43,
|
||||
manufacturer: "gemini",
|
||||
model: "veo-3.0-generate-preview",
|
||||
durationResolutionMap: JSON.stringify([
|
||||
@ -1089,7 +973,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["text", "singleImage"]),
|
||||
},
|
||||
{
|
||||
id: 44,
|
||||
manufacturer: "gemini",
|
||||
model: "veo-3.0-fast-generate-preview",
|
||||
durationResolutionMap: JSON.stringify([
|
||||
@ -1101,7 +984,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["text", "singleImage"]),
|
||||
},
|
||||
{
|
||||
id: 45,
|
||||
manufacturer: "gemini",
|
||||
model: "veo-2.0-generate-001",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5, 6, 7, 8], resolution: ["720p"] }]),
|
||||
@ -1110,34 +992,30 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["text", "singleImage"]),
|
||||
},
|
||||
{
|
||||
id: 46,
|
||||
manufacturer: "runninghub",
|
||||
model: "sora-2",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [10, 15], resolution: [] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["singleImage", "text"]),
|
||||
type: JSON.stringify(["singleImage", "text", "multiImage"]),
|
||||
},
|
||||
{
|
||||
id: 47,
|
||||
manufacturer: "runninghub",
|
||||
model: "sora-2-pro",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [15, 25], resolution: [] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["singleImage", "text"]),
|
||||
type: JSON.stringify(["singleImage", "text", "multiImage"]),
|
||||
},
|
||||
{
|
||||
id: 48,
|
||||
manufacturer: "grsai",
|
||||
model: "sora-2",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [10, 15], resolution: [] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["singleImage", "text"]),
|
||||
type: JSON.stringify(["singleImage", "text", "multiImage"]),
|
||||
},
|
||||
{
|
||||
id: 49,
|
||||
manufacturer: "grsai",
|
||||
model: "veo3.1-pro",
|
||||
durationResolutionMap: JSON.stringify([]),
|
||||
@ -1147,7 +1025,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
},
|
||||
|
||||
{
|
||||
id: 50,
|
||||
manufacturer: "grsai",
|
||||
model: "veo3.1-pro-1080p",
|
||||
durationResolutionMap: JSON.stringify([]),
|
||||
@ -1156,7 +1033,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["startEndRequired", "text"]),
|
||||
},
|
||||
{
|
||||
id: 51,
|
||||
manufacturer: "grsai",
|
||||
model: "veo3.1-pro-4k",
|
||||
durationResolutionMap: JSON.stringify([]),
|
||||
@ -1165,7 +1041,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["startEndRequired", "text"]),
|
||||
},
|
||||
{
|
||||
id: 52,
|
||||
manufacturer: "grsai",
|
||||
model: "veo3.1-fast",
|
||||
durationResolutionMap: JSON.stringify([]),
|
||||
@ -1174,7 +1049,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["startEndRequired", "text"]),
|
||||
},
|
||||
{
|
||||
id: 53,
|
||||
manufacturer: "grsai",
|
||||
model: "veo3.1-fast-1080p",
|
||||
durationResolutionMap: JSON.stringify([]),
|
||||
@ -1183,7 +1057,6 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
type: JSON.stringify(["startEndRequired", "text"]),
|
||||
},
|
||||
{
|
||||
id: 54,
|
||||
manufacturer: "grsai",
|
||||
model: "veo3.1-fast-4k",
|
||||
durationResolutionMap: JSON.stringify([]),
|
||||
@ -1191,6 +1064,153 @@ export default async (knex: Knex, forceInit: boolean = false): Promise<void> =>
|
||||
audio: 0,
|
||||
type: JSON.stringify(["startEndRequired", "text"]),
|
||||
},
|
||||
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "Seedance-1.5-Pro",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [4, 5, 6, 7, 8, 9, 10, 11, 12], resolution: ["480p", "720p", "1080p"] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16"]),
|
||||
audio: 1,
|
||||
type: JSON.stringify(["endFrameOptional", "text"]),
|
||||
},
|
||||
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "Seedance-1.0-Pro",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], resolution: ["480p", "720p", "1080p"] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["text", "endFrameOptional"]),
|
||||
},
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "Seedance-1.0-Pro-Fast",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], resolution: ["480p", "720p", "1080p"] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["text", "singleImage"]),
|
||||
},
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "Seedance-1.0-Lite-I2V",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], resolution: ["480p", "720p", "1080p"] }]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["endFrameOptional", "reference"]),
|
||||
},
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "Seedance-1.0-Lite-T2V",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], resolution: ["480p", "720p", "1080p"] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["text"]),
|
||||
},
|
||||
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "ViduQ3-turbo",
|
||||
durationResolutionMap: JSON.stringify([
|
||||
{ duration: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], resolution: ["540p", "720p", "1080p"] },
|
||||
]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16", "3:4", "4:3", "1:1"]),
|
||||
audio: 1,
|
||||
type: JSON.stringify(["text", "singleImage"]),
|
||||
},
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "ViduQ3-pro",
|
||||
durationResolutionMap: JSON.stringify([
|
||||
{ duration: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], resolution: ["540p", "720p", "1080p"] },
|
||||
]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16", "3:4", "4:3", "1:1"]),
|
||||
audio: 1,
|
||||
type: JSON.stringify(["text", "singleImage"]),
|
||||
},
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "ViduQ2-pro-fast",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], resolution: ["720p", "1080p"] }]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["singleImage", "startEndRequired"]),
|
||||
},
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "ViduQ2-pro",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], resolution: ["540p", "720p", "1080p"] }]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["singleImage", "reference", "startEndRequired", "text"]),
|
||||
},
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "ViduQ2-turbo",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], resolution: ["540p", "720p", "1080p"] }]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["singleImage", "reference", "startEndRequired", "text"]),
|
||||
},
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "ViduQ2",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], resolution: ["540p", "720p", "1080p"] }]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["singleImage", "reference", "startEndRequired", "text"]),
|
||||
},
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "ViduQ1",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5], resolution: ["1080p"] }]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["singleImage", "reference", "startEndRequired", "text"]),
|
||||
},
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "ViduQ1-classic",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [5], resolution: ["1080p"] }]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["singleImage", "startEndRequired"]),
|
||||
},
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "Vidu2.0",
|
||||
durationResolutionMap: JSON.stringify([
|
||||
{ duration: [4], resolution: ["360p", "720p", "1080p"] },
|
||||
{ duration: [8], resolution: ["720p"] },
|
||||
]),
|
||||
aspectRatio: JSON.stringify([]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["singleImage", "reference", "startEndRequired"]),
|
||||
},
|
||||
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "Hailuo-2.3-I2V",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [6, 7, 8, 9, 10], resolution: ["1080p"] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["endFrameOptional"]),
|
||||
},
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "Hailuo-2.3-Fast",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [6, 7, 8, 9, 10], resolution: ["1080p"] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["endFrameOptional"]),
|
||||
},
|
||||
{
|
||||
manufacturer: "formal",
|
||||
model: "Hailuo-2.3-T2V",
|
||||
durationResolutionMap: JSON.stringify([{ duration: [6, 7, 8, 9, 10], resolution: ["1080p"] }]),
|
||||
aspectRatio: JSON.stringify(["16:9", "9:16"]),
|
||||
audio: 0,
|
||||
type: JSON.stringify(["text"]),
|
||||
},
|
||||
]);
|
||||
},
|
||||
},
|
||||
|
||||
@ -40,7 +40,7 @@ export default router.post(
|
||||
const { id, type, projectId, base64, prompt, name } = req.body;
|
||||
|
||||
//获取风格
|
||||
const project = await u.db("t_project").where("id", projectId).select("artStyle", "type", "intro").first();
|
||||
const project = await u.db("t_project").where("id", projectId).select("artStyle", "type", "intro", "videoRatio").first();
|
||||
if (!project) return res.status(500).send(success({ message: "项目为空" }));
|
||||
|
||||
const promptsList = await u
|
||||
@ -137,7 +137,7 @@ export default router.post(
|
||||
prompt: userPrompt,
|
||||
imageBase64: base64 ? [base64] : [],
|
||||
size: "2K",
|
||||
aspectRatio: "16:9",
|
||||
aspectRatio: project.videoRatio ?? "16:9",
|
||||
taskClass: taskClass,
|
||||
name: name,
|
||||
describe: prompt,
|
||||
|
||||
@ -48,6 +48,7 @@ export default router.post(
|
||||
);
|
||||
res.status(200).send(success(reply));
|
||||
} catch (err) {
|
||||
console.log("%c Line:51 🍬 err", "background:#465975", err);
|
||||
const msg = u.error(err).message;
|
||||
console.error(msg);
|
||||
res.status(500).send(error(msg));
|
||||
|
||||
@ -23,7 +23,7 @@ export default router.post(
|
||||
"一张16:9比例的图片,完美等分为2x2四宫格布局,各区域无缝衔接:\n左上宫格:一只可爱的猫,毛发蓬松,眼睛明亮,姿态俏皮\n右上宫格:一只友善的狗,金毛犬,表情愉悦,摇着尾巴\n左下宫格:一头健壮的牛,田园背景,目光温和,皮毛光泽\n右下宫格:一匹骏马,姿态优雅,鬃毛飘逸,肌肉健美\n风格要求:四个宫格风格统一,色彩鲜艳饱和,高清画质,细节清晰锐利,专业插画风格,线条干净,统一的左上方光源,柔和阴影,和谐配色,卡通/半写实风格,宫格间用白色或浅灰细线分隔",
|
||||
imageBase64: [],
|
||||
aspectRatio: "9:16",
|
||||
size: "1K",
|
||||
size: "4K",
|
||||
taskClass: "测试任务",
|
||||
name: "测试图片生成",
|
||||
describe: "测试语言模型生成图片",
|
||||
@ -38,6 +38,7 @@ export default router.post(
|
||||
);
|
||||
res.status(200).send(success(image));
|
||||
} catch (err) {
|
||||
console.log("%c Line:41 🍖 err", "background:#fca650", err);
|
||||
const msg = u.error(err).message;
|
||||
console.error(msg);
|
||||
res.status(500).send(error(msg));
|
||||
|
||||
@ -9,7 +9,7 @@ const router = express.Router();
|
||||
export default router.post(
|
||||
"/",
|
||||
validateFields({
|
||||
projectType: z.string(),
|
||||
projectType: z.string().optional(),
|
||||
name: z.string(),
|
||||
intro: z.string(),
|
||||
type: z.string(),
|
||||
@ -20,7 +20,6 @@ export default router.post(
|
||||
const { projectType, name, intro, type, artStyle, videoRatio } = req.body;
|
||||
|
||||
await u.db("t_project").insert({
|
||||
projectType,
|
||||
name,
|
||||
intro,
|
||||
type,
|
||||
|
||||
@ -27,7 +27,7 @@ export default router.post(
|
||||
await u.db("t_novel").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_myTasks").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_assets").where("projectId", id).delete();
|
||||
|
||||
@ -24,7 +24,6 @@ export default router.post(
|
||||
type,
|
||||
artStyle,
|
||||
videoRatio,
|
||||
projectType,
|
||||
});
|
||||
|
||||
res.status(200).send(success({ message: "修改成功" }));
|
||||
|
||||
@ -99,9 +99,9 @@ const prompt = `
|
||||
`;
|
||||
async function urlToBase64(imageUrl: string): Promise<string> {
|
||||
const response = await axios.get(imageUrl, { responseType: "arraybuffer" });
|
||||
const contentType = response.headers["content-type"] || "image/png";
|
||||
const contentType = response.headers["content-type"] || "image/jpg";
|
||||
const base64 = Buffer.from(response.data, "binary").toString("base64");
|
||||
return `data:${contentType};base64,${base64}`;
|
||||
return `${base64}`;
|
||||
}
|
||||
// 生成单个分镜提示
|
||||
async function generateSingleVideoPrompt({
|
||||
@ -113,6 +113,8 @@ async function generateSingleVideoPrompt({
|
||||
storyboardPrompt: string;
|
||||
ossPath: string;
|
||||
}): Promise<{ content: string; time: number; name: string }> {
|
||||
console.log("%c Line:116 🍭 ossPath", "background:#6ec1c2", ossPath);
|
||||
|
||||
const messages: any[] = [
|
||||
{
|
||||
role: "system",
|
||||
@ -134,8 +136,10 @@ async function generateSingleVideoPrompt({
|
||||
];
|
||||
|
||||
try {
|
||||
console.log("%c Line:140 🍩", "background:#4fff4B");
|
||||
const apiConfig = await u.getPromptAi("videoPrompt");
|
||||
|
||||
console.log("%c Line:143 🍑", "background:#e41a6a");
|
||||
const result = await u.ai.text.invoke(
|
||||
{
|
||||
messages,
|
||||
@ -159,6 +163,7 @@ async function generateSingleVideoPrompt({
|
||||
|
||||
return result;
|
||||
} catch (err: any) {
|
||||
console.log("%c Line:167 🥤 err", "background:#465975", err);
|
||||
console.error("generateSingleVideoPrompt 调用失败:", err?.message || err);
|
||||
throw new Error(`生成视频提示词失败: ${err?.message || "未知错误"}`);
|
||||
}
|
||||
|
||||
@ -35,11 +35,18 @@ export default router.post(
|
||||
return res.status(500).send(error("请先选择图片"));
|
||||
}
|
||||
const configData = await u.db("t_videoConfig").where("id", configId).first();
|
||||
|
||||
if (!configData) {
|
||||
return res.status(500).send(error("视频配置不存在"));
|
||||
}
|
||||
if (configData.manufacturer == "runninghub") {
|
||||
// 优先使用视频配置中的AI配置ID查询,查不到再使用传入的aiConfigId
|
||||
let aiConfigData = null;
|
||||
if (configData.aiConfigId) {
|
||||
aiConfigData = await u.db("t_config").where("id", configData.aiConfigId).first();
|
||||
}
|
||||
if (!aiConfigData || !aiConfigData?.model) {
|
||||
return res.status(500).send(error("模型不存在"));
|
||||
}
|
||||
if (aiConfigData.model?.includes("sora")) {
|
||||
if (filePath.length > 1) {
|
||||
const gridUrl = await sharpProcessingImage(filePath, projectId);
|
||||
if (gridUrl) {
|
||||
@ -49,18 +56,6 @@ export default router.post(
|
||||
}
|
||||
}
|
||||
|
||||
// 优先使用视频配置中的AI配置ID查询,查不到再使用传入的aiConfigId
|
||||
let aiConfigData = null;
|
||||
if (configData.aiConfigId) {
|
||||
aiConfigData = await u.db("t_config").where("id", configData.aiConfigId).first();
|
||||
}
|
||||
if (!aiConfigData) {
|
||||
aiConfigData = await u.db("t_config").where("id", aiConfigId).first();
|
||||
}
|
||||
|
||||
if (!aiConfigData) {
|
||||
return res.status(500).send(error("模型配置不存在"));
|
||||
}
|
||||
// 过滤掉空值
|
||||
let fileUrl = filePath.filter((p: string) => p && p.trim() !== "");
|
||||
|
||||
@ -201,7 +196,7 @@ ${prompt}
|
||||
await u.db("t_video").where("id", videoId).update({ state: -1 });
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`视频生成失败 videoId=${videoId}:`, err);
|
||||
// console.error(`视频生成失败 videoId=${videoId}:`, (err as any).response);
|
||||
await u
|
||||
.db("t_video")
|
||||
.where("id", videoId)
|
||||
|
||||
15
src/types/database.d.ts
vendored
15
src/types/database.d.ts
vendored
@ -1,4 +1,4 @@
|
||||
// @db-hash 8171d26b6ac1f411a6ec46a0381b821a
|
||||
// @db-hash a7e02eb0ccc2f0608c1cafc9191f3291
|
||||
//该文件由脚本自动生成,请勿手动修改
|
||||
|
||||
export interface t_aiModelMap {
|
||||
@ -64,17 +64,6 @@ export interface t_imageModel {
|
||||
'model'?: 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 {
|
||||
'chapter'?: string | null;
|
||||
'chapterData'?: string | null;
|
||||
@ -96,7 +85,6 @@ export interface t_project {
|
||||
'id'?: number | null;
|
||||
'intro'?: string | null;
|
||||
'name'?: string | null;
|
||||
'projectType'?: string | null;
|
||||
'type'?: string | null;
|
||||
'userId'?: number | null;
|
||||
'videoRatio'?: string | null;
|
||||
@ -197,7 +185,6 @@ export interface DB {
|
||||
"t_config": t_config;
|
||||
"t_image": t_image;
|
||||
"t_imageModel": t_imageModel;
|
||||
"t_myTasks": t_myTasks;
|
||||
"t_novel": t_novel;
|
||||
"t_outline": t_outline;
|
||||
"t_project": t_project;
|
||||
|
||||
@ -13,7 +13,7 @@ import gemini from "./owned/gemini";
|
||||
import modelScope from "./owned/modelScope";
|
||||
import grsai from "./owned/grsai";
|
||||
import { tr } from "zod/locales";
|
||||
|
||||
import formal from "./owned/formal";
|
||||
const urlToBase64 = async (url: string): Promise<string> => {
|
||||
const res = await axios.get(url, { responseType: "arraybuffer" });
|
||||
const base64 = Buffer.from(res.data).toString("base64");
|
||||
@ -31,6 +31,7 @@ const modelInstance = {
|
||||
modelScope,
|
||||
other,
|
||||
grsai,
|
||||
formal,
|
||||
} as const;
|
||||
|
||||
export default async (input: ImageConfig, config: AIConfig) => {
|
||||
@ -46,15 +47,15 @@ export default async (input: ImageConfig, config: AIConfig) => {
|
||||
// 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,
|
||||
});
|
||||
// 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 内容类型字符串
|
||||
if (input.imageBase64 && input.imageBase64.length > 0) {
|
||||
input.imageBase64 = input.imageBase64.map((img) => {
|
||||
@ -82,15 +83,15 @@ export default async (input: ImageConfig, config: AIConfig) => {
|
||||
let imageUrl = await manufacturerFn(input, { model, apiKey, baseURL });
|
||||
if (!input.resType) input.resType = "b64";
|
||||
if (input.resType === "b64" && imageUrl.startsWith("http")) imageUrl = await urlToBase64(imageUrl);
|
||||
await u.db("t_myTasks").where("id", taskId).update({
|
||||
state: "已完成",
|
||||
});
|
||||
// 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,
|
||||
});
|
||||
// await u.db("t_myTasks").where("id", taskId).update({
|
||||
// state: "生成失败",
|
||||
// reason: error.message,
|
||||
// });
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
114
src/utils/ai/image/owned/formal.ts
Normal file
114
src/utils/ai/image/owned/formal.ts
Normal file
@ -0,0 +1,114 @@
|
||||
import "../type";
|
||||
import { generateImage, generateText, ModelMessage } from "ai";
|
||||
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
||||
import { pollTask } from "@/utils/ai/utils";
|
||||
import u from "@/utils";
|
||||
import axios from "axios";
|
||||
function getApiUrl(apiUrl: string) {
|
||||
if (apiUrl.includes("|")) {
|
||||
const parts = apiUrl.split("|");
|
||||
if (parts.length !== 2 || !parts[0].trim() || !parts[1].trim()) {
|
||||
throw new Error("url 格式错误,请使用 url1|url2 格式");
|
||||
}
|
||||
return { requestUrl: parts[0].trim(), queryUrl: parts[1].trim() };
|
||||
}
|
||||
throw new Error("请填写正确的url");
|
||||
}
|
||||
function template(replaceObj: Record<string, any>, url: string) {
|
||||
return url.replace(/\{(\w+)\}/g, (match, varName) => {
|
||||
return replaceObj.hasOwnProperty(varName) ? replaceObj[varName] : match;
|
||||
});
|
||||
}
|
||||
export default async (input: ImageConfig, config: AIConfig): Promise<string> => {
|
||||
if (!config.model) throw new Error("缺少Model名称");
|
||||
if (!config.apiKey) throw new Error("缺少API Key");
|
||||
|
||||
const defaultBaseURL = "http://192.168.0.74:3000/imagegenerator/task|http://192.168.0.74:3000/imagegenerator/task/{id}";
|
||||
const { requestUrl, queryUrl } = getApiUrl(config.baseURL! ?? defaultBaseURL);
|
||||
// 根据 size 配置映射到具体尺寸
|
||||
const sizeMap: Record<string, Record<string, string>> = {
|
||||
"1K": {
|
||||
"16:9": "1664x928",
|
||||
"9:16": "928x1664",
|
||||
},
|
||||
"2K": {
|
||||
"16:9": "2048x1152",
|
||||
"9:16": "1152x2048",
|
||||
},
|
||||
"4K": {
|
||||
"16:9": "2048x1152",
|
||||
"9:16": "1328*1328",
|
||||
},
|
||||
};
|
||||
const modelSizeMap = {
|
||||
"Qwen-Image": {
|
||||
"16:9": "1664*928",
|
||||
"9:16": "928*1664",
|
||||
},
|
||||
"Z-Image-Turbo": {
|
||||
"16:9": "1024*768",
|
||||
"9:16": "768*1024",
|
||||
},
|
||||
};
|
||||
// 构建完整的提示词
|
||||
const fullPrompt = input.systemPrompt ? `${input.systemPrompt}\n\n${input.prompt}` : input.prompt;
|
||||
|
||||
let mergedImage = input.imageBase64;
|
||||
if (mergedImage && mergedImage.length) {
|
||||
const smallImage = await u.imageTools.mergeImages(mergedImage, "5mb");
|
||||
mergedImage = [smallImage];
|
||||
}
|
||||
|
||||
const size = modelSizeMap?.[config.model]?.[input.size]?.[input.aspectRatio] ?? modelSizeMap?.[config.model]?.[input.size] ?? "1024*1024";
|
||||
|
||||
const taskBody: Record<string, any> = {
|
||||
model: config.model,
|
||||
input: {
|
||||
prompt: fullPrompt,
|
||||
...(input.imageBase64 && input.imageBase64.length ? { images: input.imageBase64 } : {}),
|
||||
},
|
||||
parameters: {
|
||||
size:"1600*2848",
|
||||
},
|
||||
// negative_prompt: "",
|
||||
};
|
||||
|
||||
const apiKey = config.apiKey.replace("Bearer ", "");
|
||||
try {
|
||||
const { data } = await axios.post(requestUrl, taskBody, { headers: { Authorization: `Bearer ${apiKey}` } });
|
||||
console.log("%c Line:70 🥪 data", "background:#ed9ec7", data);
|
||||
|
||||
if (data.code != "success") throw new Error(`任务提交失败: ${data || "未知错误"}`);
|
||||
const taskId = data.data;
|
||||
|
||||
return await pollTask(async () => {
|
||||
const { data: queryData } = await axios.get(template({ id: taskId }, queryUrl), {
|
||||
headers: { Authorization: `Bearer ${apiKey}` },
|
||||
});
|
||||
console.log("%c Line:77 🍧 data", "background:#f5ce50", data);
|
||||
console.log("%c Line:76 🥑 queryData", "background:#2eafb0", queryData);
|
||||
|
||||
const { status, result_url, fail_reason } = queryData.data || {};
|
||||
|
||||
if (status === "FAILURE") {
|
||||
return { completed: false, error: fail_reason ?? "图片生成失败" };
|
||||
}
|
||||
|
||||
if (status === "SUCCESS") {
|
||||
return { completed: true, url: result_url };
|
||||
}
|
||||
|
||||
return { completed: false };
|
||||
});
|
||||
} catch (error: any) {
|
||||
const msg = u.error(error).message || "图片生成失败";
|
||||
throw new Error(msg);
|
||||
}
|
||||
};
|
||||
|
||||
async function urlToBase64(url: string): Promise<string> {
|
||||
const res = await axios.get(url, { responseType: "arraybuffer" });
|
||||
const base64 = Buffer.from(res.data).toString("base64");
|
||||
const mimeType = res.headers["content-type"] || "image/png";
|
||||
return `data:${mimeType};base64,${base64}`;
|
||||
}
|
||||
@ -6,7 +6,7 @@ export default async (input: ImageConfig, config: AIConfig): Promise<string> =>
|
||||
if (!config.model) throw new Error("缺少Model名称");
|
||||
if (!config.apiKey) throw new Error("缺少API Key");
|
||||
if (!input.prompt) throw new Error("缺少提示词");
|
||||
|
||||
|
||||
const options: any = {};
|
||||
if (config.apiKey) options.apiKey = config.apiKey;
|
||||
if (config?.baseURL) options.baseURL = config.baseURL;
|
||||
|
||||
@ -44,7 +44,7 @@ export default async (input: ImageConfig, config: AIConfig): Promise<string> =>
|
||||
role: "user",
|
||||
content: input.imageBase64.map((i) => ({
|
||||
type: "image",
|
||||
image: i,
|
||||
image: i.replace(/^data:image\/[^;]+;base64,/, ""),
|
||||
})),
|
||||
});
|
||||
} else {
|
||||
@ -111,8 +111,14 @@ export default async (input: ImageConfig, config: AIConfig): Promise<string> =>
|
||||
aspectRatio: input.aspectRatio as "1:1" | "3:4" | "4:3" | "9:16" | "16:9",
|
||||
size: sizeMap[input.size] ?? "1024x1024",
|
||||
});
|
||||
console.log("%c Line:106 🥚 image", "background:#e41a6a", image);
|
||||
|
||||
|
||||
return image.base64;
|
||||
if (image.base64.startsWith("data:image/")) {
|
||||
return image.base64;
|
||||
} else {
|
||||
return `data:image/png;base64,${image.base64}`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ const buildOptions = async (input: AIInput<any>, config: AIConfig = {}) => {
|
||||
}
|
||||
if (!owned) throw new Error("不支持的厂商");
|
||||
|
||||
const modelInstance = owned.instance({ apiKey, baseURL: baseURL!, name: "xixixi" });
|
||||
const modelInstance = owned.instance({ apiKey: apiKey!, baseURL: baseURL! });
|
||||
|
||||
const maxStep = input.maxStep ?? (input.tools ? Object.keys(input.tools).length * 5 : undefined);
|
||||
const outputBuilders: Record<string, (schema: any) => any> = {
|
||||
@ -61,7 +61,7 @@ const buildOptions = async (input: AIInput<any>, config: AIConfig = {}) => {
|
||||
};
|
||||
|
||||
const output = input.output ? (outputBuilders[owned.responseFormat]?.(input.output) ?? null) : null;
|
||||
const chatModelManufacturer = ["volcengine", "other", "openai", "modelScope","grsai"];
|
||||
const chatModelManufacturer = ["volcengine", "other", "openai", "modelScope", "grsai"];
|
||||
const modelFn = chatModelManufacturer.includes(owned.manufacturer) ? (modelInstance as OpenAIProvider).chat(model!) : modelInstance(model!);
|
||||
|
||||
return {
|
||||
@ -86,7 +86,7 @@ const ai = Object.create({}) as {
|
||||
|
||||
ai.invoke = async (input: AIInput<any>, config: AIConfig) => {
|
||||
const options = await buildOptions(input, config);
|
||||
|
||||
|
||||
const result = await generateText(options.config);
|
||||
if (options.responseFormat === "object" && input.output) {
|
||||
const pattern = /{[^{}]*}|{(?:[^{}]*|{[^{}]*})*}/g;
|
||||
|
||||
@ -21,8 +21,7 @@ interface Owned {
|
||||
| typeof createZhipu
|
||||
| typeof createQwen
|
||||
| typeof createGoogleGenerativeAI
|
||||
| typeof createAnthropic
|
||||
| typeof createOpenAICompatible;
|
||||
| typeof createAnthropic;
|
||||
}
|
||||
const instanceMap = {
|
||||
deepSeek: createDeepSeek,
|
||||
@ -35,7 +34,8 @@ const instanceMap = {
|
||||
modelScope: (options: OpenAIProviderSettings) => createOpenAI({ ...options, headers: { ...options?.headers, "X-ModelScope-Async-Mode": "true" } }),
|
||||
xai: createXai,
|
||||
other: createOpenAI,
|
||||
grsai:createOpenAI
|
||||
grsai: createOpenAI,
|
||||
formal: createOpenAI,
|
||||
};
|
||||
const modelList: Owned[] = [
|
||||
// DeepSeek
|
||||
|
||||
@ -12,6 +12,8 @@ import gemini from "./owned/gemini";
|
||||
import apimart from "./owned/apimart";
|
||||
import other from "./owned/other";
|
||||
import grsai from "./owned/grsai";
|
||||
import formal from "./owned/formal";
|
||||
|
||||
const modelInstance = {
|
||||
volcengine: volcengine,
|
||||
kling: kling,
|
||||
@ -22,6 +24,7 @@ const modelInstance = {
|
||||
apimart: apimart,
|
||||
other: other,
|
||||
grsai: grsai,
|
||||
formal: formal,
|
||||
} as const;
|
||||
|
||||
export default async (input: VideoConfig, config?: AIConfig) => {
|
||||
@ -33,15 +36,15 @@ export default async (input: VideoConfig, config?: AIConfig) => {
|
||||
// const owned = modelList.find((m) => m.model === model);
|
||||
// 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,
|
||||
});
|
||||
// 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 内容类型字符串
|
||||
if (input.imageBase64 && input.imageBase64.length > 0) {
|
||||
input.imageBase64 = input.imageBase64.map((img) => {
|
||||
@ -71,15 +74,15 @@ export default async (input: VideoConfig, config?: AIConfig) => {
|
||||
try {
|
||||
const response = await axios.get(videoUrl, { responseType: "stream" });
|
||||
await u.oss.writeFile(input.savePath, response.data);
|
||||
await u.db("t_myTasks").where("id", taskId).update({
|
||||
state: "已完成",
|
||||
});
|
||||
// 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,
|
||||
});
|
||||
// await u.db("t_myTasks").where("id", taskId).update({
|
||||
// state: "生成失败",
|
||||
// reason: err.message,
|
||||
// });
|
||||
return videoUrl;
|
||||
}
|
||||
}
|
||||
|
||||
120
src/utils/ai/video/owned/formal.ts
Normal file
120
src/utils/ai/video/owned/formal.ts
Normal file
@ -0,0 +1,120 @@
|
||||
import "../type";
|
||||
import { generateImage, generateText, ModelMessage } from "ai";
|
||||
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
||||
import { pollTask } from "@/utils/ai/utils";
|
||||
import u from "@/utils";
|
||||
import axios from "axios";
|
||||
function getApiUrl(apiUrl: string) {
|
||||
if (apiUrl.includes("|")) {
|
||||
const parts = apiUrl.split("|");
|
||||
if (parts.length !== 2 || !parts[0].trim() || !parts[1].trim()) {
|
||||
throw new Error("url 格式错误,请使用 url1|url2 格式");
|
||||
}
|
||||
return { requestUrl: parts[0].trim(), queryUrl: parts[1].trim() };
|
||||
}
|
||||
throw new Error("请填写正确的url");
|
||||
}
|
||||
function template(replaceObj: Record<string, any>, url: string) {
|
||||
return url.replace(/\{(\w+)\}/g, (match, varName) => {
|
||||
return replaceObj.hasOwnProperty(varName) ? replaceObj[varName] : match;
|
||||
});
|
||||
}
|
||||
export default async (input: VideoConfig, config: AIConfig): Promise<string> => {
|
||||
if (!config.model) throw new Error("缺少Model名称");
|
||||
if (!config.apiKey) throw new Error("缺少API Key");
|
||||
|
||||
const defaultBaseURL = "http://192.168.0.74:3000/videogenerator/generate|http://192.168.0.74:3000/videogenerator/generate/{id}";
|
||||
const { requestUrl, queryUrl } = getApiUrl(config.baseURL! ?? defaultBaseURL);
|
||||
// 根据 size 配置映射到具体尺寸
|
||||
const sizeMap: Record<string, Record<string, string>> = {
|
||||
"480P": {
|
||||
"16:9": "832*480",
|
||||
"9:16": "480*332",
|
||||
},
|
||||
"720P": {
|
||||
"16:9": "1280*720",
|
||||
"9:16": "720*1280",
|
||||
},
|
||||
"1080P": {
|
||||
"16:9": "1920*1080",
|
||||
"9:16": "1080*1920",
|
||||
},
|
||||
};
|
||||
// 构建完整的提示词
|
||||
let mergedImage = input.imageBase64;
|
||||
if (mergedImage && mergedImage.length) {
|
||||
const smallImage = await u.imageTools.mergeImages(mergedImage, "5mb");
|
||||
mergedImage = [smallImage];
|
||||
}
|
||||
|
||||
const size = sizeMap[input.resolution]?.[input.aspectRatio] ?? "1280*720";
|
||||
const imageCount: { type: string; image_url: string }[] = [];
|
||||
if (input.imageBase64 && input.imageBase64.length) {
|
||||
input.imageBase64.forEach((i, index) => {
|
||||
imageCount.push({
|
||||
type: "image_url",
|
||||
image_url: { url: i },
|
||||
role: index === 0 ? "first_frame" : "last_frame",
|
||||
});
|
||||
});
|
||||
}
|
||||
const taskBody: Record<string, any> = {
|
||||
model: config.model,
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: input.prompt,
|
||||
},
|
||||
...imageCount,
|
||||
],
|
||||
// parameters: {
|
||||
// aspect_ratio: input.aspectRatio,
|
||||
// size: input.resolution,
|
||||
// duration: input.duration,
|
||||
// },
|
||||
// ...(typeof input.audio === "boolean" ? { generate_audio: input.audio } : {}),
|
||||
};
|
||||
console.log("%c Line:62 🥑 taskBody", "background:#ea7e5c", taskBody);
|
||||
|
||||
const apiKey = config.apiKey.replace("Bearer ", "");
|
||||
try {
|
||||
const { data } = await axios.post(requestUrl, taskBody, { headers: { Authorization: `Bearer ${apiKey}` } });
|
||||
console.log("%c Line:70 🥪 data", "background:#ed9ec7", data);
|
||||
console.log("%c Line:84 🍐 data.code != uccess", "background:#e41a6a", data.code != "success");
|
||||
console.log("%c Line:83 🍇 data.code", "background:#b03734", data.code);
|
||||
|
||||
if (data.code != "success") throw new Error(`任务提交失败: ${data || "未知错误"}`);
|
||||
const taskId = data.data;
|
||||
|
||||
return await pollTask(async () => {
|
||||
const { data: queryData } = await axios.get(template({ id: taskId }, queryUrl), {
|
||||
headers: { Authorization: `Bearer ${apiKey}` },
|
||||
});
|
||||
console.log("%c Line:77 🍧 data", "background:#f5ce50", queryData);
|
||||
|
||||
const { status, result_url, fail_reason } = queryData.data || {};
|
||||
|
||||
if (status === "FAILURE") {
|
||||
return { completed: false, error: fail_reason ? fail_reason : "视频生成失败" };
|
||||
}
|
||||
|
||||
if (status === "SUCCESS") {
|
||||
return { completed: true, url: result_url };
|
||||
}
|
||||
|
||||
return { completed: false };
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.log("%c Line:105 🍖 error", "background:#ed9ec7", error);
|
||||
const msg = u.error(error).message || "图片生成失败";
|
||||
console.log("%c Line:107 🌽 u.error(error)", "background:#ea7e5c", u.error(error));
|
||||
throw new Error(msg);
|
||||
}
|
||||
};
|
||||
|
||||
async function urlToBase64(url: string): Promise<string> {
|
||||
const res = await axios.get(url, { responseType: "arraybuffer" });
|
||||
const base64 = Buffer.from(res.data).toString("base64");
|
||||
const mimeType = res.headers["content-type"] || "image/png";
|
||||
return `data:${mimeType};base64,${base64}`;
|
||||
}
|
||||
@ -2,58 +2,145 @@ import "../type";
|
||||
import axios from "axios";
|
||||
import sharp from "sharp";
|
||||
import FormData from "form-data";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import u from "@/utils";
|
||||
|
||||
import { pollTask, validateVideoConfig } from "@/utils/ai/utils";
|
||||
import { createOpenAI } from "@ai-sdk/openai";
|
||||
import { experimental_generateVideo as generateVideo } from "ai";
|
||||
function template(replaceObj: Record<string, any>, url: string) {
|
||||
return url.replace(/\{(\w+)\}/g, (match, varName) => {
|
||||
return replaceObj.hasOwnProperty(varName) ? replaceObj[varName] : match;
|
||||
});
|
||||
}
|
||||
export default async (input: VideoConfig, config: AIConfig) => {
|
||||
if (!config.apiKey) throw new Error("缺少API Key");
|
||||
if (!config.baseURL) throw new Error("缺少baseURL");
|
||||
// const { owned, images, hasTextType } = validateVideoConfig(input, config);
|
||||
const [requestUrl, queryUrl] = config.baseURL.split("|");
|
||||
|
||||
const authorization = `Bearer ${config.apiKey}`;
|
||||
const urls = config.baseURL.split("|");
|
||||
const isThreeUrlMode = urls.length === 3;
|
||||
console.log("%c Line:24 🌭 isThreeUrlMode", "background:#ed9ec7", isThreeUrlMode);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("model", config.model);
|
||||
formData.append("prompt", input.prompt);
|
||||
formData.append("seconds", String(input.duration));
|
||||
let requestUrl: string, queryUrl: string, downLoadUrl: string | undefined;
|
||||
|
||||
if (isThreeUrlMode) {
|
||||
[requestUrl, queryUrl, downLoadUrl] = urls;
|
||||
} else {
|
||||
[requestUrl, queryUrl] = urls;
|
||||
}
|
||||
|
||||
// 根据 aspectRatio 设置 size
|
||||
const sizeMap: Record<string, string> = {
|
||||
"16:9": "1280x720",
|
||||
"9:16": "720x1280",
|
||||
};
|
||||
formData.append("size", sizeMap[input.aspectRatio] || "1920x1080");
|
||||
let resData;
|
||||
let taskId = "";
|
||||
if (isThreeUrlMode) {
|
||||
// 三个地址:使用 FormData 方式
|
||||
const formData = new FormData();
|
||||
formData.append("model", config.model);
|
||||
formData.append("prompt", input.prompt);
|
||||
formData.append("seconds", String(input.duration));
|
||||
|
||||
if (input.imageBase64 && input.imageBase64.length) {
|
||||
const base64Data = input.imageBase64[0]!.replace(/^data:image\/\w+;base64,/, "");
|
||||
const buffer = Buffer.from(base64Data, "base64");
|
||||
formData.append("input_reference", buffer, { filename: "image.jpg", contentType: "image/jpeg" });
|
||||
}
|
||||
const size = sizeMap[input.aspectRatio] || "1280x720";
|
||||
formData.append("size", size);
|
||||
|
||||
const body = {
|
||||
model: config.model,
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: input.prompt,
|
||||
},
|
||||
],
|
||||
if (input.imageBase64 && input.imageBase64.length) {
|
||||
const base64Data = input.imageBase64[0]!.replace(/^data:image\/\w+;base64,/, "");
|
||||
const buffer = Buffer.from(base64Data, "base64");
|
||||
|
||||
// 解析尺寸
|
||||
const [width, height] = size.split("x").map(Number);
|
||||
|
||||
// 使用 sharp 调整图片尺寸
|
||||
const resizedBuffer = await sharp(buffer).resize(width, height, { fit: "cover" }).jpeg({ quality: 90 }).toBuffer();
|
||||
|
||||
formData.append("input_reference", resizedBuffer, { filename: "image.jpg", contentType: "image/jpeg" });
|
||||
}
|
||||
|
||||
const response = await axios.post(requestUrl, formData, {
|
||||
headers: { Authorization: authorization, ...formData.getHeaders() },
|
||||
});
|
||||
|
||||
taskId = response.data?.task_id || response.data?.id;
|
||||
resData = response.data;
|
||||
} else {
|
||||
// 两个地址:使用 JSON 方式
|
||||
|
||||
const requestBody: any = {
|
||||
model: config.model,
|
||||
prompt: input.prompt,
|
||||
aspect_ratio: input.aspectRatio || "16:9",
|
||||
size: "720p",
|
||||
};
|
||||
|
||||
if (input.imageBase64 && input.imageBase64.length) {
|
||||
requestBody.images = input.imageBase64;
|
||||
}
|
||||
|
||||
const response = await axios.post(requestUrl, JSON.stringify(requestBody), {
|
||||
headers: {
|
||||
Authorization: authorization,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
],
|
||||
};
|
||||
const { data } = await axios.post(
|
||||
config.baseURL,
|
||||
{ ...body },
|
||||
{
|
||||
headers: { "Content-Type": "application/json", Authorization: authorization },
|
||||
},
|
||||
);
|
||||
});
|
||||
taskId = response.data.id;
|
||||
resData = response.data;
|
||||
}
|
||||
console.log("%c Line:87 🥒 taskId", "background:#f5ce50", taskId);
|
||||
|
||||
console.log("%c Line:49 🥓 data", "background:#ffdd4d", data);
|
||||
if (!taskId) throw new Error(`任务提交失败: ${resData ? JSON.stringify(resData) : "未知错误"}`);
|
||||
|
||||
if (data.status === "FAILED") throw new Error(`任务提交失败: ${data.errorMessage || "未知错误"}`);
|
||||
return await pollTask(async () => {
|
||||
// 构建查询URL,两个地址模式时使用URL参数
|
||||
const finalQueryUrl = isThreeUrlMode ? template({ id: taskId }, queryUrl) : `${queryUrl}?id=${taskId}`;
|
||||
|
||||
const { data: queryData } = await axios.get(finalQueryUrl, {
|
||||
headers: { Authorization: authorization },
|
||||
});
|
||||
console.log("%c Line:100 🥑 queryData", "background:#42b983", queryData);
|
||||
|
||||
if (queryData.status === "completed") {
|
||||
// 下载视频,带重试机制
|
||||
let videoRes;
|
||||
let retries = 3;
|
||||
let lastError;
|
||||
|
||||
for (let i = 0; i < retries; i++) {
|
||||
try {
|
||||
// 构建下载URL
|
||||
const finalDownloadUrl = isThreeUrlMode && downLoadUrl ? template({ id: taskId }, downLoadUrl) : queryData.video_url || queryData.url; // 从响应中获取视频URL
|
||||
|
||||
videoRes = await axios.get(finalDownloadUrl, {
|
||||
headers: isThreeUrlMode ? { Authorization: authorization } : {},
|
||||
responseType: "arraybuffer",
|
||||
timeout: 60 * 1000 * 10, // 60秒超时
|
||||
});
|
||||
break; // 成功则跳出循环
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
console.error(`视频下载失败,第 ${i + 1}/${retries} 次尝试:`, error);
|
||||
if (i < retries - 1) {
|
||||
// 等待后重试,使用指数退避
|
||||
await new Promise((resolve) => setTimeout(resolve, Math.pow(2, i) * 1000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!videoRes) {
|
||||
throw new Error(`视频下载失败,已重试 ${retries} 次: ${lastError}`);
|
||||
}
|
||||
|
||||
// 将视频buffer转换为base64或直接返回buffer
|
||||
const savePath = input.savePath.endsWith(".mp4") ? input.savePath : path.join(input.savePath, `other_${Date.now()}.mp4`);
|
||||
await u.oss.writeFile(input.savePath, videoRes.data);
|
||||
|
||||
return { completed: true, url: savePath };
|
||||
}
|
||||
if (queryData.status === "failed") return { completed: false, error: `任务失败: ${queryData.error || "未知错误"}` };
|
||||
// if (queryData.status === "QUEUED" || queryData.status === "RUNNING") return { completed: false };
|
||||
return { completed: false };
|
||||
});
|
||||
};
|
||||
|
||||
1
src/utils/ai/video/owned/tempCodeRunnerFile.ts
Normal file
1
src/utils/ai/video/owned/tempCodeRunnerFile.ts
Normal file
@ -0,0 +1 @@
|
||||
resizedBuffer
|
||||
@ -67,6 +67,9 @@ export default async (input: VideoConfig, config: AIConfig) => {
|
||||
Authorization: authorization,
|
||||
},
|
||||
});
|
||||
console.log("%c Line:65 🍢 response", "background:#3f7cff", response);
|
||||
|
||||
|
||||
taskId = response.data.task_id;
|
||||
} else {
|
||||
// 图生视频
|
||||
@ -89,6 +92,8 @@ export default async (input: VideoConfig, config: AIConfig) => {
|
||||
Authorization: authorization,
|
||||
},
|
||||
});
|
||||
console.log("%c Line:90 🍷 response", "background:#2eafb0", response.data);
|
||||
|
||||
taskId = response.data.task_id;
|
||||
}
|
||||
|
||||
@ -103,6 +108,7 @@ export default async (input: VideoConfig, config: AIConfig) => {
|
||||
task_ids: [taskId],
|
||||
},
|
||||
});
|
||||
console.log("%c Line:113 🧀 response.data", "background:#33a5ff", response.data);
|
||||
|
||||
const tasks = response.data.tasks;
|
||||
if (!tasks || tasks.length === 0) {
|
||||
|
||||
@ -46,6 +46,7 @@ export default async (input: VideoConfig, config: AIConfig) => {
|
||||
Authorization: authorization,
|
||||
},
|
||||
});
|
||||
console.log("%c Line:44 🍡 createResponse", "background:#2eafb0", createResponse);
|
||||
|
||||
const taskId = createResponse.data.id;
|
||||
|
||||
|
||||
@ -66,6 +66,9 @@ class OSS {
|
||||
* @throws 路径不在 OSS 根目录内、文件不存在等错误
|
||||
*/
|
||||
async getFile(userRelPath: string): Promise<Buffer> {
|
||||
console.log("%c Line:69 🥔 userRelPath", "background:#ffdd4d", userRelPath);
|
||||
console.log("%c Line:72 🥥 this.rootDir", "background:#ea7e5c", this.rootDir);
|
||||
|
||||
await this.ensureInit();
|
||||
return fs.readFile(resolveSafeLocalPath(userRelPath, this.rootDir));
|
||||
}
|
||||
|
||||
136
yarn.lock
136
yarn.lock
@ -8,20 +8,20 @@
|
||||
integrity sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==
|
||||
|
||||
"@ai-sdk/anthropic@^3.0.35":
|
||||
version "3.0.50"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/anthropic/-/anthropic-3.0.50.tgz#5ffdb638ae5418a2bf53d97448346af7ab77e09a"
|
||||
integrity sha512-BkCUgGTp/iZJuuFBF1wv7GGnrEJg7X7hqbaa+/t4HTBt9dZn3e6NFn5NhPUvo2p5SreUeHEl0As0r2uaVn3K9Q==
|
||||
version "3.0.58"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/anthropic/-/anthropic-3.0.58.tgz#de49aa3cb7e8a0115eb9d42da05f108d23a90822"
|
||||
integrity sha512-/53SACgmVukO4bkms4dpxpRlYhW8Ct6QZRe6sj1Pi5H00hYhxIrqfiLbZBGxkdRvjsBQeP/4TVGsXgH5rQeb8Q==
|
||||
dependencies:
|
||||
"@ai-sdk/provider" "3.0.8"
|
||||
"@ai-sdk/provider-utils" "4.0.16"
|
||||
"@ai-sdk/provider-utils" "4.0.19"
|
||||
|
||||
"@ai-sdk/deepseek@^2.0.17":
|
||||
version "2.0.21"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/deepseek/-/deepseek-2.0.21.tgz#7a08cb59e25bf5799c3a0461c6f6061a60d22f2e"
|
||||
integrity sha512-swIljtTiEBt5fTmnHftb20MnM06eBEANJzEYAUvU1m3yQH+HcduHxwVMLUtf9M7RqpTrBrAJxLtHHP5kPIVSCQ==
|
||||
version "2.0.24"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/deepseek/-/deepseek-2.0.24.tgz#c2e8aa1af5b7e4c7c21b355408ee58f659581163"
|
||||
integrity sha512-4vOEekW4TAYVHN0qgiwoUOQZhguGwZBiEw8LDeUmpWBm07QkLRAtxYCaSoMiA4hZZojao5mj6NRGEBW1CnDPtg==
|
||||
dependencies:
|
||||
"@ai-sdk/provider" "3.0.8"
|
||||
"@ai-sdk/provider-utils" "4.0.16"
|
||||
"@ai-sdk/provider-utils" "4.0.19"
|
||||
|
||||
"@ai-sdk/devtools@^0.0.11":
|
||||
version "0.0.11"
|
||||
@ -32,52 +32,52 @@
|
||||
"@hono/node-server" "^1.13.7"
|
||||
hono "^4.6.14"
|
||||
|
||||
"@ai-sdk/gateway@3.0.59":
|
||||
version "3.0.59"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/gateway/-/gateway-3.0.59.tgz#1ce7933878656a74f132eb6230caaf22786fd5d3"
|
||||
integrity sha512-MbtheWHgEFV/8HL1Z6E3hOAsmP73zZlNFg0F0nJAD0Adnjp4J/plqNK00Y896d+dWTw+r0OXzyov9/2wCFjH0Q==
|
||||
"@ai-sdk/gateway@3.0.66":
|
||||
version "3.0.66"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/gateway/-/gateway-3.0.66.tgz#64ad8f7b45acaa4c93c53be2bb39e772e49e31b5"
|
||||
integrity sha512-SIQ0YY0iMuv+07HLsZ+bB990zUJ6S4ujORAh+Jv1V2KGNn73qQKnGO0JBk+w+Res8YqOFSycwDoWcFlQrVxS4A==
|
||||
dependencies:
|
||||
"@ai-sdk/provider" "3.0.8"
|
||||
"@ai-sdk/provider-utils" "4.0.16"
|
||||
"@ai-sdk/provider-utils" "4.0.19"
|
||||
"@vercel/oidc" "3.1.0"
|
||||
|
||||
"@ai-sdk/google@^3.0.20":
|
||||
version "3.0.34"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/google/-/google-3.0.34.tgz#5e32b761c9434a0df1046fa8be1c0ffe48f29eac"
|
||||
integrity sha512-1tXUr1W5YACXPgtHYWIU3raqMsayp6cMI8NUT4EEzzZSpvHzkkiNWHEr+bGxEGurSUukfo+pE1RKpLwBFOZtJg==
|
||||
"@ai-sdk/google@^3.0.43":
|
||||
version "3.0.43"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/google/-/google-3.0.43.tgz#e955d8cb8a598bc75d5aa39d4eaf1cc580dc1ac8"
|
||||
integrity sha512-NGCgP5g8HBxrNdxvF8Dhww+UKfqAkZAmyYBvbu9YLoBkzAmGKDBGhVptN/oXPB5Vm0jggMdoLycZ8JReQM8Zqg==
|
||||
dependencies:
|
||||
"@ai-sdk/provider" "3.0.8"
|
||||
"@ai-sdk/provider-utils" "4.0.16"
|
||||
"@ai-sdk/provider-utils" "4.0.19"
|
||||
|
||||
"@ai-sdk/openai-compatible@2.0.31", "@ai-sdk/openai-compatible@^2.0.27":
|
||||
version "2.0.31"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/openai-compatible/-/openai-compatible-2.0.31.tgz#11aca181c215049b1c79b86cf7d58dcf68170da9"
|
||||
integrity sha512-e78xiImcTe2aCMQoFbVJluQmUV4XgahOmmehAuRPlcwzRv2KtkvuLCXPC9Xcy2u83e8SimVva9k9G8SvZcnaBA==
|
||||
"@ai-sdk/openai-compatible@2.0.35", "@ai-sdk/openai-compatible@^2.0.27":
|
||||
version "2.0.35"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/openai-compatible/-/openai-compatible-2.0.35.tgz#ab1edce39a255b1456efdf8e9a8fd4c5566c82fb"
|
||||
integrity sha512-g3wA57IAQFb+3j4YuFndgkUdXyRETZVvbfAWM+UX7bZSxA3xjes0v3XKgIdKdekPtDGsh4ZX2byHD0gJIMPfiA==
|
||||
dependencies:
|
||||
"@ai-sdk/provider" "3.0.8"
|
||||
"@ai-sdk/provider-utils" "4.0.16"
|
||||
"@ai-sdk/provider-utils" "4.0.19"
|
||||
|
||||
"@ai-sdk/openai@^3.0.25":
|
||||
version "3.0.37"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/openai/-/openai-3.0.37.tgz#8f5361eba21848b37663cbe113c91c666fe9ed58"
|
||||
integrity sha512-bcYjT3/58i/C0DN3AnrjiGsAb0kYivZLWWUtgTjsBurHSht/LTEy+w3dw5XQe3FmZwX7Z/mUQCiA3wB/5Kf7ow==
|
||||
version "3.0.41"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/openai/-/openai-3.0.41.tgz#22f559888cd4f9bb312c5c576441c3412f442e7b"
|
||||
integrity sha512-IZ42A+FO+vuEQCVNqlnAPYQnnUpUfdJIwn1BEDOBywiEHa23fw7PahxVtlX9zm3/zMvTW4JKPzWyvAgDu+SQ2A==
|
||||
dependencies:
|
||||
"@ai-sdk/provider" "3.0.8"
|
||||
"@ai-sdk/provider-utils" "4.0.16"
|
||||
"@ai-sdk/provider-utils" "4.0.19"
|
||||
|
||||
"@ai-sdk/provider-utils@4.0.16", "@ai-sdk/provider-utils@^4.0.0":
|
||||
version "4.0.16"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/provider-utils/-/provider-utils-4.0.16.tgz#24bb427d5ed023ef245f3a7af0e83590c45a74b5"
|
||||
integrity sha512-kBvDqNkt5EwlzF9FujmNhhtl8FYg3e8FO8P5uneKliqfRThWemzBj+wfYr7ZCymAQhTRnwSSz1/SOqhOAwmx9g==
|
||||
"@ai-sdk/provider-utils@4.0.19", "@ai-sdk/provider-utils@^4.0.0":
|
||||
version "4.0.19"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/provider-utils/-/provider-utils-4.0.19.tgz#535f87c34f19d5584068c522005780ba59123093"
|
||||
integrity sha512-3eG55CrSWCu2SXlqq2QCsFjo3+E7+Gmg7i/oRVoSZzIodTuDSfLb3MRje67xE9RFea73Zao7Lm4mADIfUETKGg==
|
||||
dependencies:
|
||||
"@ai-sdk/provider" "3.0.8"
|
||||
"@standard-schema/spec" "^1.1.0"
|
||||
eventsource-parser "^3.0.6"
|
||||
|
||||
"@ai-sdk/provider-utils@^3.0.0":
|
||||
version "3.0.21"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/provider-utils/-/provider-utils-3.0.21.tgz#b98175079d2787f0dda7027d74482f4ae1acfbc8"
|
||||
integrity sha512-veuMwTLxsgh31Jjn0SnBABnM1f7ebHhRWcV2ZuY3hP3iJDCZ8VXBaYqcHXoOQDqUXTCas08sKQcHyWK+zl882Q==
|
||||
version "3.0.22"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/provider-utils/-/provider-utils-3.0.22.tgz#fc9824f5a5c290a95c14888de130b02e52020060"
|
||||
integrity sha512-fFT1KfUUKktfAFm5mClJhS1oux9tP2qgzmEZVl5UdwltQ1LO/s8hd7znVrgKzivwv1s1FIPza0s9OpJaNB/vHw==
|
||||
dependencies:
|
||||
"@ai-sdk/provider" "2.0.1"
|
||||
"@standard-schema/spec" "^1.0.0"
|
||||
@ -105,13 +105,13 @@
|
||||
json-schema "^0.4.0"
|
||||
|
||||
"@ai-sdk/xai@^3.0.47":
|
||||
version "3.0.60"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/xai/-/xai-3.0.60.tgz#9dd4f427121fb1fa63e531c0beda43a3669758eb"
|
||||
integrity sha512-nDOUyzeepmyyoL5+9LxmwXy3BoX9mZy7cv3BjHPN4Xc+SVFVqL7uj/9m1oLRCNmpwfA/9QBq9kuD+J31EfdhMw==
|
||||
version "3.0.67"
|
||||
resolved "https://registry.npmmirror.com/@ai-sdk/xai/-/xai-3.0.67.tgz#b49f5c171c6515e38e3cbfafdff746054892c0b0"
|
||||
integrity sha512-KQQIDc91dUA5IGFMnXBuvPBeraYNTdpDC1qUS+JG8vE+/299//5sZFafI1kKYUu3f3p7LaZrKXYgZ1Ni7QIRbw==
|
||||
dependencies:
|
||||
"@ai-sdk/openai-compatible" "2.0.31"
|
||||
"@ai-sdk/openai-compatible" "2.0.35"
|
||||
"@ai-sdk/provider" "3.0.8"
|
||||
"@ai-sdk/provider-utils" "4.0.16"
|
||||
"@ai-sdk/provider-utils" "4.0.19"
|
||||
|
||||
"@develar/schema-utils@~2.6.5":
|
||||
version "2.6.5"
|
||||
@ -370,9 +370,9 @@
|
||||
integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
|
||||
|
||||
"@hono/node-server@^1.13.7":
|
||||
version "1.19.9"
|
||||
resolved "https://registry.npmmirror.com/@hono/node-server/-/node-server-1.19.9.tgz#8f37119b1acf283fd3f6035f3d1356fdb97a09ac"
|
||||
integrity sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==
|
||||
version "1.19.11"
|
||||
resolved "https://registry.npmmirror.com/@hono/node-server/-/node-server-1.19.11.tgz#dc419f0826dd2504e9fc86ad289d5636a0444e2f"
|
||||
integrity sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g==
|
||||
|
||||
"@img/colour@^1.0.0":
|
||||
version "1.1.0"
|
||||
@ -774,16 +774,16 @@
|
||||
integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==
|
||||
|
||||
"@types/node@*":
|
||||
version "25.3.3"
|
||||
resolved "https://registry.npmmirror.com/@types/node/-/node-25.3.3.tgz#605862544ee7ffd7a936bcbf0135a14012f1e549"
|
||||
integrity sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==
|
||||
version "25.3.5"
|
||||
resolved "https://registry.npmmirror.com/@types/node/-/node-25.3.5.tgz#beccb5915561f7a9970ace547ad44d6cdbf39b46"
|
||||
integrity sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==
|
||||
dependencies:
|
||||
undici-types "~7.18.0"
|
||||
|
||||
"@types/node@^24.9.0":
|
||||
version "24.11.0"
|
||||
resolved "https://registry.npmmirror.com/@types/node/-/node-24.11.0.tgz#34e8f9603ada03fdc36a532faefdb8e1bb3693a0"
|
||||
integrity sha512-fPxQqz4VTgPI/IQ+lj9r0h+fDR66bzoeMGHp8ASee+32OSGIkeASsoZuJixsQoVef1QJbeubcPBxKk22QVoWdw==
|
||||
version "24.11.2"
|
||||
resolved "https://registry.npmmirror.com/@types/node/-/node-24.11.2.tgz#4d16d5f21256a0506c9d7b58fcda1d4d3dadc530"
|
||||
integrity sha512-HTsxyfkxTNxOXBsEdgIOzbMgBjDGPvkTfw0B1m09j1LFPk8u3tSL8SNBRTSc381wXXX/Wp93qPi1kQXwnWuHgA==
|
||||
dependencies:
|
||||
undici-types "~7.16.0"
|
||||
|
||||
@ -801,9 +801,9 @@
|
||||
integrity sha512-JOqsl+ZoCpP4e8TDke9W79FDcSgPAR0l6pixx2JHkhnRjvShyYiAYw2LVsnA7K08Y6DeOnaU6ujmENO4os/cYg==
|
||||
|
||||
"@types/qs@*":
|
||||
version "6.14.0"
|
||||
resolved "https://registry.npmmirror.com/@types/qs/-/qs-6.14.0.tgz#d8b60cecf62f2db0fb68e5e006077b9178b85de5"
|
||||
integrity sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==
|
||||
version "6.15.0"
|
||||
resolved "https://registry.npmmirror.com/@types/qs/-/qs-6.15.0.tgz#963ab61779843fe910639a50661b48f162bc7f79"
|
||||
integrity sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==
|
||||
|
||||
"@types/range-parser@*":
|
||||
version "1.2.7"
|
||||
@ -907,13 +907,13 @@ aggregate-error@^3.0.0:
|
||||
indent-string "^4.0.0"
|
||||
|
||||
ai@^6.0.67:
|
||||
version "6.0.105"
|
||||
resolved "https://registry.npmmirror.com/ai/-/ai-6.0.105.tgz#85c38f7d67de571435f480cb5c49201a7207599e"
|
||||
integrity sha512-rp+exWtZS3J0DDvZIfetpKCIg7D3cCsvBPoFN3I67IDTs9aoBZDbpecoIkmNLT+U9RBkoEial3OGHRvme23HCw==
|
||||
version "6.0.116"
|
||||
resolved "https://registry.npmmirror.com/ai/-/ai-6.0.116.tgz#dc1c3d929453e165fcd3f188d8663617ecf94129"
|
||||
integrity sha512-7yM+cTmyRLeNIXwt4Vj+mrrJgVQ9RMIW5WO0ydoLoYkewIvsMcvUmqS4j2RJTUXaF1HphwmSKUMQ/HypNRGOmA==
|
||||
dependencies:
|
||||
"@ai-sdk/gateway" "3.0.59"
|
||||
"@ai-sdk/gateway" "3.0.66"
|
||||
"@ai-sdk/provider" "3.0.8"
|
||||
"@ai-sdk/provider-utils" "4.0.16"
|
||||
"@ai-sdk/provider-utils" "4.0.19"
|
||||
"@opentelemetry/api" "1.9.0"
|
||||
|
||||
ajv-keywords@^3.4.1:
|
||||
@ -1796,9 +1796,9 @@ electron-publish@26.8.1:
|
||||
mime "^2.5.2"
|
||||
|
||||
electron@^40.0.0:
|
||||
version "40.6.1"
|
||||
resolved "https://registry.npmmirror.com/electron/-/electron-40.6.1.tgz#f7dca0c028a13144abe2192ec2b6a75ef7418dfc"
|
||||
integrity sha512-u9YfoixttdauciHV9Ut9Zf3YipJoU093kR1GSYTTXTAXqhiXI0G1A0NnL/f0O2m2UULCXaXMf2W71PloR6V9pQ==
|
||||
version "40.8.0"
|
||||
resolved "https://registry.npmmirror.com/electron/-/electron-40.8.0.tgz#d149210300bf7df95e5d3db4a40d388e12ef7549"
|
||||
integrity sha512-WoPq0Nr9Yx3g7T6VnJXdwa/rr2+VRyH3a+K+ezfMKBlf6WjxE/LmhMQabKbb6yjm9RbZhJBRcYyoLph421O2mQ==
|
||||
dependencies:
|
||||
"@electron/get" "^2.0.0"
|
||||
"@types/node" "^24.9.0"
|
||||
@ -2139,9 +2139,9 @@ fs-extra@^10.0.0, fs-extra@^10.1.0:
|
||||
universalify "^2.0.0"
|
||||
|
||||
fs-extra@^11.1.1:
|
||||
version "11.3.3"
|
||||
resolved "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.3.tgz#a27da23b72524e81ac6c3815cc0179b8c74c59ee"
|
||||
integrity sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==
|
||||
version "11.3.4"
|
||||
resolved "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.4.tgz#ab6934eca8bcf6f7f6b82742e33591f86301d6fc"
|
||||
integrity sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.0"
|
||||
jsonfile "^6.0.1"
|
||||
@ -2399,9 +2399,9 @@ hasown@^2.0.2:
|
||||
function-bind "^1.1.2"
|
||||
|
||||
hono@^4.6.14:
|
||||
version "4.12.3"
|
||||
resolved "https://registry.npmmirror.com/hono/-/hono-4.12.3.tgz#fd8dd1127c30956a9d58c1b0c4535d21c1ef3e16"
|
||||
integrity sha512-SFsVSjp8sj5UumXOOFlkZOG6XS9SJDKw0TbwFeV+AJ8xlST8kxK5Z/5EYa111UY8732lK2S/xB653ceuaoGwpg==
|
||||
version "4.12.5"
|
||||
resolved "https://registry.npmmirror.com/hono/-/hono-4.12.5.tgz#8c16209b35040025d3f110d18f3b821de6cab00f"
|
||||
integrity sha512-3qq+FUBtlTHhtYxbxheZgY8NIFnkkC/MR8u5TTsr7YZ3wixryQ3cCwn3iZbg8p8B88iDBBAYSfZDS75t8MN7Vg==
|
||||
|
||||
hosted-git-info@^2.1.4:
|
||||
version "2.8.9"
|
||||
@ -4324,9 +4324,9 @@ tar@^6.0.2, tar@^6.1.11, tar@^6.1.2:
|
||||
yallist "^4.0.0"
|
||||
|
||||
tar@^7.4.3, tar@^7.5.6, tar@^7.5.7:
|
||||
version "7.5.9"
|
||||
resolved "https://registry.npmmirror.com/tar/-/tar-7.5.9.tgz#817ac12a54bc4362c51340875b8985d7dc9724b8"
|
||||
integrity sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg==
|
||||
version "7.5.10"
|
||||
resolved "https://registry.npmmirror.com/tar/-/tar-7.5.10.tgz#2281541123f5507db38bc6eb22619f4bbaef73ad"
|
||||
integrity sha512-8mOPs1//5q/rlkNSPcCegA6hiHJYDmSLEI8aMH/CdSQJNWztHC9WHNam5zdQlfpTwB9Xp7IBEsHfV5LKMJGVAw==
|
||||
dependencies:
|
||||
"@isaacs/fs-minipass" "^4.0.0"
|
||||
chownr "^3.0.0"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user