LaiTool/src/main/func.js

1130 lines
38 KiB
JavaScript
Raw Normal View History

2024-05-15 12:57:15 +08:00
const fspromises = require("fs").promises;
const { clipboard, shell, ipcRenderer } = require('electron');
const sharp = require('sharp');
const path = require("path");
const util = require('util');
const { spawn, exec } = require('child_process');
const execAsync = util.promisify(exec);
const { v4: uuidv4 } = require('uuid'); // 引入UUID库来生成唯一标识符
const EventEmitter = require('events');
import { define } from "../define/define";
import axios from "axios";
const { machineId } = require('node-machine-id')
import { DEFINE_STRING } from "../define/define_string";
import { ClipDraft } from "./Public/clipDraft";
import { Tools } from "./tools";
import { PublicMethod } from "./Public/publicMethod"
import { ImageStyleDefine } from "../define/iamgeStyleDefine";
let tools = new Tools();
let pm = new PublicMethod(global);
/**
* 获取对应的轨道
*/
function find_draft_node(nodes, type, value) {
for (let index = 0; index < nodes.length; index++) {
let node = nodes[index];
if (node[type] == value) {
return node
}
}
}
/**
* 判断文件夹是不是存在
* @param {文件夹地址} folderPath
* @returns true/false
*/
async function isDirectory(folderPath) {
try {
const stats = await fspromises.stat(folderPath);
return stats.isDirectory();
} catch (error) {
if (error.code === 'ENOENT') {
return false;
}
throw error;
}
}
/**
* 保存新的字幕
* @param {洗稿后的值} value
*/
async function SaveNewWord(value) {
let new_txt = path.join(global.config.project_path, "new_word.txt")
// 写到一个新的txt文件里面
let dataString = await tools.writeArrayToFile(value, new_txt);
clipboard.writeText(dataString);
return {
code: 1
}
}
/**
* 提取草稿中的温馨提示全部提取直接用
* @param {} value
*/
async function GetDraftFriendlyReminder(value) {
try {
// console.log(value);
let draft_content_json_path = path.join(global.config.draft_path, `${value[0]}/draft_content.json`);
let old_friendly_reminder_json = await getClipSetting("friendly_reminder_setting");
// 判断当前的名称是不是存在
if (old_friendly_reminder_json.code == 0) {
throw new Error(old_friendly_reminder_json.message)
}
let filter_value = old_friendly_reminder_json.value.filter(item => item.name == value[1]);
if (filter_value.length > 0) {
return {
code: 0,
message: "名字重复"
}
}
// 开始提取
let draft_json = JSON.parse(await fspromises.readFile(draft_content_json_path));
// console.log(draft_json)
let material_animations = draft_json.materials.material_animations[0];
let texts = draft_json.materials.texts[0];
let tracks = draft_json.tracks[1];
let text_value = JSON.parse(texts.content).text;
let obj = {
id: uuidv4(),
name: value[1],
material_animations,
texts,
tracks,
text_value: text_value
}
// console.log(obj)
// 开始写入
let clip_setting_json = JSON.parse(await fspromises.readFile(define.clip_setting));
clip_setting_json.friendly_reminder_setting.push(obj);
await fspromises.writeFile(define.clip_setting, JSON.stringify(clip_setting_json));
return {
code: 1
}
} catch (error) {
throw new Error(error);
}
}
/**
* 执行单张重绘的任务
* @param {执行操作的window} window
* @param {传入的值} value
* @returns
*/
async function ReGenerateImageOne(window, value) {
// console.log(value)
// 将任务加入队列
let sd_setting = JSON.parse(await fspromises.readFile(define.sd_setting, 'utf-8'));
global.requestQuene.enqueue(async () => {
let id = value[1].id;
try {
// 请求一次
let headers = { "Accept": "application/json", "Content-Type": "application/json" };
let image_path = value[1].image;
let json_path = path.join(path.dirname(path.dirname(image_path)), "input_crop/" + value[1].name + ".json");
let json = JSON.parse(await fspromises.readFile(json_path, 'utf-8'));
let tmp_image_path = image_path.split(".png")[0] + "_tmp.png";
let image_styles = await ImageStyleDefine.getImageStyleStringByIds(value[1].image_style_list ? value[1].image_style_list : []);
2024-05-24 13:46:19 +08:00
let prompt = sd_setting.webui.prompt + image_styles;
2024-05-15 12:57:15 +08:00
// 拼接提示词
if (value[1].image_style != null) {
prompt += `((${value[1].image_style})),`;
}
if (value[1].lora != null) {
prompt += `${value[1].lora},`;
}
prompt += value[1].prompt;
2024-05-24 13:46:19 +08:00
2024-06-01 15:08:22 +08:00
2024-05-15 12:57:15 +08:00
let model = value[1].model;
// 判断当前是不是有开修脸修手
let ADetailer = {
args: sd_setting.adetailer
};
// 判断请求的模式
if (model == "img2img") {
let web_api = global.config.webui_api_url + 'sdapi/v1/img2img'
let sd_config = json["webui_config"];
sd_config["seed"] = -1
// 拼接后的提示词
sd_config.prompt = prompt;
let init_image = sd_config.init_images;
let im = await fspromises.readFile(init_image, 'binary');
sd_config.init_images = [new Buffer.from(im, 'binary').toString('base64')];
sd_config.denoising_strength = value[1].denoising_strength;
if (value[1].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);
// console.log(response);
// 目前是单图出图
let images = response.data.images;
let imageData = Buffer.from(images[0].split(",", 1)[0], 'base64');
sharp(imageData)
.toFile(tmp_image_path)
.then(async () => {
// console.log("图生图成功" + image_path);
await tools.deletePngAndDeleteExifData(tmp_image_path, image_path);
window[0].win.webContents.send(DEFINE_STRING.REGENERATE_IMAGE_RETUN, { id, code: 1, type: value[2] });
})
.catch(err => {
throw new Error(err);
});
} else if (model == "txt2img") {
let body = {
"prompt": prompt,
"negative_prompt": value[1].negative_prompt,
"seed": -1,
"sampler_name": value[1].sampler_name,
// 提示词相关性
"cfg_scale": json.webui_config.cfg_scale,
"width": sd_setting.webui.width,
"height": sd_setting.webui.height,
"batch_size": 1,
"n_iter": 1,
"steps": json.webui_config.steps,
"save_images": false,
}
let web_api = global.config.webui_api_url + 'sdapi/v1/txt2img'
if (value[1].adetailer) {
let ta = {
ADetailer: ADetailer
}
body.alwayson_scripts = ta;
}
const response = await axios.post(web_api, body);
// console.log(response);
// 目前是单图出图
let images = response.data.images;
let imageData = Buffer.from(images[0].split(",", 1)[0], 'base64');
sharp(imageData)
.toFile(tmp_image_path)
.then(async () => {
// // console.log("生图成功" + image_path);
await tools.deletePngAndDeleteExifData(tmp_image_path, image_path);
window[0].win.webContents.send(DEFINE_STRING.REGENERATE_IMAGE_RETUN, { id, code: 1, type: value[2] });
})
.catch(err => {
throw new Error(err);
});
} else {
throw new Error("SD 模式错误");
}
} catch (error) {
window[0].win.webContents.send(DEFINE_STRING.REGENERATE_IMAGE_RETUN, {
id,
code: 0,
type: value[2],
message: `Error Message ${error}`
});
return;
}
}, value[1].id, DEFINE_STRING.QUEUE_BATCH.SD_BACKSTEP_GENERATE_IMAGE)
return {
code: 1,
message: "加入队列成功"
}
}
/**
* 添加草稿
* @param {*} value
*/
async function addDraft(value) {
try {
let clip = new ClipDraft(global, value);
let res = await clip.addDraft();
return res;
} catch (error) {
return {
code: 0,
message: `An error occurred: ${error}`
}
}
}
/**
*
* @returns 返回获取的字体样式的列表
*/
async function getClipSetting(style_name) {
try {
let clip_setting = JSON.parse(await fspromises.readFile(define.clip_setting));
return {
code: 1,
value: clip_setting[style_name]
}
} catch (error) {
return {
code: 0,
message: `Error message ${error, toString()}`
}
}
}
/**
* 获取剪映的草稿字体设置
* @param {传入草稿文件夹} value
* @returns 返回样式字符串
*/
async function getDraftTextStyle(value) {
let draft_path = path.join(global.config.draft_path, value[1].toString());
try {
// 判断当前的名字是不是存在
let name = value[0];
// 直接保存
let clip_setting = await fspromises.readFile(define.clip_setting);
let clip_setting_json = JSON.parse(clip_setting);
let exist_style = clip_setting_json.text_style;
let isExist = false;
exist_style.forEach(item => {
if (item.name == name) {
isExist = true;
}
});
if (isExist) {
return {
code: 0,
message: "预设样式名称已存在"
}
}
let draft_config = JSON.parse(await fspromises.readFile(path.join(draft_path, 'draft_content.json')));
let text = draft_config.materials.texts[0]
let content = text.content;
let text_json = JSON.parse(content);
let style = text_json.styles;
let srt_node = find_draft_node(draft_config.tracks, "type", "text").segments[0];
let clip = srt_node.clip;
let obj = {
name: value[0],
id: uuidv4(),
style,
font_size: text.font_size,
fonts: text.fonts.length > 0 ? text.fonts[0].title : "",
style_name: text.style_name,
clip,
ratio: draft_config.canvas_config.ratio
}
let text_style = clip_setting_json.text_style;
text_style.push(obj);
await fspromises.writeFile(define.clip_setting, JSON.stringify(clip_setting_json));
return {
code: 1,
}
} catch (error) {
return {
code: 0,
message: `Error message ${error.toString()}`
}
}
return;
}
/**
* 文案对齐
* @param {分镜的数据} value
*/
async function alginDraftImgToText(value) {
let draft_path = path.join(global.config.draft_path, value[0]);
let text_value = value[1];
try {
// 读取草稿
let draft_config = await fspromises.readFile(path.join(draft_path, 'draft_content.json'));
// 获取字幕轨道
let draft_config_json = JSON.parse(draft_config);
// 所有的字幕轨道里面的数据,读取出来
// 循环的时候,判断当前字幕是不是在第一行
let srt_nodes = find_draft_node(draft_config_json.tracks, "type", "text").segments;
let img_nodes = find_draft_node(draft_config_json.tracks, "type", "video").segments;
let srt_list = [];
let srt_obj = null
let new_srt_list = []
let text_count = 0;
for (let i = 0; i < srt_nodes.length;) {
const element = srt_nodes[i];
let material_id = element.material_id;
// 获取字幕内容,里面包含样式和内容
let srt_content = JSON.parse(find_draft_node(draft_config_json.materials.texts, "id", material_id).content);
let srt_value = srt_content.text;
// console.log(srt_value)
let start_time = element.target_timerange.start;
let end_time = element.target_timerange.start + element.target_timerange.duration;
let obj = {
start_time,
end_time,
srt_value
};
// 判断当前字幕是不是在当前句
if (tools.removePunctuationIncludingEllipsis(value[1][text_count]).includes(tools.removePunctuationIncludingEllipsis(srt_value))) {
if (srt_obj == null) {
srt_obj = {}
srt_obj.start_time = start_time;
srt_obj.value = srt_value;
}
else {
srt_obj.value = srt_obj.value + srt_value;
}
srt_list.push(obj);
i++;
} else {
srt_obj.end_time = srt_list[srt_list.length - 1].end_time;
text_count++;
new_srt_list.push(srt_obj)
srt_obj = null;
}
}
// 最后要和音频对齐
srt_obj.end_time = srt_list[srt_list.length - 1].end_time
let audio_nodes = find_draft_node(draft_config_json.tracks, "type", "audio");
if (audio_nodes != null) {
let endTime = audio_nodes.segments[0].target_timerange.duration;
srt_obj.end_time = endTime;
}
new_srt_list.push(srt_obj)
// 开始对齐
for (let i = 0; i < new_srt_list.length; i++) {
if (img_nodes.length < i) {
break;
}
if (i == 96) {
}
const element = new_srt_list[i];
let duration = 0;
if (i + 1 < new_srt_list.length) {
duration = new_srt_list[i + 1].start_time - element.start_time - 1;
} else {
duration = element.end_time - element.start_time;
}
img_nodes[i].source_timerange.duration = duration;
img_nodes[i].target_timerange.duration = duration;
img_nodes[i].target_timerange.start = element.start_time;
}
let draft_config_string = JSON.stringify(draft_config_json);
await fspromises.writeFile(path.join(draft_path, 'draft_content.json'), draft_config_string);
return {
code: 1
}
} catch (error) {
// console.log(error)
return define.error = {
code: 0,
message: `error message ${error}`
}
}
}
let pyrunner;
function createPythonRunner(mainWindow, define) {
if (!pyrunner) {
pyrunner = new func.PythonRunner(mainWindow, define);
}
return pyrunner;
}
/**
* 执行剪映图片对齐脚本
*/
function alignDraftImage(mainWindow, value) {
pyrunner = createPythonRunner(mainWindow, define);
let draft_path = path.join(global.config.draft_path, value)
pyrunner.runScript(path.join(define.scripts_path, "03_align_draft_image.py"), [draft_path])
}
/**
* 抽取关键帧
* @param {窗口} mainWindow
* @param {数组第一个值为剪映草稿位置第二个值为输出目录} value
*/
async function getFrame(value) {
try {
// let scriptPath = path.join(define.scripts_path, '00_clip.py');
// // 执行生成图片的脚本
// let script = `cd ${define.scripts_path} && python ${scriptPath} "${project_config_path}"`;
let draft_path = path.join(global.config.draft_path, value[0]).replaceAll("\\", "/");
let out_dir = path.join(value[1]).replaceAll("\\", "/")
let package_path = define.package_path.replaceAll("\\", "/");
// let command = `${path.join(define.scripts_path, "05_getgrame.exe")} "${draft_path}" "${out_dir}" "${package_path}"`
let command = `"${path.join(define.scripts_path, "Lai.exe")}" -k "${draft_path}" "${out_dir}" "${package_path}"`
const output = await execAsync(command, { maxBuffer: 1024 * 1024 * 10, encoding: 'utf-8' });
global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
code: 1,
message: "剪映关键帧抽取成功"
})
return {
code: 1,
message: output.stdout
}
} catch (error) {
global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
code: 0,
message: error.toString()
})
return {
code: 0,
message: error.toString()
}
}
}
/**
* 反推调用脚本的方法
* @param {调用的窗口} win
*/
async function PushBackPrompt() {
try {
let py_path = path.join(define.scripts_path, "Lai.exe");
let sd_config_path = define.sd_setting;
let script = `cd "${define.scripts_path}" && "${py_path}" -p "${sd_config_path.replaceAll('\\', '/')}" "input" "${global.config.project_path}"`;
const output = await execAsync(script, { maxBuffer: 1024 * 1024 * 10, encoding: 'utf-8' });
global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
code: 1,
message: "反推成功"
})
return {
code: 1,
data: output.stdout
}
} catch (error) {
global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
code: 0,
message: "反推错误。详情请见错误信息!"
})
return {
code: 0,
message: error.toString()
}
}
}
/**
* 执行Python脚本的类包括了对python脚本的监听
*/
class PythonRunner extends EventEmitter {
constructor(mainWindow, define) {
super();
this.mainWindow = mainWindow;
this.define = define;
}
runScript(scriptPath, args = []) {
const pythonProcess = spawn('python', [scriptPath, ...args]);
// 监听Python脚本的标准输出
pythonProcess.stdout.on('data', (data) => {
// console.log(data.toString("utf-8"))
this.mainWindow.webContents.send(DEFINE_STRING.PYTHON_OUTPUT, data.toString("utf-8"));
});
// 监听Python脚本的标准错误输出
pythonProcess.stderr.on('data', (data) => {
this.mainWindow.webContents.send(DEFINE_STRING.PYTHON_OUTPUT, data.toString("utf-8"));
});
// 监听子进程关闭事件
pythonProcess.on('close', (code) => {
let closeMessage = `Python script exited with code ${code}`;
// console.log(closeMessage);
this.mainWindow.webContents.send(DEFINE_STRING.PYTHON_CLOSE, closeMessage);
});
// 监听子进程错误事件
pythonProcess.on('error', (err) => {
let errorMessage = `Python script error: ${err}`;
this.mainWindow.webContents.send(DEFINE_STRING.PYTHON_OUTPUT, errorMessage);
});
}
}
/**
* 判断当前文件夹下面的所有文件夹
* @param {需要获取的文件地址} srcPath
* @returns
*/
async function getDirectories(srcPath) {
try {
const filesAndDirectories = await fspromises.readdir(srcPath, { withFileTypes: true });
const directories = filesAndDirectories
.filter(dirent => dirent.isDirectory())
.map(dirent => fspromises.stat(path.join(srcPath, dirent.name)));
const directoryStats = await Promise.all(directories);
// 将目录和它们的状态对象组合成一个数组
const directoriesWithStats = filesAndDirectories
.filter(dirent => dirent.isDirectory())
.map((dirent, index) => ({
name: dirent.name,
ctime: directoryStats[index].ctime
}));
// 按创建时间排序,最新的在前
directoriesWithStats.sort((a, b) => b.ctime - a.ctime);
// 提取排序后的目录名称
const sortedDirectories = directoriesWithStats.map(dirent => dirent.name);
return sortedDirectories;
} catch (error) {
console.error('Error reading directories:', error);
throw error; // 或者根据需要处理错误
}
}
/**
* 读取剪映草稿列表
* @returns 返回剪映草稿列表
*/
async function getDraftFileList() {
let draft_path = global.config.draft_path
let res = await getDirectories(draft_path)
return res;
}
/**
* 修改SD配置
*/
async function SaveSDConfig(value) {
try {
let sd_config = JSON.parse((await fspromises.readFile(define.sd_setting, "utf-8")).toString());
global.config.webui_api_url = value.webui_api_url || value.webui_api_url == '' ? value.webui_api_url : global.config.webui_api_url;
2024-06-01 15:08:22 +08:00
2024-05-15 12:57:15 +08:00
sd_config.setting.webui_api_url = value.webui_api_url || value.webui_api_url == "" ? value.webui_api_url : sd_config.setting.webui_api_url;
sd_config.setting.type = value.type ? value.type : sd_config.setting.type;
2024-05-24 13:46:19 +08:00
sd_config.setting.batch_size = value.batch_size ? value.batch_size : sd_config.setting.batch_size;
sd_config.setting.style_weight = value.style_weight ? value.style_weight : sd_config.setting.style_weight;
2024-06-01 15:08:22 +08:00
2024-05-15 12:57:15 +08:00
sd_config.webui.prompt = value.prompt || value.prompt == "" ? value.prompt : sd_config.webui.prompt;
sd_config.webui.negative_prompt = value.negative_prompt || value.negative_prompt == "" ? value.negative_prompt : sd_config.webui.negative_prompt;
sd_config.webui.denoising_strength = value.denoising_strength || value.denoising_strength == "" ? value.denoising_strength : sd_config.webui.denoising_strength;
sd_config.webui.sampler_name = value.sampler_name ? value.sampler_name : sd_config.webui.sampler_name;
sd_config.webui.steps = value.steps ? value.steps : sd_config.webui.steps;
sd_config.webui.width = value.width ? value.width : sd_config.webui.width;
sd_config.webui.height = value.height ? value.height : sd_config.webui.height;
sd_config.webui.cfg_scale = value.cfg_scale ? value.cfg_scale : sd_config.webui.cfg_scale;
2024-06-06 13:12:04 +08:00
sd_config.webui.adetailer = value.hasOwnProperty("adetailer") ? value.adetailer : sd_config.webui.adetailer;
2024-05-15 12:57:15 +08:00
await fspromises.writeFile(define.sd_setting, JSON.stringify(sd_config));
return {
code: 1,
message: "保存成功"
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
}
/**
* 保存生成视频的简单配置
*/
async function SaveGeneralSetting(value) {
try {
// 先读取
let config_data = JSON.parse((await fspromises.readFile(define.video_config, 'utf-8')).toString());
await fspromises.writeFile(define.video_config, JSON.stringify(value));
return {
code: 1,
message: "保存成功"
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
}
/**
* 获取合成视频的配置信息包含基本设置字幕设置音频设置水印设置
*/
async function GetVideoConfigMessage() {
try {
let data = JSON.parse((await fspromises.readFile(define.video_config, 'utf-8')).toString());
return {
code: 1,
data: data
}
} catch (error) {
return {
code: 0,
message: error.message
}
}
}
/**
* 获取当前系统安装了的字体
* 使用python脚本实现
*/
async function GetSystemInstallFontName() {
try {
// 执行python
let scriptPath = path.join(define.scripts_path, 'Lai.exe');
// let scriptPath = path.join(define.scripts_path, '00_clip.exe');
// 执行生成图片的脚本
let script = `cd "${define.scripts_path}" && "${scriptPath}" -f "${define.video_config.replaceAll("\\", "/")}"`;
const output = await execAsync(script, { maxBuffer: 1024 * 1024 * 10, encoding: 'utf-8' });
return {
code: 1,
}
} catch (error) {
return {
code: 0,
message: error
}
}
}
/**
* 保存字幕的配置信息
*/
async function SaveAssConfig(value) {
try {
let video_config = JSON.parse(await fspromises.readFile(define.video_config, 'utf8'));
// 判断ID是不是存在。存在的话直接修改。不存在创建
if (value[1].id == null) {
value[1].id = uuidv4();
video_config[value[0]].push(value[1]);
} else {
let index = video_config[value[0]].findIndex(item => item.id == value[1].id);
if (index !== -1) {
let old = video_config[value[0]][index];
old.fontName = value[1].fontName;
old.fontSize = value[1].fontSize;
old.fontColor = value[1].fontColor;
old.transparent = value[1].transparent;
old.positionX = value[1].positionX;
old.positionY = value[1].positionY;
if (value[0] == "watermarkConfig") {
old.showText = value[1].showText;
}
}
}
await fspromises.writeFile(define.video_config, JSON.stringify(video_config));
return {
code: 1,
message: "添加成功"
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
}
/**
* 删除视频配置的指定ID
*/
async function DeleteVideoConfig(value) {
// console.log(value)
try {
let video_config = JSON.parse(await fspromises.readFile(define.video_config, 'utf-8'));
video_config[value[0]] = video_config[value[0]].filter(item => item.id != value[1]);
await fspromises.writeFile(define.video_config, JSON.stringify(video_config));
return {
code: 1
}
} catch (error) {
return {
code: 0,
message: error
}
}
}
/**
* 添加生图任务队列
* @param {传入的值} value
*/
async function AddImageTask(value) {
try {
// 判断文件目录是不是存在
let json_path = path.join(global.config.project_path, "scripts/task_list.json");
// 判断文件是不是存在
let isExit = await tools.checkExists(json_path);
let json_data = {};
if (!isExit) {
const dirPath = path.dirname(json_path);
let dirIsExit = await tools.checkExists(dirPath);
if (!dirIsExit) {
await fspromises.mkdir(dirPath, { recursive: true });
}
await fspromises.writeFile(json_path, '{}');
}
let task_list = [];
let task_list_data = await pm.GetImageTask();
if (task_list_data.code == 0) {
return task_list_data;
}
// 获取当前的最大的任务编号
let current_no = 0;
if (task_list_data.data != null && task_list_data.data.task_list != null) {
if (task_list_data.data.task_list.length > 0) {
const maxNoObject = task_list_data.data.task_list.reduce((max, obj) => obj.no > max.no ? obj : max, task_list_data.data.task_list[0]);
current_no = maxNoObject.no;
task_list = task_list_data.data.task_list;
}
}
// 循环输出轮次,往里面添加数据
for (let i = 0; i < value.output_rounds; i++) {
task_list.push({
id: uuidv4(),
no: current_no + i + 1,
lora: value.lora,
out_folder: 'output_crop_' + String(current_no + i + 1).padStart(5, '0'),
image_style: value.image_style,
image_style_list: value.image_style_list,
status: "wait"
})
}
// 写入
task_list_data.data.task_list = task_list;
let write_data = task_list_data.data;
await fspromises.writeFile(json_path, JSON.stringify(write_data));
return {
code: 1,
data: write_data
}
} catch (error) {
return {
code: 0,
message: error
}
}
}
/**
* 删除指定ID的值
* @param {ID} value
*/
async function DeleteImageTaskList(value) {
try {
// 判断当前的状态。是不是可以删除。正在生成的文件不能删除
// 目前先是直接删除
let task_list = JSON.parse(await fspromises.readFile(path.join(global.config.project_path, 'scripts/task_list.json'), 'utf-8'));
// 判断状态,删除指定的输出文件夹
let d_t = task_list.task_list.filter(item => item.id == value)[0];
// ok 状态删除对应的输出文件夹
if (d_t.status == "ok" || d_t.status == "error" || d_t.status.startsWith("video")) {
await fspromises.rm(path.join(global.config.project_path, 'tmp/' + d_t.out_folder), { recursive: true, force: true });
}
let new_data = task_list.task_list.filter(item => item.id != value);
task_list.task_list = new_data;
await fspromises.writeFile(path.join(global.config.project_path, 'scripts/task_list.json'), JSON.stringify(task_list));
return {
code: 1
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
}
/**
* 获取指定的机械码
*/
async function GetMachineId() {
try {
let id = await machineId(true);
2024-06-24 13:11:19 +08:00
global.machineId = id;
2024-05-15 12:57:15 +08:00
return {
code: 1,
value: id
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
}
/**
* 获取不想要的提示词
*/
async function GetBadPrompt() {
try {
let sd_config = JSON.parse(await fspromises.readFile(define.sd_setting, 'utf-8'));
return {
code: 1,
value: sd_config.tag.badPrompt
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
}
/**
* 保存不想要的提示词
*/
async function SaveBadPrompt(value) {
try {
let tag = value.join(',');
// 写入
let sd_config = JSON.parse(await fspromises.readFile(define.sd_setting, 'utf-8'));
sd_config.tag.badPrompt = tag;
await fspromises.writeFile(define.sd_setting, JSON.stringify(sd_config));
return {
code: 1,
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
}
/**
* 一键删除不想要的值
*/
async function DeleteBadPrompt() {
try {
let sd_config = JSON.parse(await fspromises.readFile(define.sd_setting, 'utf-8'));
let badPrompt = sd_config.tag.badPrompt;
let badPrompts = [];
if (badPrompt != null) {
badPrompts = badPrompt.split(',');
}
// 修改所有的提示词
let promptPath = await tools.getFilesWithExtensions(path.join(global.config.project_path, 'tmp/input_crop'), '.txt');
for (let i = 0; i < promptPath.length; i++) {
const item = promptPath[i];
let txtStr = await fspromises.readFile(item, 'utf-8');
let tags = txtStr.split(',');
tags = tags.filter(d => !badPrompts.includes(d));
// 重新写入
await fspromises.writeFile(item, tags.join(','));
}
return {
code: 1,
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
}
/**
* 打开购买 GPT 的网址
*/
async function openGptBuyUrl(value) {
2024-06-01 15:08:22 +08:00
OpenUrl(value)
2024-05-15 12:57:15 +08:00
}
/**
* 打开传入的网址
* @param {} value
*/
async function OpenUrl(value) {
shell.openExternal(value)
}
/**
* 获取ADetailer配置列表
*/
async function GetADetailerList() {
try {
console.log(123);
let sd_setting = JSON.parse(await fspromises.readFile(define.sd_setting, 'utf-8'));
return {
code: 1,
data: sd_setting.adetailer
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
}
/**
* 保存ADetailer数据信息
*/
async function SaveADetailerConfig(value) {
try {
let sd_config = JSON.parse(await fspromises.readFile(define.sd_setting, 'utf-8'));
sd_config.adetailer = value;
await fspromises.writeFile(define.sd_setting, JSON.stringify(sd_config));
return {
code: 1,
message: "保存成功"
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
}
/**
* 开始分镜
*/
async function StartStoryboarding(value) {
try {
// 判断文件夹是不是存在,不存在创建
let frame_path = path.join(global.config.project_path, "data/frame");
let isExist = await tools.checkExists(frame_path);
if (isExist) {
await tools.deleteFileOrDirectory(frame_path);
await fspromises.mkdir(frame_path, { recursive: true });
} else {
await fspromises.mkdir(frame_path, { recursive: true });
}
let tmp_path = path.join(global.config.project_path, "tmp");
isExist = await tools.checkExists(tmp_path);
if (!isExist) {
await fspromises.mkdir(tmp_path, { recursive: true });
}
let input_path = path.join(global.config.project_path, "tmp/input_crop");
isExist = await tools.checkExists(input_path);
if (isExist) {
await tools.deleteFileOrDirectory(input_path);
await fspromises.mkdir(input_path, { recursive: true });
} else {
await fspromises.mkdir(input_path, { recursive: true });
}
global.newWindow[0].win.webContents.send(DEFINE_STRING.GET_FRAME_RETUN, { code: 1, data: "正在调用进程。请勿关闭程序" })
let cc = `${path.join(define.scripts_path, 'Lai.exe')}`;
2024-06-13 00:37:31 +08:00
// 获取生成视频设置
let video_config = JSON.parse(await fspromises.readFile(define.video_config, 'utf-8'));
let gpu = global.gpu.type;
if (video_config.libx264) {
gpu = "OTHER";
}
let child = spawn(cc, ["-a", value.video_path, frame_path, input_path, value.sensitivity, gpu], { encoding: 'utf-8' });
2024-05-15 12:57:15 +08:00
child.on('error', console.error)
child.stdout.on('data', (data) => {
console.log(data.toString());
global.newWindow[0].win.webContents.send(DEFINE_STRING.GET_FRAME_RETUN, { code: 1, data: data.toString() })
})
child.stderr.on('data', (data) => {
console.log('stderr=', data.toString())
global.newWindow[0].win.webContents.send(DEFINE_STRING.GET_FRAME_RETUN, { code: 1, data: data.toString() })
})
child.on('close', async (data) => {
console.log('data=', data.toString())
// 判断该当前文件夹下面是不是有文案文件。有的话判断最后一行是不是空
let isE = await tools.checkExists(path.join(global.config.project_path, "data/文案.txt"));
if (isE) {
let lines = (await fspromises.readFile(path.join(global.config.project_path, "data/文案.txt"), 'utf-8')).split(/\r?\n/);
let lastLine = lines[lines.length - 1];
if (lastLine == "") {
lines = lines.slice(0, -1);
}
await fspromises.writeFile(path.join(global.config.project_path, "文案.txt"), lines.join('\n'), 'utf-8');
}
global.newWindow[0].win.webContents.send(DEFINE_STRING.GET_FRAME_RETUN, { code: 1, data: data.toString(), type: 0 })
if (data == 0) {
global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, { code: 1, message: "分镜、抽帧、语音识别完成!" })
} else {
global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, { code: 0, message: "分镜错误。请看详细信息!" })
}
})
} catch (error) {
global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, { code: 0, message: error.toString() })
return {
code: 0, message: error.toString()
}
}
}
export const func = {
getDraftFileList,
PythonRunner,
getFrame,
alignDraftImage,
alginDraftImgToText,
getDraftTextStyle,
getClipSetting,
addDraft,
ReGenerateImageOne,
PushBackPrompt,
GetDraftFriendlyReminder,
SaveNewWord,
SaveSDConfig,
SaveGeneralSetting,
GetVideoConfigMessage,
GetSystemInstallFontName,
SaveAssConfig,
DeleteVideoConfig,
AddImageTask,
DeleteImageTaskList,
GetMachineId,
GetBadPrompt,
SaveBadPrompt,
DeleteBadPrompt,
openGptBuyUrl,
GetADetailerList,
SaveADetailerConfig,
OpenUrl,
StartStoryboarding
}