LaiTool/src/main/func.js
lq1405 22cfe65dde 3.1.9 2024.10.28
1. (聚合推文)MJ反推、SD反推 添加剪映分镜
2. (聚合推文)完善SD反推分类(界面同MJ反推,些许不一致)
3. (聚合推文)完成一键合成视频(单个和批量)
4. 修改聚合推文进入界面小说批次任务表格样式
5. (聚合推文)完善一键重置
6. (聚合推文)完善一键删除
2024-10-28 18:38:11 +08:00

1119 lines
31 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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'
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)
import { FLxuAPIImageType } from '../define/enum/image'
import JianyingService from './Service/jianying/jianyingService'
import VideoHandle from './Service/videoService/videoHandle'
import { successMessage } from './Public/generalTools'
/**
* 获取对应的轨道
*/
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 : []
)
let prompt = sd_setting.webui.prompt + image_styles
// 拼接提示词
if (value[1].image_style != null) {
prompt += `((${value[1].image_style})),`
}
if (value[1].lora != null) {
prompt += `${value[1].lora},`
}
prompt += value[1].prompt
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 jianying = new JianyingService()
await jianying.GetDraftFrameAndText(draft_path, out_dir)
global.newWindow[0].win.webContents.send(DEFINE_STRING.SHOW_MESSAGE_DIALOG, {
code: 1,
message: '剪映关键帧抽取成功'
})
return {
code: 1,
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()
}
}
}
/**
* 反推调用脚本的方法
* @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_crop" "${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
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
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
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
sd_config.webui.adetailer = value.hasOwnProperty('adetailer')
? value.adetailer
: sd_config.webui.adetailer
if (!sd_config.flux) {
let model = {
model: value.flux_model ? value.flux_model : FLxuAPIImageType.FLUX
}
sd_config.flux = model
} else {
sd_config.flux.model = value.flux_model ? value.flux_model : FLxuAPIImageType.FLUX
}
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 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) {
OpenUrl(value)
}
/**
* 打开传入的网址
* @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 videoHandle = new VideoHandle()
await videoHandle.StartStoryboarding(value.video_path, value.sensitivity)
return successMessage(null, '分镜、抽帧、语音识别完成!')
} 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,
GetBadPrompt,
SaveBadPrompt,
DeleteBadPrompt,
openGptBuyUrl,
GetADetailerList,
SaveADetailerConfig,
OpenUrl,
StartStoryboarding
}