Initial commit 添加MJ功能
This commit is contained in:
@@ -0,0 +1,448 @@
|
||||
import axios from "axios";
|
||||
import path from "path";
|
||||
import { DEFINE_STRING } from "../../define/define_string";
|
||||
import { define } from "../../define/define";
|
||||
let fspromises = require("fs").promises;
|
||||
import { gptDefine } from "../../define/gptDefine";
|
||||
|
||||
export class GPT {
|
||||
constructor(global) {
|
||||
this.global = global;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 输出测试案例
|
||||
* @param {*} value 传入的值(整个数据)
|
||||
*/
|
||||
async GenerateGptExampleOut(value) {
|
||||
try {
|
||||
|
||||
let data = JSON.parse(value);
|
||||
let message = gptDefine.CustomizeGptPrompt(data);
|
||||
let content = await this.FetchGpt(message);
|
||||
console.log(content);
|
||||
return {
|
||||
code: 1,
|
||||
data: content
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GPT推理提示词的方法
|
||||
* @param {*} element 当前推理的句子
|
||||
* @param {*} gpt_count 设置的GPT上下文理解数量
|
||||
* @param {*} auto_analyze_character 当前的角色数据
|
||||
* @returns
|
||||
*/
|
||||
async GPTPromptGenerate(element, gpt_count, auto_analyze_character) {
|
||||
try {
|
||||
// 获取当前的推理模式
|
||||
let gpt_auto_inference = this.global.config.gpt_auto_inference;
|
||||
let message = null;
|
||||
if (gpt_auto_inference == "customize") {
|
||||
// 自定义模式
|
||||
// 获取当前自定义的推理提示词
|
||||
let customize_gpt_prompt = (await gptDefine.getGptDataByTypeAndProperty("dynamic", "customize_gpt_prompt", [])).data;
|
||||
let index = customize_gpt_prompt.findIndex(item => item.id == this.global.config.customize_gpt_prompt);
|
||||
if (this.global.config.customize_gpt_prompt && index < 0) {
|
||||
throw new Error("自定义推理默认要选择对应的自定义推理词");
|
||||
}
|
||||
message = gptDefine.CustomizeGptPrompt(customize_gpt_prompt[index], element.after_gpt);
|
||||
message.push({
|
||||
"role": "user",
|
||||
"content": element.after_gpt
|
||||
})
|
||||
} else {
|
||||
// 内置模式
|
||||
// 获取
|
||||
let prefix_word = "";
|
||||
// 拼接一个word
|
||||
let i = element.no - 1;
|
||||
if (i <= gpt_count) {
|
||||
prefix_word = this.all_data.filter((item, index) => index < i).map(item => item.after_gpt).join('\r\n');
|
||||
} else if (i > gpt_count) {
|
||||
prefix_word = this.all_data.filter((item, index) => i - index <= gpt_count && i - index > 0).map(item => item.after_gpt).join('\r\n');
|
||||
}
|
||||
|
||||
let suffix_word = "";
|
||||
let o_i = this.all_data.length - i;
|
||||
if (o_i <= gpt_count) {
|
||||
suffix_word = this.all_data.filter((item, index) => index > i).map(item => item.after_gpt).join('\r\n');
|
||||
} else if (o_i > gpt_count) {
|
||||
suffix_word = this.all_data.filter((item, index) => index - i <= gpt_count && index - i > 0).map(item => item.after_gpt).join('\r\n');
|
||||
}
|
||||
|
||||
let word = `${prefix_word}\r\n${element.after_gpt}\r\n${suffix_word}`;
|
||||
let single_word = element.after_gpt;
|
||||
|
||||
// 判断当前的格式
|
||||
if (["superSinglePrompt", 'onlyPromptMJ'].includes(this.global.config.gpt_auto_inference)) {
|
||||
// 有返回案例的
|
||||
message = gptDefine.GetExamplePromptMessage(this.global.config.gpt_auto_inference);
|
||||
// 加当前提问的
|
||||
message.push({
|
||||
"role": "user",
|
||||
"content": single_word
|
||||
})
|
||||
|
||||
} else {
|
||||
// 直接返回,没有案例的
|
||||
message = [
|
||||
{
|
||||
"role": "system",
|
||||
"content": gptDefine.getSystemContentByType(this.global.config.gpt_auto_inference, {
|
||||
textContent: word,
|
||||
characterContent: auto_analyze_character
|
||||
})
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": gptDefine.getUserContentByType(this.global.config.gpt_auto_inference, {
|
||||
textContent: single_word,
|
||||
wordCount: this.global.config.gpt_model && this.global.config.gpt_model.includes("gpt-4") ? '20' : '40'
|
||||
})
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
let res = await this.FetchGpt(message);
|
||||
return res;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将推理提示词添加到任务
|
||||
*/
|
||||
async GPTPrompt(data) {
|
||||
try {
|
||||
console.log(data)
|
||||
let value = JSON.parse(data[0]);
|
||||
let show_global_message = data[1];
|
||||
this.all_data = JSON.parse(data[2]);
|
||||
// 获取data中的after_gpt,然后使用换行符拼接成一个字符串
|
||||
// let word = value.map(item => item.after_gpt).join('\r\n');
|
||||
let batch = DEFINE_STRING.QUEUE_BATCH.SD_ORIGINAL_GPT_PROMPT;
|
||||
|
||||
// 获取人物角色数据
|
||||
let config_json = JSON.parse(await fspromises.readFile(path.join(this.global.config.project_path, "scripts/config.json"), 'utf-8'));
|
||||
let auto_analyze_character = config_json.auto_analyze_character;
|
||||
let gpt_count = this.global.config.gpt_count ? this.global.config.gpt_count : 10;
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
const element = value[i];
|
||||
this.global.requestQuene.enqueue(async () => {
|
||||
try {
|
||||
|
||||
let content = await this.GPTPromptGenerate(element, gpt_count, auto_analyze_character);
|
||||
|
||||
if (content) {
|
||||
content = content.replace(/\)\s*\(/g, ", ").replace(/^\(/, "").replace(/\)$/, "")
|
||||
}
|
||||
// 获取对应的数据,将数据返回前端事件
|
||||
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.GPT_GENERATE_PROMPT_RETURN, {
|
||||
id: element.id,
|
||||
gpt_prompt: content
|
||||
})
|
||||
|
||||
this.global.fileQueue.enqueue(async () => {
|
||||
// 将推理出来的数据写入执行的文件中
|
||||
let json_config = JSON.parse(await fspromises.readFile(element.prompt_json, 'utf-8'));
|
||||
// 写入
|
||||
json_config.gpt_prompt = content;
|
||||
await fspromises.writeFile(element.prompt_json, JSON.stringify(json_config));
|
||||
})
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}, `${batch}_${element.id}`, batch);
|
||||
}
|
||||
|
||||
this.global.requestQuene.setBatchCompletionCallback(batch, (failedTasks) => {
|
||||
if (failedTasks.length > 0) {
|
||||
let message = `
|
||||
推理提示词任务都已完成。
|
||||
但是以下任务执行失败:
|
||||
`
|
||||
failedTasks.forEach(({ taskId, error }) => {
|
||||
message += `${taskId}-, \n 错误信息: ${error}` + '\n';
|
||||
});
|
||||
|
||||
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
|
||||
code: 0,
|
||||
message: message
|
||||
})
|
||||
} else {
|
||||
if (show_global_message) {
|
||||
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
|
||||
code: 1,
|
||||
message: "所有推理任务完成"
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
code: 1,
|
||||
}
|
||||
|
||||
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改请求的参数
|
||||
* @param {*} data
|
||||
* @returns
|
||||
*/
|
||||
ModifyData(gpt_url, data) {
|
||||
let res = data;
|
||||
if (gpt_url.includes("dashscope.aliyuncs.com")) {
|
||||
res = {
|
||||
"model": data.model,
|
||||
"input": {
|
||||
"messages": data.messages,
|
||||
},
|
||||
"parameters": {
|
||||
"result_format": "message"
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取返回的内容
|
||||
* @param {*} gpt_url GPT请求的内容
|
||||
* @param {*} res 请求返回的数据
|
||||
* @returns
|
||||
*/
|
||||
GetResponseContent(gpt_url, res) {
|
||||
let content = "";
|
||||
if (gpt_url.includes("dashscope.aliyuncs.com")) {
|
||||
content = res.data.output.choices[0].message.content;
|
||||
} else {
|
||||
|
||||
content = res.data.choices[0].message.content;
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送GPT请求
|
||||
* @param {*} message 请求的信息
|
||||
* @param {*} gpt_url gpt的url,默认在global中取
|
||||
* @param {*} gpt_key gpt的key,默认在global中取
|
||||
* @param {*} gpt_model gpt的model,默认在global中取
|
||||
* @returns
|
||||
*/
|
||||
async FetchGpt(message,
|
||||
gpt_url = this.global.config.gpt_business,
|
||||
gpt_key = this.global.config.gpt_key,
|
||||
gpt_model = this.global.config.gpt_model) {
|
||||
try {
|
||||
|
||||
let data = {
|
||||
"model": gpt_model,
|
||||
"messages": message
|
||||
};
|
||||
|
||||
data = this.ModifyData(gpt_url, data);
|
||||
let config = {
|
||||
method: 'post',
|
||||
maxBodyLength: Infinity,
|
||||
url: gpt_url,
|
||||
headers: {
|
||||
'Authorization': `Bearer ${gpt_key}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify(data)
|
||||
};
|
||||
|
||||
let res = await axios.request(config);
|
||||
let content = this.GetResponseContent(gpt_url, res);
|
||||
return content;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动分析文本,返回人物场景。角色。
|
||||
* @param {要分析的文本} value
|
||||
* @returns
|
||||
*/
|
||||
async AutoAnalyzeCharacter(value) {
|
||||
try {
|
||||
let message = [
|
||||
{
|
||||
"role": "system",
|
||||
"content": gptDefine.getSystemContentByType("character", { textContent: value })
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": gptDefine.getUserContentByType("character", {})
|
||||
}
|
||||
]
|
||||
let content = await this.FetchGpt(message);
|
||||
|
||||
return {
|
||||
code: 1,
|
||||
data: content
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取GPT的服务商配置,默认的和自定义的
|
||||
* @returns
|
||||
*/
|
||||
async GetGPTBusinessOption(value) {
|
||||
return await gptDefine.getGptDataByTypeAndProperty(value, "gpt_options", []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取GPT的模型配置,默认的和自定义的
|
||||
* @returns
|
||||
*/
|
||||
async GetGPTModelOption(value) {
|
||||
return await gptDefine.getGptDataByTypeAndProperty(value, "gpt_model_options", []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取GPT的自动推理模式配置,默认的和自定义的
|
||||
* @returns
|
||||
*/
|
||||
async GetGptAutoInferenceOptions(value) {
|
||||
return await gptDefine.getGptDataByTypeAndProperty(value, "gpt_auto_inference", []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取GPT的自动推理模式配置,默认的和自定义的
|
||||
* @returns
|
||||
*/
|
||||
async GetCustomizeGptPrompt(value) {
|
||||
return await gptDefine.getGptDataByTypeAndProperty(value, "customize_gpt_prompt", []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存自定义的GPT服务商配置
|
||||
* @param {*} value 配置信息 0 : 传入的数据 1: 属性名称
|
||||
* @returns
|
||||
*/
|
||||
async SaveDynamicGPTOption(value) {
|
||||
try {
|
||||
let res = await gptDefine.saveDynamicGPTOption(value);
|
||||
return {
|
||||
code: 1,
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定Id的自定义GPT服务商配置
|
||||
* @param {*} value id 0 : 删除的数据 1: 属性名称
|
||||
* @returns
|
||||
*/
|
||||
async DeleteDynamicGPTOption(value) {
|
||||
try {
|
||||
let res = await gptDefine.deleteDynamicGPTOption(value);
|
||||
return {
|
||||
code: 1,
|
||||
data: res
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Stirng} value 传入的GPT网址和key,判断是不是可以链接成功
|
||||
*/
|
||||
async TestGPTConnection(value) {
|
||||
try {
|
||||
value = JSON.parse(value);
|
||||
let message = [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "你好"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "你好"
|
||||
}
|
||||
];
|
||||
|
||||
let content = await this.FetchGpt(message, value.gpt_business, value.gpt_key, value.gpt_model);
|
||||
return {
|
||||
code: 1,
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 单句洗稿
|
||||
* @param {文案参数} value
|
||||
*/
|
||||
async AIModifyOneWord(value) {
|
||||
try {
|
||||
|
||||
let message = [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": `请您扮演一个抖音网文改写专家,我会给你一句文案,请你不要改变文案的结构,不改变原来的意思,仅对文案进行同义转换改写,不要有奇怪的写法,说法通俗一点,不要其他的标点符号,每一小句话之间都是以句号连接,参考抖音网文解说,以下是文案:${value[1]}。`
|
||||
}
|
||||
]
|
||||
let content = await this.FetchGpt(message);
|
||||
|
||||
return {
|
||||
code: 1,
|
||||
data: { no: value[0], content: content }
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
import axios from "axios";
|
||||
import path from "path";
|
||||
import { DEFINE_STRING } from "../../define/define_string";
|
||||
import { define } from "../../define/define";
|
||||
import { ImageStyleDefine } from "../../define/iamgeStyleDefine";
|
||||
import { cloneDeep } from 'lodash';
|
||||
let fspromises = require("fs").promises;
|
||||
const sharp = require('sharp');
|
||||
// const {
|
||||
// createCanvas,
|
||||
// loadImage
|
||||
// } = require('canvas');
|
||||
import { SdSettingDefine } from "../../define/setting/sdSettingDefine";
|
||||
import { PublicMethod } from "./publicMethod";
|
||||
import { Tools } from "../tools";
|
||||
|
||||
export class SD {
|
||||
constructor(global) {
|
||||
this.global = global;
|
||||
this.pm = new PublicMethod(global);
|
||||
this.tools = new Tools();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图片风格菜单
|
||||
* @returns 返回图片风格菜单
|
||||
*
|
||||
* */
|
||||
async GetImageStyleMenu() {
|
||||
try {
|
||||
let style = ImageStyleDefine.getImageStyleMenu();
|
||||
return {
|
||||
code: 1,
|
||||
data: style
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定的ID的风格信息,传入的是一个数组
|
||||
* @param {*} value id集合
|
||||
*/
|
||||
async GetImageStyleInfomation(value) {
|
||||
try {
|
||||
if (value) {
|
||||
value = JSON.parse(value);
|
||||
} else {
|
||||
value = [];
|
||||
}
|
||||
value = value ? value : [];
|
||||
let style = ImageStyleDefine.getAllSubStyle();
|
||||
let tmp = [];
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
const element = value[i];
|
||||
for (let j = 0; j < style.length; j++) {
|
||||
const item = style[j];
|
||||
if (item.id == element) {
|
||||
tmp.push(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
let newSubStyle = cloneDeep(tmp);
|
||||
for (let i = 0; i < newSubStyle.length; i++) {
|
||||
const element = newSubStyle[i];
|
||||
element.image = path.join(define.image_path, "style/" + element.image);
|
||||
}
|
||||
return {
|
||||
code: 1,
|
||||
data: newSubStyle
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定ID的分类的子风格信息
|
||||
* @param {*} value ID
|
||||
* @returns 返回ID对应的子风格的详细信息
|
||||
*/
|
||||
async GetStyleImageSubList(value) {
|
||||
try {
|
||||
let subStyle = ImageStyleDefine.getImagePathById(value);
|
||||
let newSubStyle = cloneDeep(subStyle);
|
||||
for (let i = 0; i < newSubStyle.length; i++) {
|
||||
const element = newSubStyle[i];
|
||||
element.image = path.join(define.image_path, "style/" + element.image);
|
||||
}
|
||||
return {
|
||||
code: 1,
|
||||
data: newSubStyle
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成一次图片的方法。可以区分模式
|
||||
* @param {图片名称 } image
|
||||
* @param {任务队列信息} task_list 301198499
|
||||
*/
|
||||
async OneImageGeneration(image, task_list, seed = -1) {
|
||||
let taskPath = path.join(this.global.config.project_path, "scripts/task_list.json")
|
||||
try {
|
||||
let imageJson = JSON.parse(await fspromises.readFile(image + '.json', 'utf-8'));
|
||||
let sd_setting = JSON.parse(await fspromises.readFile(define.sd_setting, 'utf-8'));
|
||||
let model = imageJson.model;
|
||||
let image_json = JSON.parse(await fspromises.readFile(image + '.json', 'utf-8'));
|
||||
let image_path = "";
|
||||
let target_image_path = "";
|
||||
|
||||
if (image_json.name) {
|
||||
image_path = path.join(this.global.config.project_path, `tmp/${task_list.out_folder}/tmp_${image_json.name}`)
|
||||
target_image_path = path.join(this.global.config.project_path, `tmp/${task_list.out_folder}/${image_json.name}`)
|
||||
} else {
|
||||
image_path = image.replaceAll("input_crop", task_list.out_folder).split(".png")[0] + "_tmp.png";
|
||||
target_image_path = image.replaceAll("input_crop", task_list.out_folder);
|
||||
}
|
||||
|
||||
// let prompt = "";
|
||||
// // 拼接提示词
|
||||
// if (task_list.image_style != null) {
|
||||
// prompt += `((${task_list.image_style})),`;
|
||||
// }
|
||||
// if (task_list.lora != null) {
|
||||
// prompt += `${task_list.lora},`;
|
||||
// }
|
||||
// let image_styles = await ImageStyleDefine.getImageStyleStringByIds(task_list.image_style_list ? task_list.image_style_list : []);
|
||||
|
||||
// prompt = `${prompt}, ${image_styles}, ${imageJson.webui_config.prompt}`;
|
||||
let prompt = imageJson.webui_config.prompt;
|
||||
|
||||
// 判断当前是不是有开修脸修手
|
||||
let ADetailer = {
|
||||
args: sd_setting.adetailer
|
||||
};
|
||||
|
||||
if (model == "img2img") {
|
||||
let web_api = this.global.config.webui_api_url + 'sdapi/v1/img2img'
|
||||
let sd_config = imageJson["webui_config"];
|
||||
sd_config.prompt = prompt;
|
||||
sd_config.seed = seed;
|
||||
let im = await fspromises.readFile(image, 'binary');
|
||||
sd_config.init_images = [new Buffer.from(im, 'binary').toString('base64')];
|
||||
|
||||
if (imageJson.adetailer) {
|
||||
let ta = {
|
||||
ADetailer: ADetailer
|
||||
}
|
||||
sd_config.alwayson_scripts = ta;
|
||||
}
|
||||
sd_config.height = sd_setting.webui.height;
|
||||
sd_config.width = sd_setting.webui.width;
|
||||
|
||||
const response = await axios.post(web_api, sd_config);
|
||||
let info = JSON.parse(response.data.info);
|
||||
if (seed == -1) {
|
||||
seed = info.seed;
|
||||
}
|
||||
|
||||
// 目前是单图出图
|
||||
let images = response.data.images;
|
||||
let imageData = Buffer.from(images[0].split(",", 1)[0], 'base64');
|
||||
await sharp(imageData)
|
||||
.toFile(image_path)
|
||||
.then(async () => {
|
||||
// console.log("图生图成功" + image_path);
|
||||
await this.tools.deletePngAndDeleteExifData(image_path, target_image_path);
|
||||
})
|
||||
.catch(err => {
|
||||
throw new Error(err);
|
||||
});
|
||||
return seed;
|
||||
|
||||
} else if (model == "txt2img") {
|
||||
let body = {
|
||||
"prompt": prompt,
|
||||
"negative_prompt": imageJson.webui_config.negative_prompt,
|
||||
"seed": seed,
|
||||
"sampler_name": imageJson.webui_config.sampler_name,
|
||||
// 提示词相关性
|
||||
"cfg_scale": imageJson.webui_config.cfg_scale,
|
||||
"width": sd_setting.webui.width,
|
||||
"height": sd_setting.webui.height,
|
||||
"batch_size": 1,
|
||||
"n_iter": 1,
|
||||
"steps": imageJson.webui_config.steps,
|
||||
"save_images": false,
|
||||
}
|
||||
let web_api = this.global.config.webui_api_url + 'sdapi/v1/txt2img';
|
||||
|
||||
if (imageJson.adetailer) {
|
||||
let ta = {
|
||||
ADetailer: ADetailer
|
||||
}
|
||||
body.alwayson_scripts = ta;
|
||||
}
|
||||
const response = await axios.post(web_api, body);
|
||||
let info = JSON.parse(response.data.info);
|
||||
if (seed == -1) {
|
||||
seed = info.seed;
|
||||
}
|
||||
// 目前是单图出图
|
||||
let images = response.data.images;
|
||||
let imageData = Buffer.from(images[0].split(",", 1)[0], 'base64');
|
||||
await sharp(imageData)
|
||||
.toFile(image_path)
|
||||
.then(async () => {
|
||||
// console.log("文生图成功" + image_path);
|
||||
await this.tools.deletePngAndDeleteExifData(image_path, target_image_path);
|
||||
})
|
||||
.catch(err => {
|
||||
// console.log(err)
|
||||
throw new Error(err);
|
||||
});
|
||||
return seed;
|
||||
} else {
|
||||
throw new Error("SD 模式错误");
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
// 当前队列执行失败移除整个批次的任务
|
||||
this.global.requestQuene.removeTask(task_list.out_folder, null)
|
||||
this.global.fileQueue.enqueue(async () => {
|
||||
// 记录失败状态
|
||||
let task_list_json = JSON.parse(await fspromises.readFile(taskPath, 'utf-8'));
|
||||
// 修改指定的列表的数据
|
||||
task_list_json.task_list.map(a => {
|
||||
if (a.id == task_list.id) {
|
||||
a.status = "error";
|
||||
a.errorMessage = error.toString();
|
||||
}
|
||||
})
|
||||
// 写入
|
||||
await fspromises.writeFile(taskPath, JSON.stringify(task_list_json));
|
||||
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.IMAGE_TASK_STATUS_REFRESH, {
|
||||
out_folder: task_list.out_folder,
|
||||
status: "error"
|
||||
});
|
||||
})
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*文生图
|
||||
* @param {SD 请求的地址} url
|
||||
* @param {SD请求的body} body
|
||||
*/
|
||||
async txt2img(url, body) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*图生图
|
||||
* @param {SD 请求的地址} url
|
||||
* @param {SD请求的body} body
|
||||
*/
|
||||
async img2img(url, body) {
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,850 @@
|
||||
import { define } from "../../define/define";
|
||||
import path from "path";
|
||||
import { Tools } from "../tools";
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const fspromises = require("fs").promises;
|
||||
const mm = require('music-metadata');
|
||||
const wavFileInfo = require('wav-file-info');
|
||||
let tools = new Tools();
|
||||
import { PublicMethod } from './publicMethod'
|
||||
import { cloneDeep } from "lodash";
|
||||
const compressing = require("compressing");
|
||||
|
||||
export class ClipDraft {
|
||||
constructor(global, value) {
|
||||
this.speedId = null;
|
||||
this.canvasesId = null;
|
||||
this.soundChannelId = null;
|
||||
this.vocalSeparationsId = null;
|
||||
this.materialVideoId = null;
|
||||
this.tracksSegmentsId = null;
|
||||
this.trackTypeId = null;
|
||||
this.materialAnimationsId = null;
|
||||
this.materialsTextID = null;
|
||||
this.materialsBeatsID = null;
|
||||
this.textId = null;
|
||||
this.friendlyReminderId = null;
|
||||
this.draft_json = null;
|
||||
this.one_duration_time = 5000000;
|
||||
this.text_end_time = 0;
|
||||
this.iamge_end_time = 0;
|
||||
this.dubbing_emd_time = 0;
|
||||
this.draft_duration_time = 0;
|
||||
this.global = global;
|
||||
this.value = value;
|
||||
this.pm = new PublicMethod(global);
|
||||
}
|
||||
|
||||
async InitData() {
|
||||
this.draft_name = this.global.config.project_name + '_' + this.value[0];
|
||||
let draft_path = path.join(this.global.config.draft_path, this.draft_name);
|
||||
await fspromises.rm(draft_path, { recursive: true, force: true });
|
||||
await compressing.zip.uncompress(define.draft_temp_path, path.join(this.global.config.draft_path, this.global.config.project_name + '_' + this.value[0]));
|
||||
this.draftPath = path.join(draft_path, "draft_content.json");
|
||||
this.image_dir = path.join(this.global.config.project_path, `tmp/${this.value[0]}`);
|
||||
this.srtPath = this.value[1].srt_path;
|
||||
this.style_id = this.value[1].draft_srt_style;
|
||||
this.num = 1;
|
||||
this.mp3_path = this.value[1].audio_path;
|
||||
this.friendlyReminderId = this.value[1].friendly_reminder;
|
||||
this.srt_information = (await this.pm.GetConfigJson(JSON.stringify(["srt_time_information", []]))).data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载默认的草稿
|
||||
* @returns
|
||||
*/
|
||||
async LoadDraftJson() {
|
||||
let draft_json = JSON.parse(await fspromises.readFile(this.draftPath));
|
||||
this.draft_json = draft_json;
|
||||
// console.log(this.draft_json);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加speed
|
||||
*/
|
||||
async AddSpeeds() {
|
||||
// 获取speed的模板地址
|
||||
let speed_json = JSON.parse(await fspromises.readFile(define.clip_speed_temp_path));
|
||||
// console.log(speed_json)
|
||||
// 设置ID
|
||||
let speedID = uuidv4().toUpperCase();
|
||||
this.speedId = speedID;
|
||||
speed_json.id = speedID;
|
||||
return speed_json;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加Canvases
|
||||
*/
|
||||
async AddCanvases() {
|
||||
let canvases_json = JSON.parse(await fspromises.readFile(define.add_canvases_temp_path));
|
||||
// console.log(canvases_json);
|
||||
// 设置ID
|
||||
let canvasesId = uuidv4().toUpperCase();
|
||||
this.canvasesId = canvasesId;
|
||||
canvases_json.id = canvasesId;
|
||||
return canvases_json;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加soundchannel
|
||||
* @returns
|
||||
*/
|
||||
async AddSoundChannelMapping() {
|
||||
let soundChannelMapping_json = JSON.parse(await fspromises.readFile(define.add_sound_channel_mappings_temp_path));
|
||||
// console.log(soundChannelMapping_json)
|
||||
let sound_channel_mappings_tmp_ID = uuidv4().toUpperCase();
|
||||
this.soundChannelId = sound_channel_mappings_tmp_ID;
|
||||
soundChannelMapping_json.id = sound_channel_mappings_tmp_ID;
|
||||
return soundChannelMapping_json;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加 vocal_separations
|
||||
*/
|
||||
async AddVocalSeparations() {
|
||||
let vocal_separations_json = JSON.parse(await fspromises.readFile(define.add_vocal_separations_temp_path));
|
||||
// console.log(vocal_separations_json);
|
||||
let vocalSeparationId = uuidv4().toUpperCase();
|
||||
this.vocalSeparationsId = vocalSeparationId;
|
||||
vocal_separations_json.id = vocalSeparationId;
|
||||
return vocal_separations_json;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个文件到原材料地址
|
||||
* @param {图片文件地址} imagePath
|
||||
*/
|
||||
async AddMaterialVideo(imagePath) {
|
||||
let materialVideoTmpJson = JSON.parse(await fspromises.readFile(define.add_material_video_temp_path));
|
||||
// console.log(materialVideoTmpJson);
|
||||
let materialId = uuidv4().toUpperCase();
|
||||
this.materialVideoId = materialId;
|
||||
materialVideoTmpJson.id = materialId;
|
||||
|
||||
// 获取输入的图片宽高
|
||||
// let image = await Jimp.read(imagePath);
|
||||
// let width = image.bitmap.width;
|
||||
// let height = image.bitmap.height;
|
||||
materialVideoTmpJson.width = 1000;
|
||||
materialVideoTmpJson.height = 1000;
|
||||
|
||||
materialVideoTmpJson.path = imagePath;
|
||||
let image_name = path.basename(imagePath);
|
||||
materialVideoTmpJson.material_name = image_name;
|
||||
|
||||
return materialVideoTmpJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个轨道
|
||||
* @returns
|
||||
*/
|
||||
async AddTracksSegments() {
|
||||
let tracksJson = JSON.parse(await fspromises.readFile(define.add_tracks_segments_temp_path));
|
||||
// console.log(tracksJson);
|
||||
let tracksSegmentsId = uuidv4().toUpperCase();
|
||||
tracksJson.id = tracksSegmentsId;
|
||||
tracksJson.extra_material_refs = [];
|
||||
tracksJson.extra_material_refs.push(this.speedId);
|
||||
tracksJson.extra_material_refs.push(this.canvasesId);
|
||||
tracksJson.extra_material_refs.push(this.soundChannelId);
|
||||
tracksJson.extra_material_refs.push(this.vocalSeparationsId);
|
||||
tracksJson.material_id = this.materialVideoId;
|
||||
tracksJson.target_timerange.start = this.num * tracksJson.target_timerange.duration;
|
||||
return tracksJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新建一个track
|
||||
* @param {track的类型} type
|
||||
*/
|
||||
async AddTracks(type) {
|
||||
let tracks_json = JSON.parse(await fspromises.readFile(define.add_tracks_type_temp_path));
|
||||
let track_type_id = uuidv4();
|
||||
this.trackTypeId = track_type_id;
|
||||
tracks_json.id = this.trackTypeId;
|
||||
tracks_json.type = type;
|
||||
return tracks_json;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加单个图片到轨道
|
||||
*/
|
||||
async AddOneImageToDraft(image_path) {
|
||||
// 添加 canvases
|
||||
let canvanses = await this.AddCanvases();
|
||||
this.draft_json.materials.canvases.push(canvanses)
|
||||
|
||||
// 添加 sound_channel_mappings
|
||||
let sound_channel = await this.AddSoundChannelMapping();
|
||||
this.draft_json.materials.sound_channel_mappings.push(sound_channel)
|
||||
|
||||
// 添加 speeds
|
||||
let speeds = await this.AddSpeeds();
|
||||
this.draft_json.materials.speeds.push(speeds);
|
||||
|
||||
// 添加 vocal_separations
|
||||
let vocal_sep = await this.AddVocalSeparations();
|
||||
this.draft_json.materials.vocal_separations.push(vocal_sep);
|
||||
|
||||
// 添加视频 materials 下面的 Videos
|
||||
let video = await this.AddMaterialVideo(image_path);
|
||||
this.draft_json.materials.videos.push(video);
|
||||
|
||||
// 添加track轨道
|
||||
let segment = await this.AddTracksSegments();
|
||||
return segment;
|
||||
// this.draft_json.tracks.segments.push(segment);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将所有的文件全部都写轨道上面
|
||||
*/
|
||||
async AddAllImageToTracks() {
|
||||
let img_dir = path.normalize(this.image_dir);
|
||||
let files = await fspromises.readdir(img_dir)
|
||||
let imageFiles = files.filter(file => /\.(png)$/i.test(file));
|
||||
imageFiles.sort();
|
||||
imageFiles = imageFiles.map(item => path.join(img_dir, item))
|
||||
// console.log(imageFiles);
|
||||
|
||||
// 创建一个tracks
|
||||
let tracks_json = await this.AddTracks("video");
|
||||
//往tracks里面的segments添加图片数据
|
||||
for (let i = 0; i < imageFiles.length; i++) {
|
||||
const image_path = imageFiles[i];
|
||||
let segment = await this.AddOneImageToDraft(image_path);
|
||||
tracks_json.segments.push(segment);
|
||||
// console.log(tracks_json);
|
||||
}
|
||||
|
||||
this.draft_json.tracks.push(tracks_json);
|
||||
// 修改持续时间
|
||||
let duration_time = imageFiles.length * this.one_duration_time;
|
||||
this.iamge_end_time = duration_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加materials中的material_animations
|
||||
*/
|
||||
async AddMaterialAnimations() {
|
||||
let material_animations = JSON.parse(await fspromises.readFile(define.add_material_animations_temp_path));
|
||||
let material_animations_id = uuidv4();
|
||||
this.materialAnimationsId = material_animations_id;
|
||||
material_animations.id = material_animations_id;
|
||||
return material_animations;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为字幕添加样式
|
||||
*/
|
||||
async AddTextStyle(material_text_json) {
|
||||
try {
|
||||
let clip_setting = JSON.parse(await fspromises.readFile(define.clip_setting));
|
||||
let text_style = clip_setting.text_style.filter(item => item.id != "0" && item.id != "1");
|
||||
|
||||
// 添加默认样式
|
||||
let c = JSON.parse(material_text_json.content);
|
||||
let data = JSON.parse(`[{\"size\":7.882736,\"fill\":{\"content\":{\"solid\":{\"color\":[1,1,1]}}},\"range\":[0,5]}]`);
|
||||
data[0].range = [0, c.text.length];
|
||||
c["styles"] = data;
|
||||
material_text_json.content = JSON.stringify(c);
|
||||
return material_text_json;
|
||||
|
||||
// 判断是不是添加样式添加样式
|
||||
if (this.style_id == "0") {
|
||||
return material_text_json;
|
||||
} else if (this.style_id == "1") {
|
||||
// 随机
|
||||
const randomIndex = Math.floor(Math.random() * text_style.length);
|
||||
this.style_id = text_style[randomIndex].id;
|
||||
}
|
||||
let style = text_style.filter(item => item.id == this.style_id)[0];
|
||||
let content = JSON.parse(material_text_json.content);
|
||||
|
||||
// 修改范围
|
||||
let textstring = content.text;
|
||||
let length = textstring.length;
|
||||
style.style[0].range = [0, length];
|
||||
|
||||
content.styles = style.style;
|
||||
material_text_json.content = JSON.stringify(content);
|
||||
let path = style.style[0].font.path;
|
||||
let id = style.style[0].font.id;
|
||||
let font_size = style.font_size;
|
||||
let fonts = style.fonts;
|
||||
let style_name = style.style_name;
|
||||
material_text_json.fonts.id = uuidv4();
|
||||
material_text_json.font_category_id = id;
|
||||
material_text_json.fonts.path = path;
|
||||
material_text_json.fonts.title = fonts;
|
||||
material_text_json.check_flag = font_size;
|
||||
material_text_json.title = fonts;
|
||||
material_text_json.font_size = font_size;
|
||||
material_text_json.style_name = style_name;
|
||||
return material_text_json;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得一个单的materialsText
|
||||
*/
|
||||
async AddMaterialsText(textString) {
|
||||
let material_text_json = JSON.parse(await fspromises.readFile(define.add_material_text_temp_path));
|
||||
let material_text_id = uuidv4();
|
||||
this.materialsTextID = material_text_id;
|
||||
material_text_json.id = material_text_id;
|
||||
|
||||
// 设置内容
|
||||
let content = JSON.parse(material_text_json.content);
|
||||
content.text = textString;
|
||||
material_text_json.content = JSON.stringify(content);
|
||||
|
||||
material_text_json = await this.AddTextStyle(material_text_json);
|
||||
return material_text_json;
|
||||
}
|
||||
|
||||
async ModifyTextClipTransform(text_segments) {
|
||||
// console.log(text_segments);
|
||||
|
||||
let clip_setting = JSON.parse(await fspromises.readFile(define.clip_setting));
|
||||
let text_style = clip_setting.text_style;
|
||||
if (text_style.length <= 0)
|
||||
return text_segments;
|
||||
let style = text_style.filter(item => item.id == this.style_id)[0];
|
||||
text_segments.clip = style.clip;
|
||||
return text_segments;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个字幕到tracks
|
||||
* @returns
|
||||
*/
|
||||
async AddOneTextToDraft(timeObj) {
|
||||
try {
|
||||
|
||||
// 添加 materials 中的 material_animations
|
||||
let material_animattions = await this.AddMaterialAnimations();
|
||||
this.draft_json.materials.material_animations.push(material_animattions);
|
||||
|
||||
// 添加 materials 下面的texts
|
||||
let material_text = await this.AddMaterialsText(timeObj.text);
|
||||
this.draft_json.materials.texts.push(material_text);
|
||||
|
||||
let text_segments = JSON.parse(await fspromises.readFile(define.add_track_text_segments_temp_path));
|
||||
let textId = uuidv4();
|
||||
this.textId = textId;
|
||||
text_segments.id = textId;
|
||||
text_segments.extra_material_refs = [this.materialAnimationsId];
|
||||
text_segments.material_id = this.materialsTextID;
|
||||
text_segments.target_timerange.start = timeObj.start;
|
||||
text_segments.target_timerange.duration = timeObj.end - timeObj.start;
|
||||
|
||||
// 修改样式偏移量
|
||||
text_segments = await this.ModifyTextClipTransform(text_segments);
|
||||
|
||||
return text_segments;
|
||||
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: `Error Message ${error}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加所有的text到tracks里面
|
||||
*/
|
||||
async AddAllTextToTrack() {
|
||||
// 添加一个tracks
|
||||
let new_tracks = await this.AddTracks("text");
|
||||
// 计算时间
|
||||
let srt_data = (await fspromises.readFile(this.srtPath)).toString("utf-8");
|
||||
const entries = srt_data.replace(/\r\n/g, '\n').split('\n\n');
|
||||
let data = entries.map(entry => {
|
||||
const lines = entry.split('\n');
|
||||
if (lines.length >= 3) {
|
||||
const times = lines[1];
|
||||
const text = lines.slice(2).join(' ');
|
||||
const [start, end] = times.split(' --> ').map(time => {
|
||||
const [hours, minutes, seconds] = time.split(':');
|
||||
const [sec, millis] = seconds.split(',');
|
||||
return ((parseInt(hours) * 3600 + parseInt(minutes) * 60 + parseInt(sec)) * 1000 + parseInt(millis)) * 1000;
|
||||
});
|
||||
return { start, end, text };
|
||||
}
|
||||
}).filter(entry => entry);
|
||||
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const text = data[i];
|
||||
let text_se = await this.AddOneTextToDraft(text);
|
||||
// console.log(text_se);
|
||||
new_tracks.segments.push(text_se);
|
||||
if (i == data.length - 1) {
|
||||
this.text_end_time = text.end;
|
||||
}
|
||||
}
|
||||
// console.log(this.draft_json)
|
||||
this.draft_json.tracks.push(new_tracks);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加 materials下面的 beats
|
||||
*/
|
||||
async AddMaterialsBeats() {
|
||||
let beats_json = JSON.parse(await fspromises.readFile(define.add_materials_beats_tmp_path));
|
||||
let materialsBeatsID = uuidv4();
|
||||
this.materialsBeatsID = materialsBeatsID;
|
||||
beats_json.id = materialsBeatsID;
|
||||
return beats_json;
|
||||
}
|
||||
|
||||
|
||||
async getAudioDuration(filePath) {
|
||||
const ext = filePath.split('.').pop().toLowerCase();
|
||||
|
||||
switch (ext) {
|
||||
case 'mp3':
|
||||
try {
|
||||
const metadata = await mm.parseFile(filePath);
|
||||
return metadata.format.duration;
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
|
||||
case 'wav':
|
||||
return new Promise((resolve, reject) => {
|
||||
wavFileInfo.infoByFilename(filePath, (err, info) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(info.duration);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
default:
|
||||
throw new Error("不支持的文件类型");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加 materials 下面的 audios
|
||||
*/
|
||||
async AddMaterialsAudios(musicPath) {
|
||||
try {
|
||||
let audios_json = JSON.parse(await fspromises.readFile(define.add_materials_audios_tmp_path));
|
||||
let mp3_name = path.basename(musicPath);
|
||||
let time = await this.getAudioDuration(path.normalize(musicPath));
|
||||
let duration_time = time * 1000000;
|
||||
if (this.audios_duration_time == undefined) {
|
||||
this.audios_duration_time = duration_time;
|
||||
}
|
||||
let audiosID = uuidv4();
|
||||
this.materialsAudiosID = audiosID;
|
||||
audios_json.id = audiosID;
|
||||
audios_json.name = mp3_name;
|
||||
audios_json.duration = duration_time;
|
||||
audios_json.path = musicPath;
|
||||
console.log(audios_json)
|
||||
return audios_json;
|
||||
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加tracks下面的audios下面的Segments
|
||||
*/
|
||||
async AddAudioTracksSegments() {
|
||||
try {
|
||||
let audio_segments = JSON.parse(await fspromises.readFile(define.add_tracks_audio_segments_tmp_path));
|
||||
let audioId = uuidv4();
|
||||
this.tracksAudioId = audioId;
|
||||
audio_segments.id = audioId;
|
||||
audio_segments.material_id = this.materialsAudiosID;
|
||||
audio_segments.extra_material_refs = [];
|
||||
audio_segments.extra_material_refs.push(this.speedID);
|
||||
audio_segments.extra_material_refs.push(this.materialsBeatsID);
|
||||
audio_segments.extra_material_refs.push(this.soundChannelId);
|
||||
audio_segments.extra_material_refs.push(this.vocalSeparationsId);
|
||||
audio_segments.source_timerange.duration = this.audios_duration_time;
|
||||
audio_segments.target_timerange.duration = this.audios_duration_time;
|
||||
return audio_segments;
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加配音
|
||||
*/
|
||||
async AddDubbingMusic(musicPath) {
|
||||
// 添加speeds
|
||||
let speeds = await this.AddSpeeds();
|
||||
this.draft_json.materials.speeds.push(speeds);
|
||||
|
||||
// 添加beats
|
||||
let beats = await this.AddMaterialsBeats();
|
||||
this.draft_json.materials.beats.push(beats);
|
||||
|
||||
// 添加 sound_channel_mappings
|
||||
let sound_channel_mappings = await this.AddSoundChannelMapping();
|
||||
this.draft_json.materials.sound_channel_mappings.push(sound_channel_mappings)
|
||||
|
||||
// 添加 materials 下面的 audios
|
||||
let audios = await this.AddMaterialsAudios(musicPath);
|
||||
this.draft_json.materials.audios.push(audios);
|
||||
|
||||
// 添加一个track
|
||||
let tracks_json = await this.AddTracks("audio");
|
||||
|
||||
let audio_segments_json = await this.AddAudioTracksSegments();
|
||||
tracks_json.segments.push(audio_segments_json);
|
||||
this.draft_json.tracks.push(tracks_json);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加背景音乐
|
||||
* @param {背景音乐的ID} background_music_id
|
||||
*/
|
||||
async AddRandomBackfroundMusic(background_music_id) {
|
||||
try {
|
||||
// 获取背景音乐文件夹
|
||||
let clip_setting_json = JSON.parse(await fspromises.readFile(define.clip_setting));
|
||||
let setting = clip_setting_json.background_music_setting.filter(item => item.id == background_music_id);
|
||||
console.log(setting);
|
||||
let folder_path = setting[0].folder_path;
|
||||
console.log(folder_path);
|
||||
let files = await tools.getFilesWithExtensions(folder_path, [".mp3", ".wav"]);
|
||||
if (files.length == 0) {
|
||||
throw new Error("背景音乐文件夹下面未存在数据");
|
||||
}
|
||||
// 获取随机的数据
|
||||
const randomIndex = Math.floor(Math.random() * files.length);
|
||||
let musicPath = files[randomIndex];
|
||||
|
||||
// 添加speeds
|
||||
let speeds = await this.AddSpeeds();
|
||||
this.draft_json.materials.speeds.push(speeds);
|
||||
|
||||
// 添加beats
|
||||
let beats = await this.AddMaterialsBeats();
|
||||
this.draft_json.materials.beats.push(beats);
|
||||
|
||||
// 添加 sound_channel_mappings
|
||||
let sound_channel_mappings = await this.AddSoundChannelMapping();
|
||||
this.draft_json.materials.sound_channel_mappings.push(sound_channel_mappings)
|
||||
|
||||
// 添加 materials 下面的 audios
|
||||
let audios = await this.AddMaterialsAudios(musicPath);
|
||||
// audios.duration = this.text_end_time;
|
||||
this.draft_json.materials.audios.push(audios);
|
||||
|
||||
// 添加一个track
|
||||
let tracks_json = await this.AddTracks("audio");
|
||||
let audio_segments_json = await this.AddAudioTracksSegments();
|
||||
// 修改
|
||||
audio_segments_json.source_timerange.duration = this.audios_duration_time;
|
||||
audio_segments_json.target_timerange.duration = this.audios_duration_time;
|
||||
tracks_json.segments.push(audio_segments_json);
|
||||
this.draft_json.tracks.push(tracks_json);
|
||||
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加温馨提示
|
||||
*/
|
||||
async AddFriendlyReminder() {
|
||||
// 直接push
|
||||
try {
|
||||
|
||||
return;
|
||||
|
||||
let friendlyReminder = null;
|
||||
let friendlyReminderSetting = JSON.parse(await fspromises.readFile(define.clip_setting)).friendly_reminder_setting;
|
||||
friendlyReminderSetting = friendlyReminderSetting.filter(item => item.id != "0" && item.id != "1");
|
||||
if (friendlyReminderSetting.length <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.friendlyReminderId == "0") {
|
||||
return;
|
||||
} else if (this.friendlyReminderId == "1") {
|
||||
// 获取随机的数据
|
||||
const randomIndex = Math.floor(Math.random() * friendlyReminderSetting.length);
|
||||
friendlyReminder = friendlyReminderSetting[randomIndex];
|
||||
} else {
|
||||
friendlyReminder = friendlyReminderSetting.filter(item => item.id == this.friendlyReminderId);
|
||||
}
|
||||
|
||||
// 添加 materials 下面的 material_animations
|
||||
this.draft_json.materials.material_animations.push(friendlyReminder.material_animations);
|
||||
// 添加 materials下面的texts
|
||||
this.draft_json.materials.texts.push(friendlyReminder.texts);
|
||||
// 添加 tracks
|
||||
let track = friendlyReminder.tracks;
|
||||
// 修改持续时间
|
||||
track.segments[0].target_timerange.duration = this.audios_duration_time;
|
||||
this.draft_json.tracks.push(track);
|
||||
} catch (error) {
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改草稿的持续时间
|
||||
*/
|
||||
async ModifyDurationTime() {
|
||||
|
||||
let max_time = Math.max(this.iamge_end_time, this.text_end_time, this.audios_duration_time);
|
||||
this.draft_json.duration = max_time;
|
||||
this.draft_json.canvas_config.height = 1440;
|
||||
this.draft_json.canvas_config.width = 1920;
|
||||
this.draft_json.canvas_config.ratio = "4:3";
|
||||
}
|
||||
|
||||
/**
|
||||
* 将文件写道指定的位置
|
||||
*/
|
||||
async WriteDraftFile() {
|
||||
await fspromises.writeFile(this.draftPath, JSON.stringify(this.draft_json));
|
||||
}
|
||||
|
||||
async find_draft_node(nodes, type, value) {
|
||||
for (let index = 0; index < nodes.length; index++) {
|
||||
let node = nodes[index];
|
||||
if (node[type] == value) {
|
||||
return node
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将草稿图片和文字对齐
|
||||
*/
|
||||
async AlginDraftImgToText() {
|
||||
// 所有的字幕轨道里面的数据,读取出来
|
||||
let img_nodes = (await this.find_draft_node(this.draft_json.tracks, "type", "video")).segments;
|
||||
|
||||
//将最后一个数据修改为背景音乐的最后时间
|
||||
this.srt_information[this.srt_information.length - 1].end_time = this.audios_duration_time / 1000;
|
||||
|
||||
// 开始对齐
|
||||
for (let i = 0; i < this.srt_information.length; i++) {
|
||||
if (img_nodes.length < i) {
|
||||
break;
|
||||
}
|
||||
const element = this.srt_information[i];
|
||||
let duration = 0;
|
||||
if (i + 1 < this.srt_information.length) {
|
||||
duration = (this.srt_information[i + 1].start_time - element.start_time - 1) * 1000;
|
||||
} else {
|
||||
duration = (element.end_time - element.start_time) * 1000;
|
||||
}
|
||||
img_nodes[i].source_timerange.duration = duration;
|
||||
img_nodes[i].target_timerange.duration = duration;
|
||||
img_nodes[i].target_timerange.start = element.start_time * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 key_frame 返回关键帧数据
|
||||
* @param {*} key_frame 关键帧配置
|
||||
*/
|
||||
async GetFrameData(key_frame) {
|
||||
if (key_frame.key_frame == "KFTypePositionY") {
|
||||
return key_frame.up_down_key_frame;
|
||||
} else if (key_frame.key_frame == "KFTypePositionX") {
|
||||
return key_frame.left_right_key_frame;
|
||||
} else if (key_frame.key_frame == "KFTypeScale") {
|
||||
return key_frame.scale_key_frame;
|
||||
} else {
|
||||
return {
|
||||
"default_scale": 100,
|
||||
"start_position": 0,
|
||||
"end_position": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片添加关键帧
|
||||
*/
|
||||
async AddKeyFarme() {
|
||||
let img_nodes = (await this.find_draft_node(this.draft_json.tracks, "type", "video")).segments;
|
||||
let key_frame_tmp_data = JSON.parse(await fspromises.readFile(define.add_keyframe_tmp_path, "utf-8"));
|
||||
// 添加关键帧
|
||||
// 将最后一个数据修改为背景音乐的最后时间
|
||||
this.srt_information[this.srt_information.length - 1].end_time = this.audios_duration_time / 1000;
|
||||
|
||||
let key_frame_setting = await tools.getJsonFilePropertyValue(define.clip_setting, "key_frame", null, false);
|
||||
// 判断关键帧配置是不是存在。不存在直接结束
|
||||
if (key_frame_setting == null) {
|
||||
return;
|
||||
}
|
||||
let key_frame_pos = await this.GetFrameData(key_frame_setting);
|
||||
let isFixedSpeed = key_frame_setting.isFixedSpeed;
|
||||
let key_frame_time = key_frame_setting.key_frame_time * 1000000;
|
||||
let isDown = true;
|
||||
let scale_rate = key_frame_pos.default_scale / 100;
|
||||
|
||||
// 获取通用的关键帧配置,然后添加到每一个图片上面(可以设置时间。当前图片的持续实现小于设置的时间。会计算不要过快)
|
||||
for (let i = 0; i < img_nodes.length; i++) {
|
||||
let element = img_nodes[i];
|
||||
let image_duartion = cloneDeep(element.source_timerange.duration);
|
||||
|
||||
let up_pos = Math.abs(key_frame_pos.start_position);
|
||||
let down_pos = Math.abs(key_frame_pos.end_position);
|
||||
|
||||
if (key_frame_setting.key_frame == "KFTypePositionY") {
|
||||
|
||||
|
||||
// 勾选了匀速。需要计算时间(计算比例)
|
||||
|
||||
if (isFixedSpeed && image_duartion < key_frame_time) {
|
||||
let time_rate = image_duartion / key_frame_time;
|
||||
up_pos = up_pos * time_rate;
|
||||
down_pos = down_pos * time_rate;
|
||||
}
|
||||
let key_frame_tmp = cloneDeep(key_frame_tmp_data)
|
||||
let up_pos_rate = isDown ? (up_pos / this.draft_json.canvas_config.height) : (0 - up_pos / this.draft_json.canvas_config.height)
|
||||
key_frame_tmp.id = uuidv4();
|
||||
key_frame_tmp.keyframe_list[0].id == uuidv4();
|
||||
key_frame_tmp.keyframe_list[0].values = [up_pos_rate];
|
||||
|
||||
let dow_pos_rate = isDown ? (0 - down_pos / this.draft_json.canvas_config.height) : (down_pos / this.draft_json.canvas_config.height)
|
||||
key_frame_tmp.keyframe_list[1].id = uuidv4();
|
||||
key_frame_tmp.keyframe_list[1].time_offset = image_duartion;
|
||||
key_frame_tmp.keyframe_list[1].values = [dow_pos_rate];
|
||||
|
||||
key_frame_tmp.property_type = key_frame_setting.key_frame;
|
||||
|
||||
// 修改缩放倍率
|
||||
element.clip.scale.x = scale_rate;
|
||||
element.clip.scale.y = scale_rate;
|
||||
element.clip.transform.y = dow_pos_rate;
|
||||
isDown = !isDown;
|
||||
element.common_keyframes.push(key_frame_tmp);
|
||||
} else if (key_frame_setting.key_frame == "KFTypePositionX") {
|
||||
// 勾选了匀速。需要计算时间(计算比例)
|
||||
if (isFixedSpeed && image_duartion < key_frame_time) {
|
||||
let time_rate = image_duartion / key_frame_time;
|
||||
up_pos = up_pos * time_rate;
|
||||
down_pos = down_pos * time_rate;
|
||||
}
|
||||
let key_frame_tmp = cloneDeep(key_frame_tmp_data)
|
||||
let up_pos_rate = isDown ? (up_pos / this.draft_json.canvas_config.width) : (0 - up_pos / this.draft_json.canvas_config.width)
|
||||
key_frame_tmp.id = uuidv4();
|
||||
key_frame_tmp.keyframe_list[0].id == uuidv4();
|
||||
key_frame_tmp.keyframe_list[0].values = [up_pos_rate];
|
||||
|
||||
let dow_pos_rate = isDown ? (0 - down_pos / this.draft_json.canvas_config.width) : (down_pos / this.draft_json.canvas_config.width)
|
||||
key_frame_tmp.keyframe_list[1].id = uuidv4();
|
||||
key_frame_tmp.keyframe_list[1].time_offset = image_duartion;
|
||||
key_frame_tmp.keyframe_list[1].values = [dow_pos_rate];
|
||||
|
||||
key_frame_tmp.property_type = key_frame_setting.key_frame;
|
||||
|
||||
// 修改缩放倍率
|
||||
element.clip.scale.x = scale_rate;
|
||||
element.clip.scale.y = scale_rate;
|
||||
element.clip.transform.x = dow_pos_rate;
|
||||
isDown = !isDown;
|
||||
element.common_keyframes.push(key_frame_tmp);
|
||||
}
|
||||
else if (key_frame_setting.key_frame == "KFTypeScale") {
|
||||
if (isFixedSpeed && image_duartion < key_frame_time) {
|
||||
let time_rate = image_duartion / key_frame_time;
|
||||
// 计算方式和上面的不同
|
||||
let sub_total = Math.abs(up_pos - down_pos);
|
||||
let currwnt_rate = sub_total * (1 - time_rate);
|
||||
up_pos = up_pos + currwnt_rate / 2;
|
||||
down_pos = down_pos - currwnt_rate / 2;
|
||||
}
|
||||
|
||||
// 修改上面的数据,添加Y轴缩放
|
||||
let key_frame_tmp = cloneDeep(key_frame_tmp_data)
|
||||
let up_pos_rate = isDown ? up_pos / 100 : down_pos / 100;
|
||||
key_frame_tmp.id = uuidv4();
|
||||
key_frame_tmp.keyframe_list[0].id == uuidv4();
|
||||
key_frame_tmp.keyframe_list[0].values = [up_pos_rate];
|
||||
|
||||
let dow_pos_rate = isDown ? down_pos / 100 : up_pos / 100;
|
||||
key_frame_tmp.keyframe_list[1].id = uuidv4();
|
||||
key_frame_tmp.keyframe_list[1].time_offset = image_duartion;
|
||||
key_frame_tmp.keyframe_list[1].values = [dow_pos_rate];
|
||||
|
||||
key_frame_tmp.property_type = key_frame_setting.key_frame + "X";
|
||||
|
||||
// 修改上面的数据,添加Y轴缩放
|
||||
// 修改缩放倍率
|
||||
element.clip.scale.x = isDown ? up_pos : dow_pos_rate;
|
||||
element.clip.scale.y = isDown ? up_pos : dow_pos_rate;
|
||||
element.clip.transform.x = 0;
|
||||
element.common_keyframes.push(key_frame_tmp);
|
||||
|
||||
key_frame_tmp = cloneDeep(key_frame_tmp)
|
||||
key_frame_tmp.id = uuidv4();
|
||||
key_frame_tmp.keyframe_list[0].id == uuidv4();
|
||||
key_frame_tmp.keyframe_list[1].id = uuidv4();
|
||||
key_frame_tmp.property_type = key_frame_setting.key_frame + "Y";
|
||||
element.common_keyframes.push(key_frame_tmp);
|
||||
|
||||
isDown = !isDown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 添加草稿
|
||||
*/
|
||||
async addDraft() {
|
||||
try {
|
||||
await this.InitData();
|
||||
await this.LoadDraftJson();
|
||||
await this.AddAllImageToTracks();
|
||||
await this.AddAllTextToTrack();
|
||||
await this.AddDubbingMusic(path.normalize(this.value[1].audio_path));
|
||||
if (this.value[1].background_music != "" && this.value[1].background_music != undefined && this.value[1].background_music != null) {
|
||||
await this.AddRandomBackfroundMusic(this.value[1].background_music);
|
||||
}
|
||||
|
||||
// 添加温馨提示
|
||||
// await this.AddFriendlyReminder();
|
||||
|
||||
|
||||
await this.ModifyDurationTime();
|
||||
|
||||
// 对齐草稿数据
|
||||
await this.AlginDraftImgToText();
|
||||
|
||||
// 添加关键帧
|
||||
await this.AddKeyFarme();
|
||||
|
||||
await this.WriteDraftFile();
|
||||
return {
|
||||
code: 1,
|
||||
draft_name: this.draft_name
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: `An error occurred: ${error}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,335 @@
|
||||
import path from "path";
|
||||
import { define } from "../../define/define";
|
||||
import { Tools } from "../tools";
|
||||
import { DEFINE_STRING } from "../../define/define_string";
|
||||
import { get, has } from "lodash";
|
||||
const util = require('util');
|
||||
const { spawn, exec } = require('child_process');
|
||||
const execAsync = util.promisify(exec);
|
||||
const fspromises = require("fs").promises;
|
||||
|
||||
export class PublicMethod {
|
||||
constructor(global) {
|
||||
this.global = global;
|
||||
this.tools = new Tools();
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改config.json文件中的指定的属性
|
||||
* @param {*} value 0: 要修改的数据 1: 要修改的属性 2: 是否需要解析
|
||||
* @returns
|
||||
*/
|
||||
async SaveConfigJsonProperty(value) {
|
||||
try {
|
||||
let data = value[0];
|
||||
let property = value[1];
|
||||
let parse = value[2];
|
||||
if (parse) {
|
||||
data = JSON.parse(value[0])
|
||||
}
|
||||
let json_path = path.join(global.config.project_path, "scripts/config.json");
|
||||
// 判断文件是不是存在
|
||||
let isExit = await this.tools.checkExists(json_path);
|
||||
let json_data = {};
|
||||
if (!isExit) {
|
||||
const dirPath = path.dirname(json_path);
|
||||
await fspromises.mkdir(dirPath, { recursive: true });
|
||||
await fspromises.writeFile(json_path, '{}');
|
||||
}
|
||||
else {
|
||||
const o_data = await fspromises.readFile(json_path, 'utf8');
|
||||
// 将读取的 JSON 字符串转换为 JavaScript 对象
|
||||
let obj = JSON.parse(o_data);
|
||||
json_data = obj;
|
||||
}
|
||||
json_data[property] = data;
|
||||
|
||||
await fspromises.writeFile(json_path, JSON.stringify(json_data));
|
||||
return {
|
||||
code: 1
|
||||
}
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前项目的config.json文件中的指定的属性信息,若是没有传入属性,则返回所有的信息
|
||||
* @param {Array} value 0 要获取的属性 1 返回的默认值
|
||||
* @param {Boolean} ckeck 是否需要校验属性不存在
|
||||
* @returns
|
||||
*/
|
||||
async GetConfigJson(value, ckeck = true) {
|
||||
try {
|
||||
value = JSON.parse(value)
|
||||
let srt_config_path = path.join(global.config.project_path, "scripts/config.json");
|
||||
let data = await this.tools.getJsonFilePropertyValue(srt_config_path, value[0], value[1], ckeck);
|
||||
return {
|
||||
code: 1,
|
||||
data: data
|
||||
}
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改生成图片的任务队列数据
|
||||
* @param {传入的要修改的数据数组} value
|
||||
*/
|
||||
async ModifyImageTaskList(value) {
|
||||
this.global.fileQueue.enqueue(async () => {
|
||||
try {
|
||||
let task_list_path = path.join(this.global.config.project_path, "scripts/task_list.json");
|
||||
let isE = await this.tools.checkExists(task_list_path);
|
||||
if (!isE) {
|
||||
throw new Error("任务队列文件不存在。请先添加 批次任务");
|
||||
}
|
||||
let task_list_json = JSON.parse(await fspromises.readFile(task_list_path, "utf-8"));
|
||||
// 循环循环数据。修改
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
const element = value[i];
|
||||
let index = task_list_json.task_list.findIndex(item => item.id == element.id);
|
||||
task_list_json.task_list[index] = element;
|
||||
}
|
||||
await fspromises.writeFile(task_list_path, JSON.stringify(task_list_json));
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}, "modifyFile", "modifyFile", "task_list")
|
||||
this.global.fileQueue.setSubBatchCompletionCallback("modifyFile", "task_list", async (failedTasks) => {
|
||||
// 报错
|
||||
if (failedTasks.length > 0) {
|
||||
let message = "";
|
||||
failedTasks.forEach(({ taskId, error }) => {
|
||||
message += `${taskId}-, \n 错误信息: ${error}` + '\n';
|
||||
});
|
||||
throw new Error(message);
|
||||
// this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
|
||||
// code: 0,
|
||||
// message: message
|
||||
// })
|
||||
}
|
||||
// else {
|
||||
// this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
|
||||
// code: 1,
|
||||
// message: "修改成功"
|
||||
// })
|
||||
// }
|
||||
return true;
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 高清指定的文件夹
|
||||
* @param {要高清的文件夹} folder
|
||||
*/
|
||||
async ImproveFolder(folder) {
|
||||
try {
|
||||
let bakPath = path.join(this.global.config.project_path, "tmp/bak");
|
||||
let oldInput = path.join(this.global.config.project_path, "tmp/" + folder);
|
||||
let newInput = path.join(this.global.config.project_path, "tmp/bak/" + folder)
|
||||
// 创建文件夹
|
||||
let existFolder = await this.tools.checkExists(bakPath);
|
||||
if (!existFolder) {
|
||||
await fspromises.mkdir(bakPath, { recursive: true });
|
||||
}
|
||||
|
||||
let isExistNewFolder = await this.tools.checkExists(newInput);
|
||||
if (isExistNewFolder) {
|
||||
await fspromises.rm(newInput, { recursive: true, force: true });
|
||||
}
|
||||
// 备份文件
|
||||
await fspromises.rename(oldInput, newInput);
|
||||
//创建同名的文件,用作输出
|
||||
await fspromises.mkdir(oldInput, { recursive: true });
|
||||
|
||||
// 开始高清
|
||||
let command = `"${path.join(define.package_path, "Improve/rnv.exe")}" -i "${newInput}" -o "${oldInput}"`;
|
||||
let out = await execAsync(command, { maxBuffer: 1024 * 1024 * 10, encoding: 'utf-8' });
|
||||
console.log(out);
|
||||
await this.ModifyTaskStatus('out_folder', folder, "video_improvied");
|
||||
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.VIDEO_GENERATE_STATUS_REFRESH, {
|
||||
out_folder: folder,
|
||||
status: "video_improvied"
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
await this.ModifyTaskStatus('out_folder', folder, "video_improvie_error");
|
||||
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.VIDEO_GENERATE_STATUS_REFRESH, {
|
||||
out_folder: folder,
|
||||
status: "video_improvie_error"
|
||||
})
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成SD相对的JSON文件。删除反推的txt文件
|
||||
*/
|
||||
async AddWebuiJson() {
|
||||
try {
|
||||
// 读取所有txt文件
|
||||
let txtfile = await this.tools.getFilesWithExtensions(path.join(this.global.config.project_path, 'tmp/input_crop'), '.txt');
|
||||
let image = await this.tools.getFilesWithExtensions(path.join(this.global.config.project_path, 'tmp/input_crop'), '.png');
|
||||
let promptJson = await this.tools.getFilesWithExtensions(path.join(this.global.config.project_path, 'tmp/input_crop'), '.json');
|
||||
|
||||
// json 已经存在,不做后续处理
|
||||
if (image.length == promptJson.length) {
|
||||
return {
|
||||
code: 1,
|
||||
}
|
||||
}
|
||||
|
||||
if (txtfile.length != image.length) {
|
||||
throw new Error("关键词文件和图片数量对不上,请检查!!")
|
||||
}
|
||||
let sd_config = JSON.parse(await fspromises.readFile(define.sd_setting, 'utf-8'));
|
||||
|
||||
for (let i = 0; i < image.length; i++) {
|
||||
const element = image[i];
|
||||
let txtpath = element.split('.png')[0] + '.txt';
|
||||
let prompt = await fspromises.readFile(txtpath, 'utf-8');
|
||||
// console.log(txtpath)
|
||||
let obj = {}
|
||||
obj.model = sd_config.setting.type;
|
||||
obj.api = sd_config.setting.webui_api_url + 'sdapi/v1/img2img';
|
||||
obj.webui_config = {
|
||||
sampler_name: sd_config.webui.sampler_name,
|
||||
prompt: prompt + ',' + sd_config.webui.prompt,
|
||||
negative_prompt: sd_config.webui.negative_prompt,
|
||||
batch_size: 1,
|
||||
steps: sd_config.webui.steps,
|
||||
cfg_scale: sd_config.webui.cfg_scale,
|
||||
denoising_strength: sd_config.webui.denoising_strength,
|
||||
width: sd_config.webui.width,
|
||||
height: sd_config.webui.height,
|
||||
seed: sd_config.setting.seed,
|
||||
init_images: element,
|
||||
}
|
||||
obj.adetailer = sd_config.webui.adetailer;
|
||||
|
||||
// 写入
|
||||
await fspromises.writeFile(element + '.json', JSON.stringify(obj));
|
||||
// 删除对应的txt文件
|
||||
await fspromises.unlink(txtpath);
|
||||
}
|
||||
|
||||
return {
|
||||
code: 1,
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前项目的生图任务列表
|
||||
*/
|
||||
async GetImageTask() {
|
||||
try {
|
||||
let json_path = path.join(this.global.config.project_path, "scripts/task_list.json");
|
||||
let isExit = await this.tools.checkExists(json_path);
|
||||
if (!isExit) {
|
||||
return {
|
||||
code: 1,
|
||||
data: null
|
||||
}
|
||||
}
|
||||
let json_data = JSON.parse(await fspromises.readFile(json_path));
|
||||
return {
|
||||
code: 1,
|
||||
data: json_data
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
code: 0,
|
||||
message: error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改任务的状态
|
||||
* @param {查找的类型 id out_folder} type
|
||||
* @param {查找的类型} id
|
||||
* @param {新的状态} newStatus
|
||||
*/
|
||||
async ModifyTaskStatus(type, id, newStatus) {
|
||||
this.global.fileQueue.enqueue(async () => {
|
||||
try {
|
||||
// 将修改数据写入到一个并发为 1 的队列中
|
||||
let tmp_task = await fspromises.readFile(path.join(this.global.config.project_path, 'scripts/task_list.json'), 'utf-8');
|
||||
console.log(tmp_task)
|
||||
let task = JSON.parse(tmp_task);
|
||||
if (type == "id") {
|
||||
let index = task.task_list.findIndex(item => item.id == id);
|
||||
if (index < 0) {
|
||||
throw new Error("传入的数据未找到");
|
||||
} else {
|
||||
task.task_list[index].status = newStatus;
|
||||
}
|
||||
} else if (type == "out_folder") {
|
||||
let index = task.task_list.findIndex(item => item.out_folder == id);
|
||||
if (index < 0) {
|
||||
throw new Error("传入的数据未找到");
|
||||
} else {
|
||||
task.task_list[index].status = newStatus;
|
||||
}
|
||||
} else {
|
||||
throw new Error("输入类型错误")
|
||||
}
|
||||
await fspromises.writeFile(path.join(this.global.config.project_path, 'scripts/task_list.json'), JSON.stringify(task));
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}, "modifyFile", "modifyFile", "task_list")
|
||||
this.global.fileQueue.setSubBatchCompletionCallback("modifyFile", "task_list", async (failedTasks) => {
|
||||
// 报错
|
||||
if (failedTasks.length > 0) {
|
||||
let message = "";
|
||||
failedTasks.forEach(({ taskId, error }) => {
|
||||
message += `${taskId}-, \n 错误信息: ${error}` + '\n';
|
||||
});
|
||||
|
||||
this.global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
|
||||
code: 0,
|
||||
message: message
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定文件夹下面特定条件的文件夹
|
||||
* @param {指定的文件夹目录} parentFolder
|
||||
* @param {查询条件 start end include} condition
|
||||
* @param {查询的值} value
|
||||
* @returns
|
||||
*/
|
||||
async getSubFolderList(parentFolder, condition, value) {
|
||||
try {
|
||||
// console.log(value);
|
||||
let folders = await fspromises.readdir(parentFolder, { withFileTypes: true });
|
||||
folders = folders.filter(item => item.isDirectory())
|
||||
.map(item => item.name)
|
||||
|
||||
if (condition == "start") {
|
||||
folders = folders.filter(item => item.startsWith(value));
|
||||
} else if (condition == "end") {
|
||||
folders = folders.filter(item => item.endsWith(value));
|
||||
} else if (condition == "include") {
|
||||
//包含过滤
|
||||
folders = folders.filter(item => item.includes(value));
|
||||
} else {
|
||||
throw new Error("条件参数错误");
|
||||
}
|
||||
return folders;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user