diff --git a/package-lock.json b/package-lock.json index 52d311f..c6a2ea1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "laitool", - "version": "3.2.3", + "version": "3.2.4", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/package.json b/package.json index ce4ddcd..02c8e6c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "laitool", - "version": "3.2.3", + "version": "3.2.4", "description": "An AI tool for image processing, video processing, and other functions.", "main": "./out/main/index.js", "author": "laitool.cn", @@ -92,8 +92,13 @@ "resources/tmp/**", "resources/icon.ico" ], + "nsis": { + "oneClick": false, + "allowToChangeInstallationDirectory": true + }, "win": { + "target": "nsis", "icon": "./resources/icon.ico" } } -} +} \ No newline at end of file diff --git a/resources/scripts/db/book.realm.lock b/resources/scripts/db/book.realm.lock index 6b06983..8d08189 100644 Binary files a/resources/scripts/db/book.realm.lock and b/resources/scripts/db/book.realm.lock differ diff --git a/resources/scripts/db/software.realm b/resources/scripts/db/software.realm index 38e7fb1..205f13d 100644 Binary files a/resources/scripts/db/software.realm and b/resources/scripts/db/software.realm differ diff --git a/resources/scripts/db/software.realm.lock b/resources/scripts/db/software.realm.lock index 8379390..109d2d9 100644 Binary files a/resources/scripts/db/software.realm.lock and b/resources/scripts/db/software.realm.lock differ diff --git a/src/define/api/apiUrlDefine.js b/src/define/api/apiUrlDefine.ts similarity index 75% rename from src/define/api/apiUrlDefine.js rename to src/define/api/apiUrlDefine.ts index 6e8b88b..895a7ce 100644 --- a/src/define/api/apiUrlDefine.js +++ b/src/define/api/apiUrlDefine.ts @@ -12,7 +12,22 @@ let apiUrl = [ d3_url: { image: 'https://api.laitool.cc/v1/images/generations' }, - buy_url: 'https://api.laitool.cc/register?aff=Zmdu' + buy_url: 'https://api.laitool.cc/login' + }, + { + label: 'LAI API - 美国', + value: '2b443f53-ba12-42b3-a57c-e4df92685c73', + gpt_url: 'https://laitool.net/v1/chat/completions', + mj_url: { + imagine: 'https://laitool.net/mj/submit/imagine', + describe: 'https://laitool.net/mj/submit/describe', + update_file: 'https://laitool.net/mj/submit/upload-discord-images', + once_get_task: 'https://laitool.net/mj/task/${id}/fetch' + }, + d3_url: { + image: 'https://laitool.net/v1/images/generations' + }, + buy_url: 'https://laitool.net/login' }, { label: 'openai-hk', diff --git a/src/define/define.js b/src/define/define.js index 8aebecd..2d02a94 100644 --- a/src/define/define.js +++ b/src/define/define.js @@ -1,145 +1,149 @@ -const path = require('path') -const { app } = require('electron') let define = {} -if (!app.isPackaged) { - define = { - discordScript: path.join(__dirname, '../../src/main/discord/discordScript.js'), - zhanwei_image: path.join(__dirname, '../../resources/image/zhanwei.png'), - config_path: path.join(__dirname, '../../resources/config/global_setting.json'), - clip_setting: path.join(__dirname, '../../resources/config/clip_setting.json'), - sd_setting: path.join(__dirname, '../../resources/config/sd_config.json'), - dynamic_setting: path.join(__dirname, '../../resources/config/dynamic_setting.json'), - tag_setting: path.join(__dirname, '../../resources/config/tag_setting.json'), - img_base: path.join(__dirname, '../../resources/config/img_base.json'), - video_config: path.join(__dirname, '../../resources/config/video_config.json'), - system_config: path.join(__dirname, '../../resources/config/system_config.json'), - scripts_path: path.join(__dirname, '../../resources/scripts'), - db_path: path.join(__dirname, '../../resources/scripts/db'), - project_path: path.join(__dirname, '../../project'), - tts_path: path.join(__dirname, '../../tts'), - logger_path: path.join(__dirname, '../../resources/logger'), - package_path: path.join(__dirname, '../../resources/package'), - image_path: path.join(__dirname, '../../resources/image'), - temp_sd_image: path.join(__dirname, '../../resources/image/TempSDImage'), - draft_temp_path: path.join(__dirname, '../../resources/tmp/temp.zip'), - init_config_path: path.join(__dirname, '../../resources/tmp/config'), - clip_speed_temp_path: path.join(__dirname, '../../resources/tmp/Clip/speeds_tmp.json'), - add_canvases_temp_path: path.join(__dirname, '../../resources/tmp/Clip/canvases_tmp.json'), - add_sound_channel_mappings_temp_path: path.join( - __dirname, - '../../resources/tmp/Clip/sound_channel_mappings_tmp.json' - ), - add_vocal_separations_temp_path: path.join( - __dirname, - '../../resources/tmp/Clip/vocal_separations_tmp.json' - ), - add_material_video_temp_path: path.join( - __dirname, - '../../resources/tmp/Clip/videoMaterialTemp.json' - ), - add_tracks_segments_temp_path: path.join( - __dirname, - '../../resources/tmp/Clip/tracks_segments_tmp.json' - ), - add_tracks_type_temp_path: path.join( - __dirname, - '../../resources/tmp/Clip/tracks_type_tmp.json' - ), - add_material_animations_temp_path: path.join( - __dirname, - '../../resources/tmp/Clip/material_animations_tmp.json' - ), - add_material_text_temp_path: path.join( - __dirname, - '../../resources/tmp/Clip/material_text_temp.json' - ), - add_track_text_segments_temp_path: path.join( - __dirname, - '../../resources/tmp/Clip/track_text_segments_temp.json' - ), - add_materials_beats_tmp_path: path.join( - __dirname, - '../../resources/tmp/Clip/materials_beats_tmp.json' - ), - add_materials_audios_tmp_path: path.join( - __dirname, - '../../resources/tmp/Clip/materials_audios_tmp.json' - ), - add_tracks_audio_segments_tmp_path: path.join( - __dirname, - '../../resources/tmp/Clip/tracks_audio_segments_tmp.json' - ), - add_keyframe_tmp_path: path.join(__dirname, '../../resources/tmp/Clip/keyframe_tmp.json') - } -} else { - define = { - zhanwei_image: path.join(__dirname, '../../../resources/image/zhanwei.png'), - config_path: path.join(__dirname, '../../../resources/config/global_setting.json'), - clip_setting: path.join(__dirname, '../../../resources/config/clip_setting.json'), - sd_setting: path.join(__dirname, '../../../resources/config/sd_config.json'), - dynamic_setting: path.join(__dirname, '../../../resources/config/dynamic_setting.json'), - tag_setting: path.join(__dirname, '../../../resources/config/tag_setting.json'), - video_config: path.join(__dirname, '../../../resources/config/video_config.json'), - system_config: path.join(__dirname, '../../../resources/config/system_config.json'), - img_base: path.join(__dirname, '../../../resources/config/img_base.json'), - scripts_path: path.join(__dirname, '../../../resources/scripts'), - db_path: path.join(__dirname, '../../../resources/scripts/db'), - project_path: path.join(__dirname, '../../../project'), - tts_path: path.join(__dirname, '../../../tts'), - logger_path: path.join(__dirname, '../../../resources/logger'), - package_path: path.join(__dirname, '../../../resources/package'), - discordScript: path.join(__dirname, '../../../resources/scripts/discordScript.js'), - image_path: path.join(__dirname, '../../../resources/image'), - temp_sd_image: path.join(__dirname, '../../../resources/image/TempSDImage'), - draft_temp_path: path.join(__dirname, '../../../resources/tmp/temp.zip'), - init_config_path: path.join(__dirname, '../../../resources/tmp/config'), - clip_speed_temp_path: path.join(__dirname, '../../../resources/tmp/Clip/speeds_tmp.json'), - add_canvases_temp_path: path.join(__dirname, '../../../resources/tmp/Clip/canvases_tmp.json'), - add_sound_channel_mappings_temp_path: path.join( - __dirname, - '../../../resources/tmp/Clip/sound_channel_mappings_tmp.json' - ), - add_vocal_separations_temp_path: path.join( - __dirname, - '../../../resources/tmp/Clip/vocal_separations_tmp.json' - ), - add_material_video_temp_path: path.join( - __dirname, - '../../../resources/tmp/Clip/videoMaterialTemp.json' - ), - add_tracks_segments_temp_path: path.join( - __dirname, - '../../../resources/tmp/Clip/tracks_segments_tmp.json' - ), - add_tracks_type_temp_path: path.join( - __dirname, - '../../../resources/tmp/Clip/tracks_type_tmp.json' - ), - add_material_animations_temp_path: path.join( - __dirname, - '../../../resources/tmp/Clip/material_animations_tmp.json' - ), - add_material_text_temp_path: path.join( - __dirname, - '../../../resources/tmp/Clip/material_text_temp.json' - ), - add_track_text_segments_temp_path: path.join( - __dirname, - '../../../resources/tmp/Clip/track_text_segments_temp.json' - ), - add_materials_beats_tmp_path: path.join( - __dirname, - '../../../resources/tmp/Clip/materials_beats_tmp.json' - ), - add_materials_audios_tmp_path: path.join( - __dirname, - '../../../resources/tmp/Clip/materials_audios_tmp.json' - ), - add_tracks_audio_segments_tmp_path: path.join( - __dirname, - '../../../resources/tmp/Clip/tracks_audio_segments_tmp.json' - ), - add_keyframe_tmp_path: path.join(__dirname, '../../../resources/tmp/Clip/keyframe_tmp.json') +const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined' + +if (!isBrowser) { + const path = require('path') + const { app } = require('electron') + if (!app.isPackaged) { + define = { + discordScript: path.join(__dirname, '../../src/main/discord/discordScript.js'), + zhanwei_image: path.join(__dirname, '../../resources/image/zhanwei.png'), + config_path: path.join(__dirname, '../../resources/config/global_setting.json'), + clip_setting: path.join(__dirname, '../../resources/config/clip_setting.json'), + sd_setting: path.join(__dirname, '../../resources/config/sd_config.json'), + dynamic_setting: path.join(__dirname, '../../resources/config/dynamic_setting.json'), + tag_setting: path.join(__dirname, '../../resources/config/tag_setting.json'), + img_base: path.join(__dirname, '../../resources/config/img_base.json'), + video_config: path.join(__dirname, '../../resources/config/video_config.json'), + system_config: path.join(__dirname, '../../resources/config/system_config.json'), + scripts_path: path.join(__dirname, '../../resources/scripts'), + db_path: path.join(__dirname, '../../resources/scripts/db'), + project_path: path.join(__dirname, '../../project'), + tts_path: path.join(__dirname, '../../tts'), + logger_path: path.join(__dirname, '../../resources/logger'), + package_path: path.join(__dirname, '../../resources/package'), + image_path: path.join(__dirname, '../../resources/image'), + temp_sd_image: path.join(__dirname, '../../resources/image/TempSDImage'), + draft_temp_path: path.join(__dirname, '../../resources/tmp/temp.zip'), + init_config_path: path.join(__dirname, '../../resources/tmp/config'), + clip_speed_temp_path: path.join(__dirname, '../../resources/tmp/Clip/speeds_tmp.json'), + add_canvases_temp_path: path.join(__dirname, '../../resources/tmp/Clip/canvases_tmp.json'), + add_sound_channel_mappings_temp_path: path.join( + __dirname, + '../../resources/tmp/Clip/sound_channel_mappings_tmp.json' + ), + add_vocal_separations_temp_path: path.join( + __dirname, + '../../resources/tmp/Clip/vocal_separations_tmp.json' + ), + add_material_video_temp_path: path.join( + __dirname, + '../../resources/tmp/Clip/videoMaterialTemp.json' + ), + add_tracks_segments_temp_path: path.join( + __dirname, + '../../resources/tmp/Clip/tracks_segments_tmp.json' + ), + add_tracks_type_temp_path: path.join( + __dirname, + '../../resources/tmp/Clip/tracks_type_tmp.json' + ), + add_material_animations_temp_path: path.join( + __dirname, + '../../resources/tmp/Clip/material_animations_tmp.json' + ), + add_material_text_temp_path: path.join( + __dirname, + '../../resources/tmp/Clip/material_text_temp.json' + ), + add_track_text_segments_temp_path: path.join( + __dirname, + '../../resources/tmp/Clip/track_text_segments_temp.json' + ), + add_materials_beats_tmp_path: path.join( + __dirname, + '../../resources/tmp/Clip/materials_beats_tmp.json' + ), + add_materials_audios_tmp_path: path.join( + __dirname, + '../../resources/tmp/Clip/materials_audios_tmp.json' + ), + add_tracks_audio_segments_tmp_path: path.join( + __dirname, + '../../resources/tmp/Clip/tracks_audio_segments_tmp.json' + ), + add_keyframe_tmp_path: path.join(__dirname, '../../resources/tmp/Clip/keyframe_tmp.json') + } + } else { + define = { + zhanwei_image: path.join(__dirname, '../../../resources/image/zhanwei.png'), + config_path: path.join(__dirname, '../../../resources/config/global_setting.json'), + clip_setting: path.join(__dirname, '../../../resources/config/clip_setting.json'), + sd_setting: path.join(__dirname, '../../../resources/config/sd_config.json'), + dynamic_setting: path.join(__dirname, '../../../resources/config/dynamic_setting.json'), + tag_setting: path.join(__dirname, '../../../resources/config/tag_setting.json'), + video_config: path.join(__dirname, '../../../resources/config/video_config.json'), + system_config: path.join(__dirname, '../../../resources/config/system_config.json'), + img_base: path.join(__dirname, '../../../resources/config/img_base.json'), + scripts_path: path.join(__dirname, '../../../resources/scripts'), + db_path: path.join(__dirname, '../../../resources/scripts/db'), + project_path: path.join(__dirname, '../../../project'), + tts_path: path.join(__dirname, '../../../tts'), + logger_path: path.join(__dirname, '../../../resources/logger'), + package_path: path.join(__dirname, '../../../resources/package'), + discordScript: path.join(__dirname, '../../../resources/scripts/discordScript.js'), + image_path: path.join(__dirname, '../../../resources/image'), + temp_sd_image: path.join(__dirname, '../../../resources/image/TempSDImage'), + draft_temp_path: path.join(__dirname, '../../../resources/tmp/temp.zip'), + init_config_path: path.join(__dirname, '../../../resources/tmp/config'), + clip_speed_temp_path: path.join(__dirname, '../../../resources/tmp/Clip/speeds_tmp.json'), + add_canvases_temp_path: path.join(__dirname, '../../../resources/tmp/Clip/canvases_tmp.json'), + add_sound_channel_mappings_temp_path: path.join( + __dirname, + '../../../resources/tmp/Clip/sound_channel_mappings_tmp.json' + ), + add_vocal_separations_temp_path: path.join( + __dirname, + '../../../resources/tmp/Clip/vocal_separations_tmp.json' + ), + add_material_video_temp_path: path.join( + __dirname, + '../../../resources/tmp/Clip/videoMaterialTemp.json' + ), + add_tracks_segments_temp_path: path.join( + __dirname, + '../../../resources/tmp/Clip/tracks_segments_tmp.json' + ), + add_tracks_type_temp_path: path.join( + __dirname, + '../../../resources/tmp/Clip/tracks_type_tmp.json' + ), + add_material_animations_temp_path: path.join( + __dirname, + '../../../resources/tmp/Clip/material_animations_tmp.json' + ), + add_material_text_temp_path: path.join( + __dirname, + '../../../resources/tmp/Clip/material_text_temp.json' + ), + add_track_text_segments_temp_path: path.join( + __dirname, + '../../../resources/tmp/Clip/track_text_segments_temp.json' + ), + add_materials_beats_tmp_path: path.join( + __dirname, + '../../../resources/tmp/Clip/materials_beats_tmp.json' + ), + add_materials_audios_tmp_path: path.join( + __dirname, + '../../../resources/tmp/Clip/materials_audios_tmp.json' + ), + add_tracks_audio_segments_tmp_path: path.join( + __dirname, + '../../../resources/tmp/Clip/tracks_audio_segments_tmp.json' + ), + add_keyframe_tmp_path: path.join(__dirname, '../../../resources/tmp/Clip/keyframe_tmp.json') + } } } @@ -155,4 +159,5 @@ define['API'] = 'f85d39ed5a40fd09966f13f12b6cf0f0' define['lms'] = 'https://lms.laitool.cn' + export { define } diff --git a/src/define/enum/image.ts b/src/define/enum/image.ts index 0f5484f..61d1eed 100644 --- a/src/define/enum/image.ts +++ b/src/define/enum/image.ts @@ -1,15 +1,4 @@ -/** - * Flux 调用API时候的 生图模型 - */ -export enum FLxuAPIImageType { - FLUX = "flux", - FLUX_PRO = "flux-pro", - FLUX_DEV = "flux-dev", - FLUX_SCHNELL = "flux-schnell", - FLUX_PRO_MAX = "flux-pro-max" -} - export enum PresetType { // 角色 diff --git a/src/define/enum/mjEnum.ts b/src/define/enum/mjEnum.ts index 6cc6aca..3cf17da 100644 --- a/src/define/enum/mjEnum.ts +++ b/src/define/enum/mjEnum.ts @@ -35,10 +35,10 @@ export enum MJRobotType { export enum MJSpeed { // 快速 - FAST = 'fast', + FAST = 'FAST', // 休闲 - RELAX = 'relaxed' + RELAX = 'RELAXED' } export enum MJRespoonseType { diff --git a/src/define/enum/option.ts b/src/define/enum/option.ts index 2fef9e8..9b7dc05 100644 --- a/src/define/enum/option.ts +++ b/src/define/enum/option.ts @@ -36,5 +36,25 @@ export enum OptionKeyName { */ TTS_GlobalSetting = 'TTS_GlobalSetting', + //#endregion + + + //#region MJ + + /** + * MJ 基础设置 + */ + MJ_GlobalSetting = 'MJ_GlobalSetting', + + //#endregion + + //#region FLUX + + /** + * FLUX API 模型列表 + */ + FLUX_APIModelList = 'FLUX_APIModelList', + + //#endregion } \ No newline at end of file diff --git a/src/define/response/ForwardResponse.ts b/src/define/response/ForwardResponse.ts new file mode 100644 index 0000000..c0e632c --- /dev/null +++ b/src/define/response/ForwardResponse.ts @@ -0,0 +1,25 @@ +import { ValidateJson } from "../Tools/validate"; + +/** + * 获取转发请求的数据,序列化后返回 + * @param response + * @returns + */ +function GetForwardResponseData(response: any) { + if (response.status != 200) { + throw new Error("转发请求失败") + } + if (response.data.code != 1) { + throw new Error(response.data.message) + } + if (!ValidateJson(response.data.data)) { + throw new Error(response.data.data) + } + return JSON.parse(response.data.data); +} + +let ForwardResponse = { + GetForwardResponseData, +} + +export default ForwardResponse; \ No newline at end of file diff --git a/src/main/IPCEvent/mjIpc.js b/src/main/IPCEvent/mjIpc.js index 87d1c49..f7bcab0 100644 --- a/src/main/IPCEvent/mjIpc.js +++ b/src/main/IPCEvent/mjIpc.js @@ -60,7 +60,6 @@ function MjIpc() { ) // 获取MJ生图的方式 - // GetMJGenerateCategory: async (callback) => callback(await ipcRenderer.invoke(DEFINE_STRING.MJ.GET_MJ_GENERATE_CATEGORY)), ipcMain.handle( DEFINE_STRING.MJ.GET_MJ_GENERATE_CATEGORY, async (event) => await mjSimple.GetMJGenerateCategory() diff --git a/src/main/IPCEvent/optionsIpc.ts b/src/main/IPCEvent/optionsIpc.ts index 944fca7..83ae84e 100644 --- a/src/main/IPCEvent/optionsIpc.ts +++ b/src/main/IPCEvent/optionsIpc.ts @@ -10,7 +10,7 @@ function OptionsIpc() { */ ipcMain.handle( DEFINE_STRING.OPTIONS.GET_OPTION_BY_KEY, - async (_, key: string) => await OptionHandle.GetOptionByKey(key) + async (_, key: string | string[]) => await OptionHandle.GetOptionByKey(key) ) /** diff --git a/src/main/Public/GPT.js b/src/main/Public/GPT.js index 812c2ed..7d9733f 100644 --- a/src/main/Public/GPT.js +++ b/src/main/Public/GPT.js @@ -4,7 +4,6 @@ import { DEFINE_STRING } from '../../define/define_string' import { define } from '../../define/define' let fspromises = require('fs').promises import { gptDefine } from '../../define/gptDefine' -import { apiUrl } from '../../define/api/apiUrlDefine' import { successMessage } from '../Public/generalTools' import { RetryWithBackoff } from '../../define/Tools/common' diff --git a/src/main/Service/Flux/flux.ts b/src/main/Service/Flux/flux.ts index 744fd66..84f759e 100644 --- a/src/main/Service/Flux/flux.ts +++ b/src/main/Service/Flux/flux.ts @@ -11,6 +11,8 @@ import { Base64ToFile, GetImageBase64 } from '../../../define/Tools/image'; import { BookBackTaskStatus } from '../../../define/enum/bookEnum'; import { MJAction, MJImageType } from '../../../define/enum/mjEnum'; import { GptService } from '../GPT/gpt'; +import { TaskModal } from '@/model/task'; +import { ValidateJson } from '@/define/Tools/validate'; export class FluxOpt { gptService: GptService @@ -203,18 +205,55 @@ export class FluxOpt { * @param body 请求的请求体 * @returns */ - async FluxAPIImageRequest(url: string, key: string, body: { model: string; prompt: string; size: string; }): Promise { - let response = await axios.post(url, { ...body, n: 1 }, { - headers: { - Authorization: 'Bearer ' + key - } - }) + async FluxAPIImageRequest(url: string, key: string, body: { model: string; prompt: string; size: string; }, useTransfer: boolean): Promise { - if (response.data && response.data.data && response.data.data.length > 0) { - return response.data.data[0].url - } else { - return undefined + let data = { + ...body, + n: 1 } + + let resData: any = []; + + if (useTransfer) { + let transferUrl = define.lms + "/lms/Forward/SimpleTransfer"; + let transferConfig = { + method: 'post', + url: transferUrl, + maxBodyLength: Infinity, + timeout: 600000, // 600 seconds timeout + headers: { + 'Content-Type': 'application/json' + }, + data: JSON.stringify({ + url: url, + apiKey: key, + dataString: JSON.stringify(data) + }) + } + let response = await axios(transferConfig) + if (response.status != 200) { + throw new Error("转发请求失败") + } + if (response.data.code != 1) { + throw new Error(response.data.message) + } + if (!ValidateJson(response.data.data)) { + throw new Error(response.data.data) + } + let re = JSON.parse(response.data.data); + resData = re.data + } else { + let response = await axios.post(url, data, { + headers: { + Authorization: 'Bearer ' + key + } + }) + resData = response.data.data + } + if (!Array.isArray(resData) || resData.length == 0) { + throw new Error("FLUX API 返回数据异常") + } + return resData[0].url } /** @@ -239,7 +278,11 @@ export class FluxOpt { prompt = sdSetting.webui.prompt + ', ' + prompt } let size = `${sdSetting.webui.width}x${sdSetting.webui.height}` + if (!sdSetting.flux.model) { + throw new Error('FLUX API 模型为空,请先设置!') + } let model = sdSetting.flux.model + let useTransfer = sdSetting.flux.useTransfer // 一次请求生成一张 多个请求 let SdOriginalImage = path.join(book.bookFolderPath, 'data/SdOriginalImage'); @@ -259,7 +302,7 @@ export class FluxOpt { model: model, prompt: prompt, size: size - }) + }, useTransfer) // 这边开始处理返回的数据 if (isEmpty(imageUrl)) { throw new Error('FLUX 生图返回的图片地址为空') diff --git a/src/main/Service/MJ/mj.ts b/src/main/Service/MJ/mj.ts index bdcde2e..15e501d 100644 --- a/src/main/Service/MJ/mj.ts +++ b/src/main/Service/MJ/mj.ts @@ -9,7 +9,7 @@ import { BookBackTaskStatus, BookBackTaskType, BookTaskStatus, BookType, DialogT import { DEFINE_STRING } from "../../../define/define_string"; import { MJ } from "../../../model/mj"; import { MJRespoonseType } from "../../../define/enum/mjEnum"; -import { MJSetting } from "../../../model/Setting/mjSetting"; +import { MJSettingModel } from "../../../model/Setting/mjSetting"; import { GeneralResponse } from "../../../model/generalResponse" import { LoggerStatus, ResponseMessageType } from "../../../define/enum/softwareEnum"; import { ImageStyle } from "../Book/imageStyle"; @@ -27,7 +27,7 @@ const fspromise = fs.promises export class MJOpt { mjApi: MJApi; - mjSetting: MJSetting.MjSetting + mjSimpleSetting: MJSettingModel.MjSimpleSettingModel; imageStyle: ImageStyle; logScheduler: LogScheduler; tools: Tools; @@ -48,8 +48,8 @@ export class MJOpt { * 获取MJ设置 */ async GetMJSetting() { - if (!this.mjSetting) { - this.mjSetting = await this.softWareServiceBasic.GetMjSetting() + if (!this.mjSimpleSetting) { + this.mjSimpleSetting = await this.softWareServiceBasic.GetMjSetting() } } @@ -231,7 +231,7 @@ export class MJOpt { code: 1, type: MJRespoonseType.UPDATED, mjType: MJAction.DESCRIBE, - category: this.mjSetting.type, + category: this.mjSimpleSetting.type, messageId: reqRes, id: task.bookTaskDetailId, progress: 0, @@ -258,7 +258,7 @@ export class MJOpt { code: 0, type: MJRespoonseType.UPDATED, mjType: MJAction.DESCRIBE, - category: this.mjSetting.type, + category: this.mjSimpleSetting.type, messageId: undefined, id: task.bookTaskDetailId, progress: 0, @@ -560,7 +560,7 @@ export class MJOpt { await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, { mjApiUrl: this.mjApi.imagineUrl, progress: 100, - category: this.mjApi.mjSetting.type, + category: this.mjApi.mjSimpleSetting.type, imageClick: task_res.imageClick, imageShow: task_res.imageShow, messageId: task_res.messageId, @@ -622,7 +622,7 @@ export class MJOpt { await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, { mjApiUrl: this.mjApi.imagineUrl, progress: 100, - category: this.mjApi.mjSetting.type, + category: this.mjApi.mjSimpleSetting.type, imageClick: task_res.imageClick, imageShow: task_res.imageShow, messageId: task_res.messageId, @@ -644,7 +644,7 @@ export class MJOpt { await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, { mjApiUrl: this.mjApi.imagineUrl, progress: task_res.progress, - category: this.mjApi.mjSetting.type, + category: this.mjApi.mjSimpleSetting.type, imageClick: task_res.imageClick, imageShow: task_res.imageShow, messageId: task_res.messageId, @@ -697,7 +697,6 @@ export class MJOpt { // 这个就是任务ID let reqRes = await this.mjApi.SubmitMJImagine(task.id, prompt) if (reqRes == '23') { - console.log(task.id, "33333") // 任务队列过多,重新提交排队 await this.bookServiceBasic.UpdateTaskStatus({ id: task.id, @@ -711,7 +710,7 @@ export class MJOpt { code: 1, type: MJRespoonseType.UPDATED, mjType: MJAction.IMAGINE, - category: this.mjSetting.type, + category: this.mjSimpleSetting.type, message_id: '', id: task.bookTaskDetailId, progress: 0, @@ -721,7 +720,7 @@ export class MJOpt { await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, { mjApiUrl: this.mjApi.imagineUrl, progress: 0, - category: this.mjApi.mjSetting.type, + category: this.mjApi.mjSimpleSetting.type, imageClick: "", imageShow: "", messageId: "", @@ -747,7 +746,7 @@ export class MJOpt { code: 1, type: MJRespoonseType.UPDATED, mjType: MJAction.IMAGINE, - category: this.mjSetting.type, + category: this.mjSimpleSetting.type, message_id: reqRes, id: task.bookTaskDetailId, progress: 0, @@ -773,7 +772,7 @@ export class MJOpt { code: 0, type: MJRespoonseType.UPDATED, mjType: MJAction.IMAGINE, - category: this.mjSetting.type, + category: this.mjSimpleSetting.type, messageId: undefined, id: task.bookTaskDetailId, progress: 0, @@ -784,7 +783,7 @@ export class MJOpt { await this.bookServiceBasic.UpdateBookTaskDetailMjMessage(task.bookTaskDetailId, { mjApiUrl: this.mjApi.imagineUrl, progress: 0, - category: this.mjApi.mjSetting.type, + category: this.mjApi.mjSimpleSetting.type, imageClick: "", imageShow: "", messageId: "", diff --git a/src/main/Service/MJ/mjApi.ts b/src/main/Service/MJ/mjApi.ts index 81da1c9..0874030 100644 --- a/src/main/Service/MJ/mjApi.ts +++ b/src/main/Service/MJ/mjApi.ts @@ -1,65 +1,83 @@ import axios from "axios" import { define } from "../../../define/define" -import { GetImageBase64 } from "../../../define/Tools/image" -import { MJImageType, MJRespoonseType, MJSpeed } from "../../../define/enum/mjEnum" +import { MJImageType, MJRespoonseType, MJRobotType, MJSpeed } from "../../../define/enum/mjEnum" import { MJSettingService } from "../../../define/db/service/SoftWare/mjSettingService" import { BookBackTaskListService } from "../../../define/db/service/Book/bookBackTaskListService" import { BookBackTaskStatus } from "../../../define/enum/bookEnum" -import { MJSetting } from "../../../model/Setting/mjSetting" -import { GPT } from "../../Public/GPT" +import { MJSettingModel } from "../../../model/Setting/mjSetting" import { MJ } from "../../../model/mj" -import { LaiAPIType } from "../../../define/enum/softwareEnum" import { isEmpty } from "lodash" +import { OptionServices } from "../Options/optionServices" +import { OptionKeyName } from "@/define/enum/option" +import { ValidateJson } from "@/define/Tools/validate" +import { apiUrl } from "@/define/api/apiUrlDefine" /** * 调用MJ的API类 */ class MJApi { - mjSetting: MJSetting.MjSetting + mjSimpleSetting: MJSettingModel.MjSimpleSettingModel bootType: string imagineUrl: string fetchTaskUrl: string describeUrl: string + optionServices: OptionServices + + mj_globalSetting: MJSettingModel.MJ_GlobalSettingModel + constructor() { this.bootType = "MID_JOURNEY" + this.optionServices = new OptionServices() } - async InitMJSetting(): Promise { + /** + * 初始化MJ设置 + */ + async InitMJSetting(): Promise { // 获取MJ配置,从数据库中 let _mjSettingService = await MJSettingService.getInstance() let mjSettings = _mjSettingService.GetMJSettingTreeData() if (mjSettings.code == 0) { throw new Error(mjSettings.message) } - this.mjSetting = mjSettings.data - this.bootType = this.mjSetting.selectRobot == "niji" ? "NIJI_JOURNEY" : "MID_JOURNEY" - if (this.mjSetting.type == MJImageType.REMOTE_MJ) { + + + let mjSettingData = await this.optionServices.GetOptionByKey(OptionKeyName.MJ_GlobalSetting); + if (mjSettingData.code == 0) { + throw new Error("加载MJ设置失败,失败原因如下:" + mjSettingData.message) + } + if (mjSettingData.data == null) { + throw new Error("加载MJ设置失败,失败原因如下:没有找到对应的MJ设置,请先去MJ设置中设置") + } + if (!ValidateJson(mjSettingData.data.value)) { + throw new Error("MJ设置的数据格式不正确,请检查数据格式") + } + + this.mj_globalSetting = JSON.parse(mjSettingData.data.value) as MJSettingModel.MJ_GlobalSettingModel + this.mjSimpleSetting = this.mj_globalSetting.mj_simpleSetting + + this.bootType = this.mjSimpleSetting.selectRobot == MJRobotType.NIJI ? "NIJI_JOURNEY" : "MID_JOURNEY" + if (this.mjSimpleSetting.type == MJImageType.REMOTE_MJ) { this.imagineUrl = define.remotemj_api + 'mj/submit/imagine' this.describeUrl = define.remotemj_api + 'mj/submit/describe' this.fetchTaskUrl = define.remotemj_api + 'mj/task/${id}/fetch' } else { - if (global.config.laiApiSelect == LaiAPIType.HK_PROXY) { - this.imagineUrl = define.hkServerUrl + 'mj/submit/imagine' - this.describeUrl = define.hkServerUrl + 'mj/submit/describe' - this.fetchTaskUrl = define.hkServerUrl + 'mj/task/${id}/fetch' - } else if (global.config.laiApiSelect == LaiAPIType.BAK_MAIN) { - this.imagineUrl = define.bakServerUrl + 'mj/submit/imagine' - this.describeUrl = define.bakServerUrl + 'mj/submit/describe' - this.fetchTaskUrl = define.bakServerUrl + 'mj/task/${id}/fetch' - } else { - let gpt = new GPT() - let mj_api = (await gpt.GetGPTBusinessOption('all', (value) => value.mj_url)).data - let mj_api_url_index = mj_api.findIndex((item) => item.value == this.mjSetting.apiSetting.mjApiUrl) - if (mj_api_url_index == -1) { - throw new Error('没有找到对应的MJ API的配置,请先检查配置') - } - this.imagineUrl = mj_api[mj_api_url_index].mj_url.imagine; - this.fetchTaskUrl = mj_api[mj_api_url_index].mj_url.once_get_task; - this.describeUrl = mj_api[mj_api_url_index].mj_url.imagine.replace("imagine", "describe"); + + let apiUrlIndex = apiUrl.findIndex(item => item.value == this.mj_globalSetting.mj_apiSetting.mjApiUrl); + if (apiUrlIndex == -1) { + throw new Error('没有找到MJ API对应的请求URL,请检查配置'); } + + let apiUrlItem = apiUrl[apiUrlIndex]; + if (apiUrlItem.mj_url == null) { + throw new Error('没有找到MJ API对应的请求URL,请检查配置'); + } + + this.imagineUrl = apiUrlItem.mj_url.imagine + this.describeUrl = apiUrlItem.mj_url.describe + this.fetchTaskUrl = apiUrlItem.mj_url.once_get_task } - return mjSettings.data } //#region 获取对应的任务,通过ID @@ -71,27 +89,66 @@ class MJApi { async GetMJAPITaskById(taskId: string, backTaskId: string) { try { await this.InitMJSetting(); - let url = this.fetchTaskUrl.replace("${id}", taskId) + let APIDescribeUrl = this.fetchTaskUrl.replace("${id}", taskId) let headers = undefined - if (this.mjSetting.type == MJImageType.REMOTE_MJ) { + let useTransfer = false + + if (this.mjSimpleSetting.type == MJImageType.REMOTE_MJ) { headers = { 'mj-api-secret': define.API } + useTransfer = this.mj_globalSetting.mj_remoteSimpleSetting.useTransfer } else { headers = { - Authorization: this.mjSetting.apiSetting.apiKey + Authorization: this.mj_globalSetting.mj_apiSetting.apiKey } + useTransfer = this.mj_globalSetting.mj_apiSetting.useTransfer } - let res = await axios.get(url, { - headers: headers - }) + let resData = undefined + if (useTransfer) { - let progress = res.data.progress && res.data.progress.length > 0 - ? parseInt(res.data.progress.slice(0, -1)) + let url = define.lms + "/lms/Forward/GetTransfer"; + let config = { + method: 'post', + url: url, + maxBodyLength: Infinity, + headers: { + 'Content-Type': 'application/json' + }, + data: JSON.stringify({ + url: APIDescribeUrl, + apiKey: this.mjSimpleSetting.type == MJImageType.REMOTE_MJ ? + define.API : + headers.Authorization, + }) + } + + let res = await axios.request(config); + if (res.status != 200) { + throw new Error("转发请求失败") + } + if (res.data.code != 1) { + throw new Error(res.data.message) + } + if (!ValidateJson(res.data.data)) { + throw new Error(res.data.data) + } + resData = JSON.parse(res.data.data); + + } else { + let res = await axios.get(APIDescribeUrl, { + headers: headers + }) + resData = res.data + } + + + let progress = resData.progress && resData.progress.length > 0 + ? parseInt(resData.progress.slice(0, -1)) : 0 - let status = res.data.status.toLowerCase() + let status = resData.status.toLowerCase() let code = status == 'failure' || status == 'cancel' ? 0 : 1 let _bookBackTaskListService = await BookBackTaskListService.getInstance() @@ -101,22 +158,22 @@ class MJApi { _bookBackTaskListService.UpdateTaskStatus({ id: backTaskId, status: BookBackTaskStatus.FAIL, - errorMessage: res.data.message + errorMessage: resData.message }) } } let resObj = { type: MJRespoonseType.UPDATED, progress: isNaN(progress) ? 0 : progress, - category: this.mjSetting.type, - imageClick: res.data.imageUrl, - imageShow: res.data.imageUrl, - imagePath: res.data.imageUrl, + category: this.mjSimpleSetting.type, + imageClick: resData.imageUrl, + imageShow: resData.imageUrl, + imagePath: resData.imageUrl, messageId: taskId, status: status, code: code, - prompt: res.data.prompt == "" ? res.data.promptEn : res.data.prompt, - message: res.data.failReason, + prompt: resData.prompt == "" ? resData.promptEn : resData.prompt, + message: resData.failReason, mjApiUrl: this.fetchTaskUrl, } as MJ.MJResponseToFront return resObj @@ -135,7 +192,7 @@ class MJApi { async SubmitMJDescribe(param: MJ.APIDescribeParams): Promise { await this.InitMJSetting() let res = undefined - switch (this.mjSetting.type) { + switch (this.mjSimpleSetting.type) { case MJImageType.REMOTE_MJ: case MJImageType.API_MJ: res = await this.SubmitMJDescribeAPI(param) @@ -157,7 +214,7 @@ class MJApi { botType: this.bootType, base64: param.image, accountFilter: { - modes: [this.mjSetting.apiSetting.mjSpeed == MJSpeed.FAST ? "FAST" : "RELAX"], + modes: [this.mj_globalSetting.mj_apiSetting.mjSpeed == MJSpeed.FAST ? "FAST" : "RELAX"], remark: global.machineId }, @@ -168,11 +225,12 @@ class MJApi { } } - if (this.mjSetting.type == MJImageType.REMOTE_MJ) { + if (this.mjSimpleSetting.type == MJImageType.REMOTE_MJ) { config.headers["mj-api-secret"] = define.API; + delete data.accountFilter.modes; } else { delete data.accountFilter.remark - config.headers["Authorization"] = this.mjSetting.apiSetting.apiKey; + config.headers["Authorization"] = this.mj_globalSetting.mj_apiSetting.apiKey; } // 开始请求 @@ -215,7 +273,7 @@ class MJApi { async SubmitMJImagine(taskId: string, prompt: string): Promise { await this.InitMJSetting() let res = undefined - switch (this.mjSetting.type) { + switch (this.mjSimpleSetting.type) { case MJImageType.REMOTE_MJ: case MJImageType.API_MJ: res = await this.SubmitMJImagineAPI(taskId, prompt) @@ -233,12 +291,13 @@ class MJApi { async SubmitMJImagineAPI(taskId: string, prompt: string): Promise { let _bookBackTaskListService = await BookBackTaskListService.getInstance() + // 提交API的出图任务 let data = { botType: this.bootType, prompt: prompt, accountFilter: { - modes: [this.mjSetting.apiSetting.mjSpeed == MJSpeed.FAST ? "FAST" : "RELAX"], + modes: [this.mj_globalSetting.mj_apiSetting.mjSpeed == MJSpeed.FAST ? "FAST" : "RELAX"], remark: global.machineId }, @@ -249,18 +308,59 @@ class MJApi { } } - if (this.mjSetting.type == MJImageType.REMOTE_MJ) { + let useTransfer = false; + + if (this.mjSimpleSetting.type == MJImageType.REMOTE_MJ) { config.headers["mj-api-secret"] = define.API; + delete data.accountFilter.modes; + useTransfer = this.mj_globalSetting.mj_remoteSimpleSetting.useTransfer } else { delete data.accountFilter.remark - config.headers["Authorization"] = this.mjSetting.apiSetting.apiKey; + config.headers["Authorization"] = this.mj_globalSetting.mj_apiSetting.apiKey; + useTransfer = this.mj_globalSetting.mj_apiSetting.useTransfer } - // 开始请求 - let res = await axios.post(this.imagineUrl, data, config) + let resData: any = undefined; + if (useTransfer) { + let url = define.lms + "/lms/Forward/SimpleTransfer" + let transferConfig = { + method: 'post', + url: url, + maxBodyLength: Infinity, + headers: { + 'Content-Type': 'application/json' + }, + data: JSON.stringify({ + url: this.imagineUrl, + apiKey: this.mjSimpleSetting.type == MJImageType.REMOTE_MJ ? define.API : this.mj_globalSetting.mj_apiSetting.apiKey, + dataString: JSON.stringify(data) + }) + } + let res = await axios.request(transferConfig); + if (res.status != 200) { + throw new Error("转发请求失败") + } + if (res.data.code != 1) { + throw new Error(res.data.message) + } + if (!ValidateJson(res.data.data)) { + throw new Error(res.data.data) + } + let re = JSON.parse(res.data.data); + resData = re + } else { + + // 开始请求 + let res = await axios.post(this.imagineUrl, data, config) + resData = res.data + } + + if (resData == null) { + throw new Error("返回的数据为空") + } // 某些API的返回的code为23,表示队列已满,需要重新请求 - if (res.data.code == 23) { + if (resData.code == 23) { _bookBackTaskListService.UpdateTaskStatus({ id: taskId, status: BookBackTaskStatus.RECONNECT @@ -268,13 +368,13 @@ class MJApi { return '23' } - if (res.data.code != 1 && res.data.code != 22) { + if (resData.code != 1 && resData.code != 22) { _bookBackTaskListService.UpdateTaskStatus({ id: taskId, status: BookBackTaskStatus.FAIL, - errorMessage: res.data.description + errorMessage: resData.description }) - throw new Error(res.data.description) + throw new Error(resData.description) } _bookBackTaskListService.UpdateTaskStatus({ @@ -282,7 +382,7 @@ class MJApi { status: BookBackTaskStatus.RUNNING }) - return res.data.result as string + return resData.result as string } diff --git a/src/main/Service/MJ/mjDefine.ts b/src/main/Service/MJ/mjDefine.ts new file mode 100644 index 0000000..a78588b --- /dev/null +++ b/src/main/Service/MJ/mjDefine.ts @@ -0,0 +1,169 @@ +import { apiUrl } from "@/define/api/apiUrlDefine" +import { MJRobotType, MJSpeed } from "@/define/enum/mjEnum" + +/** + * 获取MJ的请求模式列表 + * @returns + */ +function GetMJRequestModelOptions() { + let mjRequstModel = [{ + label: "本地MJ(待开发)", + value: "local_mj", + disable: true + }, + { + label: "代理MJ(token)", + value: "remote_mj", + disable: false + }, + { + label: "浏览器模式", + value: "browser_mj", + disable: false + }, + { + label: "API模式", + value: "api_mj", + disable: false + }] + return mjRequstModel.filter(item => !item.disable) +} + +/** + * 获取MJ的机器人列表 + * @returns + */ +function GetMJRobotOptions() { + return [{ + label: 'MJ', + value: MJRobotType.MJ + }, + { + label: 'NIJI', + value: MJRobotType.NIJI + }] +} + +/** + * 获取机器人对应的出图模型 + */ +function GetMJRobotModelOptions(mjRobot?: MJRobotType) { + let allRobotModel = [ + { + label: "MJ V6.0", + text: "v 6", + type: MJRobotType.MJ, + value: "3e6473ab-9a64-4574-9a38-f5c75af552b6" + }, + { + label: "MJ V5.2", + text: "v 5.2", + type: MJRobotType.MJ, + value: "27a0d30e-f46c-4684-96c8-d91334deb94f" + }, + { + label: "MJ V5.1", + text: "v 5.1", + type: MJRobotType.MJ, + value: "e1226715-e969-44c4-b18b-f2ad5dae5d2f" + }, { + label: "MJ V5.0", + text: "v 5", + type: MJRobotType.MJ, + value: "afb7bea1-4eda-46ea-8165-34701b4566bf" + }, { + label: "MJ V4.0", + text: "v 4", + type: MJRobotType.MJ, + value: "d05b8497-7f4a-4890-8fac-89f1803984d2" + }, { + label: "NIJI V6", + text: "niji 6", + type: MJRobotType.NIJI, + value: "99377cad-c103-4cee-a958-86a104879328" + }, { + label: "NIJI V5", + text: "niji 5", + type: MJRobotType.NIJI, + value: "53cec077-9885-4635-ab18-e021066b2c4c" + }, { + label: "NIJI V4", + text: "niji 4", + type: MJRobotType.NIJI, + value: "6a7199fe-6e0d-40a9-9772-b5eb3d2e2e66" + }, + ] + + switch (mjRobot) { + case MJRobotType.MJ: + return allRobotModel.filter(item => item.type == MJRobotType.MJ) + case MJRobotType.NIJI: + return allRobotModel.filter(item => item.type == MJRobotType.NIJI) + default: + return allRobotModel + } +} + +/** + * 获取MJ出图的比例Options + * @returns + */ +function GetMJImageScaleOptions() { + return [{ + label: "1:1", + text: "1:1", + value: "3e2772f2-041c-49c6-ba13-d0ed120310b8" + }, { + label: "4:3", + text: "4:3", + value: "fcef555c-1958-4082-88fe-434782aa8151" + }, { + label: "3:4", + text: "3:4", + value: "13f71d53-73a3-4c9b-9c1e-6e7e939aee73" + }, { + label: "16:9", + text: "16:9", + value: "bf33ce1a-15cd-4901-b38e-89543cf14a1f" + }, { + label: "9:16", + text: "9:16", + value: "fd4641e2-97f4-4a86-8616-4965e05f3348" + }] +} + +/** + * 获取MJ API 可用的URL Options + * @returns + */ +function GetMJAPIUrlOptions() { + return apiUrl.filter((item) => item.mj_url) +} + +/** + * 获取MJ的速度Options + * @returns + */ +function GetMJSpeedOptions() { + return [{ + label: "FAST", + value: MJSpeed.FAST + }, { + label: "RELAXED", + value: MJSpeed.RELAX + }] +} + +/** + * MJ的一些数据的定义 + */ +let MJDefine = { + GetMJRequestModelOptions, + GetMJRobotOptions, + GetMJRobotModelOptions, + GetMJImageScaleOptions, + GetMJAPIUrlOptions, + GetMJSpeedOptions +} + +export default MJDefine \ No newline at end of file diff --git a/src/main/Service/Options/index.ts b/src/main/Service/Options/index.ts index aae795d..f2eb151 100644 --- a/src/main/Service/Options/index.ts +++ b/src/main/Service/Options/index.ts @@ -13,7 +13,7 @@ class OptionHandle { * @param key 指定的Key的值 * @returns */ - GetOptionByKey = async (key: string) => await this.optionServices.GetOptionByKey(key) + GetOptionByKey = async (key: string | string[]) => await this.optionServices.GetOptionByKey(key) /** * 修改指定的Option,通过key,不存在则创建 diff --git a/src/main/Service/Options/optionServices.ts b/src/main/Service/Options/optionServices.ts index cea6a63..5574836 100644 --- a/src/main/Service/Options/optionServices.ts +++ b/src/main/Service/Options/optionServices.ts @@ -3,6 +3,7 @@ import { OptionKeyName, OptionType } from '@/define/enum/option' import { ValidateJson } from '@/define/Tools/validate' import { errorMessage, successMessage } from '@/main/Public/generalTools' import { ErrorItem, GeneralResponse, SuccessItem } from '@/model/generalResponse' +import { OptionModel } from '@/model/option/option' export class OptionServices { optionRealmService!: OptionRealmService constructor() { } @@ -19,10 +20,26 @@ export class OptionServices { * @param key * @returns */ - public async GetOptionByKey(key: string): Promise { + public async GetOptionByKey(key: string | string[]): Promise { try { await this.InitService() - let res = this.optionRealmService.GetOptionByKey(key) + let res: Array | OptionModel.OptionItem; + if (Array.isArray(key)) { + if (key.length <= 0) { + throw new Error('Key不能为空') + } + let temp = [] + for (let i = 0; i < key.length; i++) { + const element = key[i]; + let resItem = this.optionRealmService.GetOptionByKey(element) + if (resItem != null) { + temp.push(resItem) + } + } + res = temp; + } else { + res = this.optionRealmService.GetOptionByKey(key) + } return successMessage(res, '获取成功 OptionKey: ' + key, 'OptionOptions.GetOptionByKey') } catch (error: any) { return errorMessage( diff --git a/src/main/Service/ServiceBasic/softwareServiceBasic.ts b/src/main/Service/ServiceBasic/softwareServiceBasic.ts index 5bd4a1d..500f17b 100644 --- a/src/main/Service/ServiceBasic/softwareServiceBasic.ts +++ b/src/main/Service/ServiceBasic/softwareServiceBasic.ts @@ -1,6 +1,6 @@ import { SoftwareService } from '../../../define/db/service/SoftWare/softwareService'; import { MJSettingService } from '../../../define/db/service/SoftWare/mjSettingService'; -import { MJSetting } from '../../../model/Setting/mjSetting'; +import { MJSettingModel } from '../../../model/Setting/mjSetting'; export class SoftWareServiceBasic { @@ -85,7 +85,7 @@ export class SoftWareServiceBasic { * 获取MJ的设置信息 * @returns */ - async GetMjSetting(): Promise { + async GetMjSetting(): Promise { await this.InitService(); let mjSetting = this.mjSettingService.GetMjSetting({}) if (mjSetting.code == 1) { diff --git a/src/main/Service/task/taskManage.ts b/src/main/Service/task/taskManage.ts index f21018a..0bf0be2 100644 --- a/src/main/Service/task/taskManage.ts +++ b/src/main/Service/task/taskManage.ts @@ -12,7 +12,7 @@ import { D3Opt } from '../d3' import { FluxOpt } from '../Flux/flux' import { AsyncQueue } from '../../quene' import { SoftWareServiceBasic } from '../ServiceBasic/softwareServiceBasic' -import { MJSetting } from '../../../model/Setting/mjSetting' +import { MJSettingModel } from '../../../model/Setting/mjSetting' import { BookVideo } from '../Book/bookVideo' import { BookServiceBasic } from '../ServiceBasic/bookServiceBasic' import { TaskModal } from '@/model/task' @@ -32,7 +32,7 @@ export class TaskManager { bookServiceBasic: BookServiceBasic videoGlobal: VideoGlobal - mjSetting: MJSetting.MjSetting + mjSimpleSetting: MJSettingModel.MjSimpleSettingModel spaceTime: number = 5000; count = 0; isListening = false; @@ -65,7 +65,7 @@ export class TaskManager { } if (getMJsetting) { // 初始化MJ设置 - this.mjSetting = await this.softWareServiceBasic.GetMjSetting() + this.mjSimpleSetting = await this.softWareServiceBasic.GetMjSetting() } } @@ -141,8 +141,8 @@ export class TaskManager { if (element.type == BookBackTaskType.MJ_IMAGE || element.type == BookBackTaskType.MJ_REVERSE) { // 判断任务数量是不是又修改 let taskNumber = global.mjQueue.getConcurrencyLimit(); - if (taskNumber != this.mjSetting.taskCount) { - global.mjQueue.concurrencyLimit = this.mjSetting.taskCount // 重置并发执行的数量 + if (taskNumber != this.mjSimpleSetting.taskCount) { + global.mjQueue.concurrencyLimit = this.mjSimpleSetting.taskCount // 重置并发执行的数量 } if (global.mjQueue.getWaitingQueue() > 10) { diff --git a/src/main/Service/video/kling.ts b/src/main/Service/video/kling.ts index f42107e..2a62c88 100644 --- a/src/main/Service/video/kling.ts +++ b/src/main/Service/video/kling.ts @@ -7,11 +7,12 @@ import { cloneDeep, isEmpty } from "lodash"; import { GetBaseUrl } from "@/define/Tools/common"; import axios from "axios"; import { Book } from "@/model/book/book"; -import { c } from "naive-ui"; import { VideoStatus } from "@/define/enum/video"; import { SendMessageToRenderer } from "../globalService"; import { ResponseMessageType } from "@/define/enum/softwareEnum"; import { BookBackTaskStatus, BookTaskStatus } from "@/define/enum/bookEnum"; +import { define } from "@/define/define" +import ForwardResponse from "@/define/response/ForwardResponse"; export class KlingService { bookServiceBasic: BookServiceBasic @@ -25,7 +26,7 @@ export class KlingService { * @param gptUrl GPT地址 * @param gptApiKey GPTAPIKey */ - async KlingImageToVideo(task: TaskModal.Task, gptUrl: string, gptApiKey: string): Promise { + async KlingImageToVideo(task: TaskModal.Task, gptUrl: string, gptApiKey: string, useTransfer: boolean = false): Promise { try { let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(task.bookTaskDetailId); let klingOptionsString = bookTaskDetail.videoMessage.klingOptions; @@ -76,18 +77,41 @@ export class KlingService { if (klingOptions.hasOwnProperty("callback_url")) { data.callback_url = klingOptions.callback_url; } - // 开始请求 let baseUrl = GetBaseUrl(gptUrl); let url = baseUrl + "/kling/v1/videos/image2video"; - let res = await axios.post(url, data, { - headers: { - "Authorization": gptApiKey - } - }); - // console.log("kling合成视频结果", res); - let resData = res.data; + let resData: any = undefined; + if (useTransfer) { + let transferUrl = define.lms + "/lms/Forward/SimpleTransfer"; + let transferConfig = { + method: 'post', + url: transferUrl, + maxBodyLength: Infinity, + timeout: 600000, // 600 seconds timeout + headers: { + 'Content-Type': 'application/json' + }, + data: JSON.stringify({ + url: url, + apiKey: gptApiKey, + dataString: JSON.stringify(data) + }) + } + let response = await axios(transferConfig) + resData = ForwardResponse.GetForwardResponseData(response) + + } else { + let res = await axios.post(url, data, { + headers: { + "Authorization": gptApiKey + } + }); + + // console.log("kling合成视频结果", res); + resData = res.data; + } + let id = resData.data.task_id; // 修改数据 @@ -107,38 +131,60 @@ export class KlingService { data: JSON.stringify(resData) }, task.messageName); - await this.FetchKlingVideoResult(bookTaskDetail, task, resData.data.task_id, baseUrl, gptApiKey); + await this.FetchKlingVideoResult(bookTaskDetail, task, resData.data.task_id, baseUrl, gptApiKey, useTransfer); } catch (error) { throw new Error("可灵合成视频失败,失败信息如下:" + error.toString()); } } - async FetchKlingVideoResult(bookTaskDetail: Book.SelectBookTaskDetail, task: TaskModal.Task, taskId: string, baseUrl: string, gptApiKey: string) { + async FetchKlingVideoResult(bookTaskDetail: Book.SelectBookTaskDetail, task: TaskModal.Task, taskId: string, baseUrl: string, gptApiKey: string, useTransfer: boolean = false) { while (true) { try { let url = baseUrl + "/kling/v1/videos/image2video/" + taskId; - let res = await axios.get(url, { - headers: { - Authorization: gptApiKey + let resData: any = undefined; + if (useTransfer) { + let transferUrl = define.lms + "/lms/Forward/GetTransfer"; + let transferConfig = { + method: 'post', + url: transferUrl, + maxBodyLength: Infinity, + headers: { + 'Content-Type': 'application/json' + }, + data: JSON.stringify({ + url: url, + apiKey: gptApiKey, + }) } - }); - // console.log("kling合成视频结果", res.data); - let data = res.data.data; - if (data.task_status == "submitted") { + let res = await axios.request(transferConfig); + resData = ForwardResponse.GetForwardResponseData(res) + } else { + let res = await axios.get(url, { + headers: { + Authorization: gptApiKey + } + }); + resData = res.data; + } + if (!resData) { + throw new Error("获取可灵合成视频结果失败") + } + + if (resData.data.task_status == "submitted") { SendMessageToRenderer({ code: 1, id: bookTaskDetail.id, message: "可灵合成任务提交成功,正在合成中", type: ResponseMessageType.KLING_VIDEO, - data: JSON.stringify(data) + data: JSON.stringify(resData.data) }, task.messageName); - } else if (data.task_status == "processing") { + } else if (resData.data.task_status == "processing") { let videoMessage = cloneDeep(bookTaskDetail.videoMessage); delete videoMessage.id; videoMessage.status = VideoStatus.PROCESSING; videoMessage.taskId = taskId; - videoMessage.messageData = JSON.stringify(data); + videoMessage.messageData = JSON.stringify(resData.data); await this.bookServiceBasic.UpdateBookTaskDetailVideoMessage(task.bookTaskDetailId, videoMessage); SendMessageToRenderer({ @@ -146,16 +192,16 @@ export class KlingService { id: bookTaskDetail.id, message: "可灵合成任务正在合成中", type: ResponseMessageType.KLING_VIDEO, - data: JSON.stringify(data) + data: JSON.stringify(resData.data) }, task.messageName); - } else if (data.task_status == "succeed") { + } else if (resData.data.task_status == "succeed") { // 完成 let videoMessage = cloneDeep(bookTaskDetail.videoMessage); delete videoMessage.id; videoMessage.status = VideoStatus.SUCCESS; videoMessage.taskId = taskId; - videoMessage.videoUrl = data.task_result.videos[0].url; - videoMessage.messageData = JSON.stringify(data); + videoMessage.videoUrl = resData.data.task_result.videos[0].url; + videoMessage.messageData = JSON.stringify(resData.data); await this.bookServiceBasic.UpdateBookTaskDetailVideoMessage(task.bookTaskDetailId, videoMessage); await this.bookServiceBasic.UpdetedBookTaskData(task.bookTaskId, { status: BookTaskStatus.IMAGE_TO_VIDEO_SUCCESS, @@ -169,7 +215,7 @@ export class KlingService { id: bookTaskDetail.id, message: "可灵合成视频完成", type: ResponseMessageType.KLING_VIDEO, - data: JSON.stringify(data.data) + data: JSON.stringify(resData.data.data) }, task.messageName); break; } else { @@ -177,18 +223,18 @@ export class KlingService { let videoMessage = cloneDeep(bookTaskDetail.videoMessage); delete videoMessage.id; videoMessage.status = VideoStatus.FAIL; - videoMessage.msg = res.data.message; + videoMessage.msg = resData.message; videoMessage.taskId = taskId; - videoMessage.messageData = JSON.stringify(data); + videoMessage.messageData = JSON.stringify(resData.data); await this.bookServiceBasic.UpdateBookTaskDetailVideoMessage(bookTaskDetail.id, videoMessage); SendMessageToRenderer({ code: 0, id: bookTaskDetail.id, - message: "runway合成视频失败,错误信息如下:" + res.data.message, + message: "runway合成视频失败,错误信息如下:" + resData.data.message, type: ResponseMessageType.KLING_VIDEO, - data: JSON.stringify(data) + data: JSON.stringify(resData.data) }, task.messageName); - throw new Error("可灵合成视频失败,失败信息如下:" + res.data.message); + throw new Error("可灵合成视频失败,失败信息如下:" + resData.message); } // 等待20秒后再次请求 await new Promise(resolve => setTimeout(resolve, 20000)); diff --git a/src/main/Service/video/luma.ts b/src/main/Service/video/luma.ts index fc1742f..d8c872d 100644 --- a/src/main/Service/video/luma.ts +++ b/src/main/Service/video/luma.ts @@ -11,14 +11,25 @@ import { SendMessageToRenderer } from "../globalService"; import { ResponseMessageType } from "@/define/enum/softwareEnum"; import { Book } from "@/model/book/book"; import { BookBackTaskStatus, BookTaskStatus } from "@/define/enum/bookEnum"; +import { define } from "@/define/define" +import ForwardResponse from "@/define/response/ForwardResponse"; export class LumaService { bookServiceBasic: BookServiceBasic + requestModel: string constructor() { this.bookServiceBasic = new BookServiceBasic(); + this.requestModel = "fast" } - async LumaImageToVideo(task: TaskModal.Task, gptUrl: string, gptApiKey: string): Promise { + /** + * LUMA 合成视频 + * @param task + * @param gptUrl + * @param gptApiKey + * @param useTransfer + */ + async LumaImageToVideo(task: TaskModal.Task, gptUrl: string, gptApiKey: string, useTransfer: boolean = false): Promise { try { let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(task.bookTaskDetailId); let lumaOptionsString = bookTaskDetail.videoMessage.lumaOptions; @@ -27,6 +38,7 @@ export class LumaService { } let lumaOptions: BookTaskDetail.lumaOptions = JSON.parse(lumaOptionsString); // console.log("lumaOptions", lumaOptions, "gptUrl", gptUrl, "gptApiKey", gptApiKey); + this.requestModel = lumaOptions.request_model == null ? "fast" : lumaOptions.request_model; let data: BookTaskDetail.lumaOptions = { user_prompt: lumaOptions.user_prompt, @@ -59,16 +71,39 @@ export class LumaService { // 开始请求 let baseUrl = GetBaseUrl(gptUrl); let url = baseUrl + "/luma/generations"; - let res = await axios.post(url, data, { - headers: { - "Authorization": gptApiKey + if (this.requestModel == 'relax') { + url = baseUrl + "/luma-relax/luma/generations"; + } + + let returnData: any = undefined + // 是否国内转发 + if (useTransfer) { + + let transferUrl = define.lms + "/lms/Forward/SimpleTransfer"; + let transferConfig = { + method: 'post', + url: transferUrl, + maxBodyLength: Infinity, + timeout: 600000, // 600 seconds timeout + headers: { + 'Content-Type': 'application/json' + }, + data: JSON.stringify({ + url: url, + apiKey: gptApiKey, + dataString: JSON.stringify(data) + }) } - }); - - // console.log("luma合成视频结果", res); - - let returnData = res.data; - // console.log("luma合成视频结果", returnData); + let response = await axios(transferConfig) + returnData = ForwardResponse.GetForwardResponseData(response) + } else { + let res = await axios.post(url, data, { + headers: { + "Authorization": gptApiKey + } + }); + returnData = res.data; + } let id = returnData.id; // 修改数据 @@ -88,7 +123,7 @@ export class LumaService { data: JSON.stringify(returnData) }, task.messageName); - await this.FetchLumaVideoResult(bookTaskDetail, task, id, baseUrl, gptApiKey); + await this.FetchLumaVideoResult(bookTaskDetail, task, id, baseUrl, gptApiKey, useTransfer); } catch (error) { throw new Error("Luma合成视频失败,错误信息如下:" + error.toString()); } @@ -101,14 +136,38 @@ export class LumaService { * @param gptApiKey Key * @returns */ - async GetVideoUri(taskId: string, baseUrl: string, gptApiKey: string): Promise { + async GetVideoUri(taskId: string, baseUrl: string, gptApiKey: string, useTransfer: boolean = false): Promise { let url = baseUrl + "/luma/generations/" + taskId + "/download_video_url"; - let res = await axios.get(url, { - headers: { - Authorization: gptApiKey + + if (this.requestModel == "relax") { + url = baseUrl + "/luma-relax/luma/generations/" + taskId + "/download_video_url"; + } + + let resData: any = undefined; + if (useTransfer) { + let transferUrl = define.lms + "/lms/Forward/GetTransfer"; + let transferConfig = { + method: 'post', + url: transferUrl, + maxBodyLength: Infinity, + headers: { + 'Content-Type': 'application/json' + }, + data: JSON.stringify({ + url: url, + apiKey: gptApiKey, + }) } - }); - let resData = res.data; + let res = await axios.request(transferConfig); + resData = ForwardResponse.GetForwardResponseData(res) + } else { + let res = await axios.get(url, { + headers: { + Authorization: gptApiKey + } + }); + resData = res.data; + } // console.log("luma获取视频地址", resData); return resData.url; } @@ -121,24 +180,45 @@ export class LumaService { * @param baseUrl 请求的网址 * @param gptApiKey APIKey */ - async FetchLumaVideoResult(bookTaskDetail: Book.SelectBookTaskDetail, task: TaskModal.Task, taskId: string, baseUrl: string, gptApiKey: string) { + async FetchLumaVideoResult(bookTaskDetail: Book.SelectBookTaskDetail, task: TaskModal.Task, taskId: string, baseUrl: string, gptApiKey: string, useTransfer: boolean = false): Promise { while (true) { try { let url = baseUrl + "/luma/generations/" + taskId; - let res = await axios.get(url, { - headers: { - Authorization: gptApiKey + if (this.requestModel == 'relax') { + url = baseUrl + "/luma-relax/luma/generations/" + taskId; + } + + let resData: any = undefined + if (useTransfer) { + let transferUrl = define.lms + "/lms/Forward/GetTransfer"; + let transferConfig = { + method: 'post', + url: transferUrl, + maxBodyLength: Infinity, + headers: { + 'Content-Type': 'application/json' + }, + data: JSON.stringify({ + url: url, + apiKey: gptApiKey, + }) } - }); - // console.log("luma合成视频结果", res.data); - let resData = res.data; + let res = await axios.request(transferConfig); + resData = ForwardResponse.GetForwardResponseData(res) + } else { + let res = await axios.get(url, { + headers: { + Authorization: gptApiKey + } + }); + resData = res.data; + } if (resData.state == "completed") { let video_url = resData.video.download_url; if (isEmpty(video_url)) { // 完成 - let vr = await this.GetVideoUri(taskId, baseUrl, gptApiKey); - // console.log("luma合成视频结果", vr); + let vr = await this.GetVideoUri(taskId, baseUrl, gptApiKey, useTransfer); video_url = vr; } // 保存数据 diff --git a/src/main/Service/video/runway.ts b/src/main/Service/video/runway.ts index b3cf562..b5ec31a 100644 --- a/src/main/Service/video/runway.ts +++ b/src/main/Service/video/runway.ts @@ -11,6 +11,8 @@ import { SendMessageToRenderer } from "../globalService"; import { ResponseMessageType } from "@/define/enum/softwareEnum"; import { Book } from "@/model/book/book"; import { BookBackTaskStatus, BookTaskStatus } from "@/define/enum/bookEnum"; +import { define } from "@/define/define" +import ForwardResponse from "@/define/response/ForwardResponse"; export class RunwayService { bookServiceBasic: BookServiceBasic @@ -24,7 +26,7 @@ export class RunwayService { * @param gptUrl 调用地址 * @param gptApiKey Key */ - async ImageToVideo(task: TaskModal.Task, gptUrl: string, gptApiKey: string) { + async ImageToVideo(task: TaskModal.Task, gptUrl: string, gptApiKey: string, useTransfer: boolean = false) { try { let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(task.bookTaskDetailId); @@ -77,16 +79,42 @@ export class RunwayService { } // 开始请求 let baseUrl = GetBaseUrl(gptUrl); - let res = await axios.post(baseUrl + "/runway/pro/generate", data, { - headers: { - Authorization: gptApiKey + let url = baseUrl + "/runway/pro/generate" + + let resData: any = undefined + + if (useTransfer) { + + let transferUrl = define.lms + "/lms/Forward/SimpleTransfer"; + let transferConfig = { + method: 'post', + url: transferUrl, + maxBodyLength: Infinity, + timeout: 600000, // 600 seconds timeout + headers: { + 'Content-Type': 'application/json' + }, + data: JSON.stringify({ + url: url, + apiKey: gptApiKey, + dataString: JSON.stringify(data) + }) } - }); - // console.log("runway合成视频结果", res.data); - let resData = res.data; - if (resData.code != 200) { - throw new Error(res.data.msg); + let response = await axios(transferConfig) + resData = ForwardResponse.GetForwardResponseData(response) + } else { + let res = await axios.post(url, data, { + headers: { + Authorization: gptApiKey + } + }); + // console.log("runway合成视频结果", res.data); + resData = res.data; } + if (resData.code != 200) { + throw new Error(resData.msg); + } + // 修改数据 let videoMessage = cloneDeep(bookTaskDetail.videoMessage); videoMessage.taskId = resData.data.task_id; @@ -104,37 +132,62 @@ export class RunwayService { type: ResponseMessageType.RUNWAY_VIDEO, data: JSON.stringify(resData.data) }, task.messageName); - await this.FetchRunwayVideoResult(bookTaskDetail, task, resData.data.task_id, baseUrl, gptApiKey); + await this.FetchRunwayVideoResult(bookTaskDetail, task, resData.data.task_id, baseUrl, gptApiKey, useTransfer); } catch (error) { throw new Error("runway合成视频失败,错误信息如下:" + error.toString()); } } - async FetchRunwayVideoResult(bookTaskDetail: Book.SelectBookTaskDetail, task: TaskModal.Task, taskId: string, baseUrl: string, gptApiKey: string) { + async FetchRunwayVideoResult(bookTaskDetail: Book.SelectBookTaskDetail, task: TaskModal.Task, taskId: string, baseUrl: string, gptApiKey: string, useTransfer: boolean = false) { while (true) { try { let url = baseUrl + "/runway/feed"; - let res = await axios.post(url, { - "task_id": taskId - }, { - headers: { - Authorization: gptApiKey - } - }); - let data = res.data; - if (data.code != 200) { - throw new Error(data.msg); + let resData: any = undefined + + if (useTransfer) { + let transferUrl = define.lms + "/lms/Forward/SimpleTransfer"; + let transferConfig = { + method: 'post', + url: transferUrl, + maxBodyLength: Infinity, + timeout: 600000, // 600 seconds timeout + headers: { + 'Content-Type': 'application/json' + }, + data: JSON.stringify({ + url: url, + apiKey: gptApiKey, + dataString: JSON.stringify({ + "task_id": taskId + }) + }) + } + let response = await axios(transferConfig) + resData = ForwardResponse.GetForwardResponseData(response) + } else { + let res = await axios.post(url, { + "task_id": taskId + }, { + headers: { + Authorization: gptApiKey + } + }); + + resData = res.data; + } + if (resData.code != 200) { + throw new Error(resData.msg); } - if (data.data.status == '3') { + if (resData.data.status == '3') { // 完成 let videoMessage = cloneDeep(bookTaskDetail.videoMessage); delete videoMessage.id; videoMessage.status = VideoStatus.SUCCESS; videoMessage.taskId = taskId; - videoMessage.videoUrl = data.data.video_url; - videoMessage.messageData = JSON.stringify(data.data); + videoMessage.videoUrl = resData.data.video_url; + videoMessage.messageData = JSON.stringify(resData.data); await this.bookServiceBasic.UpdateBookTaskDetailVideoMessage(task.bookTaskDetailId, videoMessage); await this.bookServiceBasic.UpdetedBookTaskData(task.bookTaskId, { status: BookTaskStatus.IMAGE_TO_VIDEO_SUCCESS, @@ -149,37 +202,37 @@ export class RunwayService { id: bookTaskDetail.id, message: "runway合成视频完成", type: ResponseMessageType.RUNWAY_VIDEO, - data: JSON.stringify(data.data) + data: JSON.stringify(resData.data) }, task.messageName); break; - } else if (data.data.status == '1') { + } else if (resData.data.status == '1') { // 处理中 SendMessageToRenderer({ code: 1, id: bookTaskDetail.id, message: "runway合成视频处理中", type: ResponseMessageType.RUNWAY_VIDEO, - data: JSON.stringify(data.data) + data: JSON.stringify(resData.data) }, task.messageName); } else { // 没有完成 - if (data.data.status == '2') { + if (resData.data.status == '2') { // 有报错信息直接返回错误 let videoMessage = cloneDeep(bookTaskDetail.videoMessage); delete videoMessage.id; videoMessage.status = VideoStatus.FAIL; - videoMessage.msg = data.data.msg; + videoMessage.msg = resData.data.msg; videoMessage.taskId = taskId; - videoMessage.messageData = JSON.stringify(data.data); + videoMessage.messageData = JSON.stringify(resData.data); await this.bookServiceBasic.UpdateBookTaskDetailVideoMessage(bookTaskDetail.id, videoMessage); SendMessageToRenderer({ code: 0, id: bookTaskDetail.id, - message: "runway合成视频失败,错误信息如下:" + data.data.msg, + message: "runway合成视频失败,错误信息如下:" + resData.data.msg, type: ResponseMessageType.RUNWAY_VIDEO, - data: JSON.stringify(data.data) + data: JSON.stringify(resData.data) }, task.messageName); - throw new Error(data.data.msg); + throw new Error(resData.data.msg); } } // 等待20秒后再次请求 diff --git a/src/main/Service/video/videoGlobal.ts b/src/main/Service/video/videoGlobal.ts index c45c228..e3ff7c3 100644 --- a/src/main/Service/video/videoGlobal.ts +++ b/src/main/Service/video/videoGlobal.ts @@ -128,24 +128,24 @@ export class VideoGlobal { async ImageToVideo(task: TaskModal.Task): Promise { try { - let { gptUrl, gptApiKey } = await this.gptService.RefreshGptSetting(); + let { gptUrl, gptApiKey, useTransfer } = await this.gptService.RefreshGptSetting(); switch (task.type) { case BookBackTaskType.RUNWAY_VIDEO: - await this.runwayService.ImageToVideo(task, gptUrl, gptApiKey); + await this.runwayService.ImageToVideo(task, gptUrl, gptApiKey, useTransfer); break; case BookBackTaskType.LUMA_VIDEO: - await this.lumaService.LumaImageToVideo(task, gptUrl, gptApiKey); + await this.lumaService.LumaImageToVideo(task, gptUrl, gptApiKey, useTransfer); break; case BookBackTaskType.KLING_VIDEO: - await this.klingService.KlingImageToVideo(task, gptUrl, gptApiKey); + await this.klingService.KlingImageToVideo(task, gptUrl, gptApiKey, useTransfer); break; default: throw new Error("暂不支持的视频类型"); } - + // 执行完毕,开始下载视频 let bookTaskDetail = await this.bookServiceBasic.GetBookTaskDetailDataById(task.bookTaskDetailId); let book = await this.bookServiceBasic.GetBookDataById(task.bookId); diff --git a/src/main/func.js b/src/main/func.js index 98eaca2..90dbe93 100644 --- a/src/main/func.js +++ b/src/main/func.js @@ -16,7 +16,6 @@ import { PublicMethod } from './Public/publicMethod' import { ImageStyleDefine } from '../define/iamgeStyleDefine' let tools = new Tools() let pm = new PublicMethod(global) -import { FLxuAPIImageType } from '../define/enum/image' import JianyingService from './Service/jianying/jianyingService' import VideoHandle from './Service/videoService/videoHandle' import { successMessage } from './Public/generalTools' @@ -691,11 +690,13 @@ async function SaveSDConfig(value) { if (!sd_config.flux) { let model = { - model: value.flux_model ? value.flux_model : FLxuAPIImageType.FLUX + model: value.flux_model ? value.flux_model : 'flux', + useTransfer: value.useTransfer == null ? false : value.useTransfer } sd_config.flux = model } else { - sd_config.flux.model = value.flux_model ? value.flux_model : FLxuAPIImageType.FLUX + sd_config.flux.model = value.flux_model ? value.flux_model : sd_config.flux.model + sd_config.flux.useTransfer = value.useTransfer == null ? false : value.useTransfer } await fspromises.writeFile(define.sd_setting, JSON.stringify(sd_config)) diff --git a/src/main/setting/setting.js b/src/main/setting/setting.js index 188ef7b..5b0de18 100644 --- a/src/main/setting/setting.js +++ b/src/main/setting/setting.js @@ -11,7 +11,6 @@ import { TagDefine } from '../../define/tagDefine' import { errorMessage } from '../Public/generalTools' import { TaskManager } from '../Service/task/taskManage' import { SoftWareServiceBasic } from '../Service/ServiceBasic/softwareServiceBasic' -import { FLxuAPIImageType } from '../../define/enum/image' let tagDefine = new TagDefine(global) export class Setting { @@ -176,7 +175,9 @@ export class Setting { sd_model: sd_config.sd_model, lora: sd_config.lora, sampler: sd_config.sampler, - flux_model: sd_config.flux?.model ? sd_config.flux.model : FLxuAPIImageType.FLUX + flux_model: sd_config.flux?.model, + useTransfer: + sd_config.flux.useTransfer == undefined ? false : sd_config.flux.useTransfer } } } catch (error) { diff --git a/src/model/Setting/mjSetting.d.ts b/src/model/Setting/mjSetting.d.ts index 630bfaf..a43857a 100644 --- a/src/model/Setting/mjSetting.d.ts +++ b/src/model/Setting/mjSetting.d.ts @@ -1,7 +1,10 @@ -import { MJImageType, MJRobotType } from "../../define/enum/mjEnum" +import { MJImageType, MJRobotType, MJSpeed } from "../../define/enum/mjEnum" -declare namespace MJSetting { - type ActionRemoteMJSetting = { +declare namespace MJSettingModel { + /** + * 代理模式配置数据模型 + */ + type ActionRemoteMJSettingModel = { id?: string accountId?: string channelId?: string @@ -19,22 +22,10 @@ declare namespace MJSetting { updateTime?: Date } - - type BrowserMJ = { - id: string - serviceId: string - channelId: string - mjBotId: string - nijBotId: string - token: string - userAgent: string - userAgentCustom: boolean - createTime: Date - updateTime: Date - version: string - } - - type RemoteMJ = { + /** + * 代理模式配置数据模型 + */ + type RemoteMJSettingModel = { id: string accountId: string | null channelId: string @@ -49,23 +40,47 @@ declare namespace MJSetting { timeoutMinutes: number userAgent: string userToken: string - createTime: Date - updateTime: Date - version: string + createTime?: Date + updateTime?: Date + version?: string } - type APIMj = { + /** + * 浏览器模式配置数据模型 + */ + type BrowserMJSettingModel = { + id: string + serviceId: string + channelId: string + mjBotId: string + nijBotId: string + token: string + userAgent: string + userAgentCustom: boolean + createTime?: Date + updateTime?: Date + version?: string + } + + + /** + * MJ API 设置 + */ + type MJAPISettingModel = { id: string mjApiUrl: string - mjSpeed: string // MJ出图的速度模式 + mjSpeed: MJSpeed // MJ出图的速度模式 apiKey: string - createTime: Date - updateTime: Date - version: string + useTransfer: boolean // 是否国内转发 + createTime?: Date + updateTime?: Date + version?: string } - type MjSetting = { - id: string + /** + * MJ 基础设置 + */ + type MjSimpleSettingModel = { type: MJImageType requestModel: MJImageType selectRobot: MJRobotType @@ -74,11 +89,22 @@ declare namespace MJSetting { imageSuffix: string taskCount: number spaceTime: number - createTime: Date - updateTime: Date - version: string - apiSetting: APIMj - remoteSetting: RemoteMJ - browserSetting: BrowserMJ + } + + /** + * MJ 代理设置模型 + */ + type MJRemoteSimpleSettingModel = { + useTransfer: boolean // 是否国内转发 + } + + /** + * MJ 全局设置 + */ + type MJ_GlobalSettingModel = { + mj_simpleSetting: MjSimpleSettingModel + mj_apiSetting: MJAPISettingModel + mj_browserSetting: BrowserMJSettingModel + mj_remoteSimpleSetting: MJRemoteSimpleSettingModel } } diff --git a/src/model/book/bookTaskDetail.d.ts b/src/model/book/bookTaskDetail.d.ts index 30d1f0e..3bd3ef3 100644 --- a/src/model/book/bookTaskDetail.d.ts +++ b/src/model/book/bookTaskDetail.d.ts @@ -56,6 +56,7 @@ declare namespace BookTaskDetail { image_url?: string; // 图片地址(参考图,支持第三方图片地址、Base64) image_end_url?: string; // 尾帧图片地址(支持第三方图片地址、Base64) notify_hook?: string; // 回调地址 + request_model?: string; // 请求的模型,快速还是慢速 } type klingOptions = { diff --git a/src/model/option/option.d.ts b/src/model/option/option.d.ts index 9bf418d..d0ba7ef 100644 --- a/src/model/option/option.d.ts +++ b/src/model/option/option.d.ts @@ -1,3 +1,4 @@ +import { MJImageType, MJRobotType } from "@/define/enum/mjEnum" import { OptionType } from "@/define/enum/option" declare namespace OptionModel { diff --git a/src/preload/options.ts b/src/preload/options.ts index bc8f4af..7d06f25 100644 --- a/src/preload/options.ts +++ b/src/preload/options.ts @@ -4,7 +4,7 @@ import { OptionType } from '@/define/enum/option' const options = { /** 通过Key获取指定的option */ - GetOptionByKey: async (key: string) => + GetOptionByKey: async (key: string | string[]) => await ipcRenderer.invoke(DEFINE_STRING.OPTIONS.GET_OPTION_BY_KEY, key), /** diff --git a/src/renderer/src/common/SDFluxCommon.ts b/src/renderer/src/common/SDFluxCommon.ts new file mode 100644 index 0000000..f5603cb --- /dev/null +++ b/src/renderer/src/common/SDFluxCommon.ts @@ -0,0 +1,30 @@ +import { define } from "@/define/define" +import { OptionKeyName } from "@/define/enum/option"; +import { ValidateJson } from "@/define/Tools/validate"; +import axios from "axios"; +import { isEmpty } from "lodash"; +/** + * 远程的FLUX模型列表 + * @returns + */ +async function GetRemoteFluxModelList() { + debugger + let res = await axios.get(define.lms + `/lms/LaitoolOptions/GetSimpleOptions/LaitoolFluxApiModelList`); + if (res.data.code != 1) { + throw new Error(res.data.message) + } + let data = res.data.data.filter(item => item.key == "LaitoolFluxApiModelList") + if (data.length != 1) { + throw new Error("获取远程FLUX API模型列表失败") + } + if (isEmpty(data[0].value) || !ValidateJson(data[0].value)) { + throw new Error("FLUX API模型列表数据异常,请联系管理员!") + } + return JSON.parse(data[0].value) +} + +let SDFluxCommon = { + GetRemoteFluxModelList +} + +export default SDFluxCommon \ No newline at end of file diff --git a/src/renderer/src/common/initCommon.ts b/src/renderer/src/common/initCommon.ts index b27f34d..5bc6448 100644 --- a/src/renderer/src/common/initCommon.ts +++ b/src/renderer/src/common/initCommon.ts @@ -1,6 +1,7 @@ // @ts-nocheck import { OptionKeyName, OptionType } from '@/define/enum/option' import { useOptionStore } from '@/stores/option' +import SDFluxCommon from './SDFluxCommon' /** * 初始化特殊字符数据,用于文案的相关处理 @@ -90,8 +91,54 @@ async function InitTTSGlobalSetting() { } } +/** + * 初始化模型列表 + * @returns + */ +async function InitFluxModelList(isMust: boolean = false): Promise> { + debugger + let initData = [] + if (!isMust) { + let FLUX_APIModelListData = await window.options.GetOptionByKey(OptionKeyName.FLUX_APIModelList); + if (FLUX_APIModelListData.code == 0) { + window.api.showGlobalMessageDialog(FLUX_APIModelListData); + return initData; + } + if (FLUX_APIModelListData.data == null) { + initData = await SDFluxCommon.GetRemoteFluxModelList() + let saveRes = await window.options.ModifyOptionByKey( + OptionKeyName.FLUX_APIModelList, + JSON.stringify(initData), + OptionType.JOSN + ) + if (saveRes.code == 0) { + window.api.showGlobalMessageDialog(saveRes) + return initData + } else { + return initData + } + } else { + return JSON.parse(FLUX_APIModelListData.data.value) + } + } else { + initData = await SDFluxCommon.GetRemoteFluxModelList() + let saveRes = await window.options.ModifyOptionByKey( + OptionKeyName.FLUX_APIModelList, + JSON.stringify(initData), + OptionType.JOSN + ) + if (saveRes.code == 0) { + window.api.showGlobalMessageDialog(saveRes) + return initData + } else { + return initData + } + } +} + let InitCommon = { InitSpecialCharacters, - InitTTSGlobalSetting + InitTTSGlobalSetting, + InitFluxModelList } export default InitCommon diff --git a/src/renderer/src/components/Book/Components/Video/GenerateVideoDialog.vue b/src/renderer/src/components/Book/Components/Video/GenerateVideoDialog.vue index cae464e..c050afe 100644 --- a/src/renderer/src/components/Book/Components/Video/GenerateVideoDialog.vue +++ b/src/renderer/src/components/Book/Components/Video/GenerateVideoDialog.vue @@ -95,6 +95,8 @@ async function GetBookTaskDetailOption() { } if (ValidateJson(videoMessage.value.lumaOptions)) { lumaOptions.value = JSON.parse(videoMessage.value.lumaOptions) + lumaOptions.value.request_model = + lumaOptions.value.request_model == null ? 'fast' : lumaOptions.value.request_model lumaOptions.value.image_url = videoMessage.value.imageUrl } if (ValidateJson(videoMessage.value.klingOptions)) { diff --git a/src/renderer/src/components/Book/Components/Video/LumaOption.vue b/src/renderer/src/components/Book/Components/Video/LumaOption.vue index 6f9b42a..7b40127 100644 --- a/src/renderer/src/components/Book/Components/Video/LumaOption.vue +++ b/src/renderer/src/components/Book/Components/Video/LumaOption.vue @@ -30,6 +30,16 @@ + + + @@ -37,7 +47,7 @@ diff --git a/src/renderer/src/components/Setting/MJSetting/MJAPISetting.vue b/src/renderer/src/components/Setting/MJSetting/MJAPISetting.vue new file mode 100644 index 0000000..c7d1d70 --- /dev/null +++ b/src/renderer/src/components/Setting/MJSetting/MJAPISetting.vue @@ -0,0 +1,95 @@ + + + diff --git a/src/renderer/src/components/Setting/MJSetting/MJBrowserSetting.vue b/src/renderer/src/components/Setting/MJSetting/MJBrowserSetting.vue new file mode 100644 index 0000000..9f0d13e --- /dev/null +++ b/src/renderer/src/components/Setting/MJSetting/MJBrowserSetting.vue @@ -0,0 +1,70 @@ + + + diff --git a/src/renderer/src/components/Setting/MJSetting/MJRemoteSetting.vue b/src/renderer/src/components/Setting/MJSetting/MJRemoteSetting.vue new file mode 100644 index 0000000..40747ac --- /dev/null +++ b/src/renderer/src/components/Setting/MJSetting/MJRemoteSetting.vue @@ -0,0 +1,48 @@ + + + diff --git a/src/renderer/src/components/Setting/MJSetting/MJSettingHome.vue b/src/renderer/src/components/Setting/MJSetting/MJSettingHome.vue new file mode 100644 index 0000000..cb2ac67 --- /dev/null +++ b/src/renderer/src/components/Setting/MJSetting/MJSettingHome.vue @@ -0,0 +1,147 @@ + + + diff --git a/src/renderer/src/components/Setting/MJSetting/MJSimpleSetting.vue b/src/renderer/src/components/Setting/MJSetting/MJSimpleSetting.vue new file mode 100644 index 0000000..f141934 --- /dev/null +++ b/src/renderer/src/components/Setting/MJSetting/MJSimpleSetting.vue @@ -0,0 +1,141 @@ + + + diff --git a/src/renderer/src/components/Setting/SDSetting.vue b/src/renderer/src/components/Setting/SDSetting.vue index 491b873..a4b64d3 100644 --- a/src/renderer/src/components/Setting/SDSetting.vue +++ b/src/renderer/src/components/Setting/SDSetting.vue @@ -111,18 +111,41 @@ placeholder="输入迭代步数" /> - - + - - + + + 加载数据 + + + + + + + +
注意:使用国内转发可能会出现服务器超时错误,错误码504
+
+ 保存设置 @@ -134,7 +157,7 @@ - diff --git a/src/renderer/src/components/TTS/EdgeTTS.vue b/src/renderer/src/components/TTS/EdgeTTS.vue index a7491ba..cdb7606 100644 --- a/src/renderer/src/components/TTS/EdgeTTS.vue +++ b/src/renderer/src/components/TTS/EdgeTTS.vue @@ -52,6 +52,7 @@ import { useOptionStore } from '@/stores/option' let message = useMessage() let optionStore = useOptionStore() +let roleOptions = ref([]) async function SwitchTTSOptions(key) { console.log('SwitchTTSOptions', key) @@ -65,7 +66,6 @@ async function SwitchTTSOptions(key) { console.log('SwitchTTSOptions', roleOptions.value) } -let roleOptions = ref([]) onMounted(async () => { // 获取配音角色列表 await SwitchTTSOptions('edge-tts') diff --git a/src/renderer/src/components/TTS/TTSHome.vue b/src/renderer/src/components/TTS/TTSHome.vue index 0c108c5..8df6cb8 100644 --- a/src/renderer/src/components/TTS/TTSHome.vue +++ b/src/renderer/src/components/TTS/TTSHome.vue @@ -14,7 +14,7 @@ diff --git a/src/renderer/src/main.js b/src/renderer/src/main.js index 2477472..f11e49f 100644 --- a/src/renderer/src/main.js +++ b/src/renderer/src/main.js @@ -86,7 +86,7 @@ const routes = [ { path: '/mj_setting', name: 'mj_setting', - component: () => import('./components/Setting/MJSetting.vue') + component: () => import('./components/Setting/MJSetting/MJSettingHome.vue') }, { path: '/video_setting', diff --git a/src/stores/option.ts b/src/stores/option.ts index 372f2c1..055dd01 100644 --- a/src/stores/option.ts +++ b/src/stores/option.ts @@ -1,9 +1,12 @@ +import { MJImageType, MJRobotType, MJSpeed } from "@/define/enum/mjEnum"; import { OptionKeyName } from "@/define/enum/option"; import { OptionModel } from "@/model/option/option"; +import { MJSettingModel } from "@/model/Setting/mjSetting"; import { defineStore } from "pinia"; export type OptionStoreModel = { - //#region + + //#region 文案处理 /** 文案处理 AI设置 */ [OptionKeyName.CW_AISetting]: { @@ -23,6 +26,11 @@ export type OptionStoreModel = { [OptionKeyName.TTS_GlobalSetting]: OptionModel.TTS_GlobalSettingModel | undefined; //#endregion + + //#region MJ + /** MJ 基础设置 */ + [OptionKeyName.MJ_GlobalSetting]: MJSettingModel.MJ_GlobalSettingModel; + //#endregion } export const useOptionStore = defineStore('option', { @@ -64,6 +72,38 @@ export const useOptionStore = defineStore('option', { ttsText: "你好,我是你的智能语音助手!", /** 保存的音频文件路径 */ saveAudioPath: undefined, + }, + [OptionKeyName.MJ_GlobalSetting]: { + mj_simpleSetting: { + type: MJImageType.API_MJ, + requestModel: MJImageType.API_MJ, + selectRobot: MJRobotType.MJ, + imageScale: "3e2772f2-041c-49c6-ba13-d0ed120310b8", + imageModel: "3e6473ab-9a64-4574-9a38-f5c75af552b6", + imageSuffix: " --niji 6 --ar 1:1", + taskCount: 3, + spaceTime: 10 + }, + mj_apiSetting: { + id: "6db0d484-2a41-4545-8b26-ed32812965ad", + mjApiUrl: "b44c6f24-59e4-4a71-b2c7-3df0c4e35e65", + mjSpeed: MJSpeed.RELAX, + apiKey: "LAI API的令牌", + useTransfer: false + }, + mj_browserSetting: { + id: "4d5d57f2-1d7a-4e0f-b347-a7283e75d64a", + serviceId: "自己的服务器ID", + channelId: "自己的频道ID", + mjBotId: "自己的MJ机器人ID", + nijBotId: "自己的NIJI机器人ID", + token: "自己的令牌", + userAgent: "自己的UserAgent", + userAgentCustom: false, + }, + mj_remoteSimpleSetting: { + useTransfer: false + } } } as unknown as OptionStoreModel), diff --git a/src/stores/setting.ts b/src/stores/setting.ts index f8e228f..70cdb9e 100644 --- a/src/stores/setting.ts +++ b/src/stores/setting.ts @@ -1,5 +1,5 @@ import { defineStore } from 'pinia' -import { MJSetting } from '../model/Setting/mjSetting' +import { MJSettingModel } from '../model/Setting/mjSetting' // 系统相关设置 export const useSettingStore = defineStore('setting', { @@ -21,7 +21,7 @@ export const useSettingStore = defineStore('setting', { userToken: undefined, createTime: undefined, updateTime: undefined - } as MJSetting.ActionRemoteMJSetting, + } as MJSettingModel.ActionRemoteMJSettingModel, // tts 配置 ttsSetting: { selectModel: 'edge-tts', @@ -37,7 +37,7 @@ export const useSettingStore = defineStore('setting', { }, } as TTSSettingModel.TTSSetting , - ttsRoles: [] + ttsRoles: [] }), getters: {}, actions: { @@ -62,7 +62,7 @@ export const useSettingStore = defineStore('setting', { userToken: undefined, createTime: undefined, updateTime: undefined - } as MJSetting.ActionRemoteMJSetting + } as MJSettingModel.ActionRemoteMJSettingModel } } })