LaiTool/src/main/func.js

1119 lines
31 KiB
JavaScript
Raw Normal View History

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)
2024-09-12 14:13:09 +08:00
import { FLxuAPIImageType } from '../define/enum/image'
import JianyingService from './Service/jianying/jianyingService'
import VideoHandle from './Service/videoService/videoHandle'
import { successMessage } from './Public/generalTools'
2024-05-15 12:57:15 +08:00
/**
* 获取对应的轨道
*/
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
2024-05-15 12:57:15 +08:00
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 判断文件夹是不是存在
* @param {文件夹地址} folderPath
2024-05-15 12:57:15 +08:00
* @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
2024-05-15 12:57:15 +08:00
}
throw error
}
2024-05-15 12:57:15 +08:00
}
/**
* 保存新的字幕
* @param {洗稿后的值} value
2024-05-15 12:57:15 +08:00
*/
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
}
2024-05-15 12:57:15 +08:00
}
/**
* 提取草稿中的温馨提示全部提取直接用
* @param {} value
2024-05-15 12:57:15 +08:00
*/
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)
2024-05-15 12:57:15 +08:00
}
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)
}
2024-05-15 12:57:15 +08:00
}
/**
* 执行单张重绘的任务
* @param {执行操作的window} window
* @param {传入的值} value
* @returns
2024-05-15 12:57:15 +08:00
*/
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
2024-05-15 12:57:15 +08:00
}
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
2024-05-15 12:57:15 +08:00
}
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, {
2024-05-15 12:57:15 +08:00
id,
code: 1,
type: value[2]
})
})
.catch((err) => {
throw new Error(err)
})
} else {
throw new Error('SD 模式错误')
2024-05-15 12:57:15 +08:00
}
} 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: '加入队列成功'
}
2024-05-15 12:57:15 +08:00
}
/**
* 添加草稿
* @param {*} value
2024-05-15 12:57:15 +08:00
*/
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}`
2024-05-15 12:57:15 +08:00
}
}
2024-05-15 12:57:15 +08:00
}
/**
*
2024-05-15 12:57:15 +08:00
* @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())}`
2024-05-15 12:57:15 +08:00
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 获取剪映的草稿字体设置
* @param {传入草稿文件夹} value
2024-05-15 12:57:15 +08:00
* @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: '预设样式名称已存在'
}
}
2024-05-15 12:57:15 +08:00
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))
2024-05-15 12:57:15 +08:00
return {
code: 1
2024-05-15 12:57:15 +08:00
}
} catch (error) {
return {
code: 0,
message: `Error message ${error.toString()}`
}
}
return
2024-05-15 12:57:15 +08:00
}
/**
* 文案对齐
* @param {分镜的数据} value
2024-05-15 12:57:15 +08:00
*/
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
2024-05-15 12:57:15 +08:00
}
srt_list.push(obj)
i++
} else {
2024-05-15 12:57:15 +08:00
srt_obj.end_time = srt_list[srt_list.length - 1].end_time
text_count++
2024-05-15 12:57:15 +08:00
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
2024-05-15 12:57:15 +08:00
}
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}`
})
}
2024-05-15 12:57:15 +08:00
}
let pyrunner
2024-05-15 12:57:15 +08:00
function createPythonRunner(mainWindow, define) {
if (!pyrunner) {
pyrunner = new func.PythonRunner(mainWindow, define)
}
return pyrunner
2024-05-15 12:57:15 +08:00
}
/**
* 执行剪映图片对齐脚本
*/
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])
2024-05-15 12:57:15 +08:00
}
/**
* 抽取关键帧
* @param {窗口} mainWindow
* @param {数组第一个值为剪映草稿位置第二个值为输出目录} value
2024-05-15 12:57:15 +08:00
*/
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, package_path)
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()
2024-05-15 12:57:15 +08:00
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 反推调用脚本的方法
* @param {调用的窗口} win
2024-05-15 12:57:15 +08:00
*/
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()
2024-05-15 12:57:15 +08:00
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 执行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)
})
}
2024-05-15 12:57:15 +08:00
}
/**
* 判断当前文件夹下面的所有文件夹
* @param {需要获取的文件地址} srcPath
* @returns
2024-05-15 12:57:15 +08:00
*/
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 // 或者根据需要处理错误
}
2024-05-15 12:57:15 +08:00
}
/**
* 读取剪映草稿列表
* @returns 返回剪映草稿列表
*/
async function getDraftFileList() {
let draft_path = global.config.draft_path
let res = await getDirectories(draft_path)
return res
2024-05-15 12:57:15 +08:00
}
/**
* 修改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()
2024-05-15 12:57:15 +08:00
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 保存生成视频的简单配置
*/
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: '保存成功'
2024-05-15 12:57:15 +08:00
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 获取合成视频的配置信息包含基本设置字幕设置音频设置水印设置
*/
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
2024-05-15 12:57:15 +08:00
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 获取当前系统安装了的字体
* 使用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
2024-05-15 12:57:15 +08:00
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 保存字幕的配置信息
*/
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
2024-05-15 12:57:15 +08:00
}
}
}
await fspromises.writeFile(define.video_config, JSON.stringify(video_config))
return {
code: 1,
message: '添加成功'
2024-05-15 12:57:15 +08:00
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 删除视频配置的指定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
2024-05-15 12:57:15 +08:00
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 添加生图任务队列
* @param {传入的值} value
2024-05-15 12:57:15 +08:00
*/
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, '{}')
2024-05-15 12:57:15 +08:00
}
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
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 删除指定ID的值
* @param {ID} value
2024-05-15 12:57:15 +08:00
*/
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
})
}
2024-05-15 12:57:15 +08:00
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)
)
2024-05-15 12:57:15 +08:00
return {
code: 1
2024-05-15 12:57:15 +08:00
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 获取不想要的提示词
*/
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
2024-05-15 12:57:15 +08:00
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
2024-05-15 12:57:15 +08:00
}
/**
2024-05-15 12:57:15 +08:00
* 保存不想要的提示词
*/
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()
2024-05-15 12:57:15 +08:00
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 一键删除不想要的值
*/
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
2024-05-15 12:57:15 +08:00
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 打开购买 GPT 的网址
*/
async function openGptBuyUrl(value) {
OpenUrl(value)
2024-05-15 12:57:15 +08:00
}
/**
* 打开传入的网址
* @param {} value
2024-05-15 12:57:15 +08:00
*/
async function OpenUrl(value) {
shell.openExternal(value)
2024-05-15 12:57:15 +08:00
}
/**
* 获取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
2024-05-15 12:57:15 +08:00
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 保存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: '保存成功'
2024-05-15 12:57:15 +08:00
}
} catch (error) {
return {
code: 0,
message: error.toString()
}
}
2024-05-15 12:57:15 +08:00
}
/**
* 开始分镜
*/
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()
2024-05-15 12:57:15 +08:00
}
}
2024-05-15 12:57:15 +08:00
}
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
}