2024-10-20 23:19:22 +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'
|
|
|
|
|
|
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'
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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-10-20 23:19:22 +08:00
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 判断文件夹是不是存在
|
2024-10-20 23:19:22 +08:00
|
|
|
|
* @param {文件夹地址} folderPath
|
2024-05-15 12:57:15 +08:00
|
|
|
|
* @returns true/false
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function isDirectory(folderPath) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
}
|
2024-10-20 23:19:22 +08:00
|
|
|
|
throw error
|
|
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 保存新的字幕
|
2024-10-20 23:19:22 +08:00
|
|
|
|
* @param {洗稿后的值} value
|
2024-05-15 12:57:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async function SaveNewWord(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 提取草稿中的温馨提示,全部提取直接用
|
2024-10-20 23:19:22 +08:00
|
|
|
|
* @param {} value
|
2024-05-15 12:57:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async function GetDraftFriendlyReminder(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
}
|
2024-10-20 23:19:22 +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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 执行单张重绘的任务
|
2024-10-20 23:19:22 +08:00
|
|
|
|
* @param {执行操作的window} window
|
|
|
|
|
|
* @param {传入的值} value
|
|
|
|
|
|
* @returns
|
2024-05-15 12:57:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async function ReGenerateImageOne(window, value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
// 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
|
|
|
|
}
|
2024-10-20 23:19:22 +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
|
|
|
|
}
|
2024-10-20 23:19:22 +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,
|
2024-10-20 23:19:22 +08:00
|
|
|
|
code: 1,
|
|
|
|
|
|
type: value[2]
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch((err) => {
|
|
|
|
|
|
throw new Error(err)
|
|
|
|
|
|
})
|
|
|
|
|
|
} else {
|
|
|
|
|
|
throw new Error('SD 模式错误')
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
2024-10-20 23:19:22 +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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 添加草稿
|
2024-10-20 23:19:22 +08:00
|
|
|
|
* @param {*} value
|
2024-05-15 12:57:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async function addDraft(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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-10-20 23:19:22 +08:00
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2024-10-20 23:19:22 +08:00
|
|
|
|
*
|
2024-05-15 12:57:15 +08:00
|
|
|
|
* @returns 返回获取的字体样式的列表
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function getClipSetting(style_name) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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-10-20 23:19:22 +08:00
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取剪映的草稿字体设置
|
2024-10-20 23:19:22 +08:00
|
|
|
|
* @param {传入草稿文件夹} value
|
2024-05-15 12:57:15 +08:00
|
|
|
|
* @returns 返回样式字符串
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function getDraftTextStyle(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
|
2024-10-20 23:19:22 +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
|
|
|
|
|
2024-10-20 23:19:22 +08:00
|
|
|
|
return {
|
|
|
|
|
|
code: 1
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
2024-10-20 23:19:22 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
code: 0,
|
|
|
|
|
|
message: `Error message ${error.toString()}`
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 文案对齐
|
2024-10-20 23:19:22 +08:00
|
|
|
|
* @param {分镜的数据} value
|
2024-05-15 12:57:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async function alginDraftImgToText(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
}
|
2024-10-20 23:19:22 +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
|
2024-10-20 23:19:22 +08:00
|
|
|
|
text_count++
|
2024-05-15 12:57:15 +08:00
|
|
|
|
new_srt_list.push(srt_obj)
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-20 23:19:22 +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
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-20 23:19:22 +08:00
|
|
|
|
let pyrunner
|
2024-05-15 12:57:15 +08:00
|
|
|
|
|
|
|
|
|
|
function createPythonRunner(mainWindow, define) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
if (!pyrunner) {
|
|
|
|
|
|
pyrunner = new func.PythonRunner(mainWindow, define)
|
|
|
|
|
|
}
|
|
|
|
|
|
return pyrunner
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 执行剪映图片对齐脚本
|
|
|
|
|
|
*/
|
|
|
|
|
|
function alignDraftImage(mainWindow, value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 抽取关键帧
|
2024-10-20 23:19:22 +08:00
|
|
|
|
* @param {窗口} mainWindow
|
|
|
|
|
|
* @param {数组,第一个值为剪映草稿位置,第二个值为,输出目录} value
|
2024-05-15 12:57:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async function getFrame(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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-10-20 23:19:22 +08:00
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 反推调用脚本的方法
|
2024-10-20 23:19:22 +08:00
|
|
|
|
* @param {调用的窗口} win
|
2024-05-15 12:57:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async function PushBackPrompt() {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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-10-20 23:19:22 +08:00
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 执行Python脚本的类,包括了对python脚本的监听
|
|
|
|
|
|
*/
|
|
|
|
|
|
class PythonRunner extends EventEmitter {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 判断当前文件夹下面的所有文件夹
|
2024-10-20 23:19:22 +08:00
|
|
|
|
* @param {需要获取的文件地址} srcPath
|
|
|
|
|
|
* @returns
|
2024-05-15 12:57:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async function getDirectories(srcPath) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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() {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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-10-20 23:19:22 +08:00
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 保存生成视频的简单配置
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function SaveGeneralSetting(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
}
|
2024-10-20 23:19:22 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
code: 0,
|
|
|
|
|
|
message: error.toString()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取合成视频的配置信息。包含基本设置。字幕设置。音频设置。水印设置
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function GetVideoConfigMessage() {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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-10-20 23:19:22 +08:00
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取当前系统安装了的字体
|
|
|
|
|
|
* 使用python脚本实现
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function GetSystemInstallFontName() {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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-10-20 23:19:22 +08:00
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 保存字幕的配置信息
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function SaveAssConfig(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
}
|
2024-10-20 23:19:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
await fspromises.writeFile(define.video_config, JSON.stringify(video_config))
|
|
|
|
|
|
return {
|
|
|
|
|
|
code: 1,
|
|
|
|
|
|
message: '添加成功'
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
2024-10-20 23:19:22 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
code: 0,
|
|
|
|
|
|
message: error.toString()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 删除视频配置的指定ID
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function DeleteVideoConfig(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
// 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-10-20 23:19:22 +08:00
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 添加生图任务队列
|
2024-10-20 23:19:22 +08:00
|
|
|
|
* @param {传入的值} value
|
2024-05-15 12:57:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async function AddImageTask(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
}
|
2024-10-20 23:19:22 +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的值
|
2024-10-20 23:19:22 +08:00
|
|
|
|
* @param {ID} value
|
2024-05-15 12:57:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async function DeleteImageTaskList(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
|
2024-10-20 23:19:22 +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
|
|
|
|
|
2024-10-20 23:19:22 +08:00
|
|
|
|
return {
|
|
|
|
|
|
code: 1
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
2024-10-20 23:19:22 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
code: 0,
|
|
|
|
|
|
message: error.toString()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取不想要的提示词
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function GetBadPrompt() {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
}
|
2024-10-20 23:19:22 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
code: 0,
|
|
|
|
|
|
message: error.toString()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-20 23:19:22 +08:00
|
|
|
|
/**
|
2024-05-15 12:57:15 +08:00
|
|
|
|
* 保存不想要的提示词
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function SaveBadPrompt(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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-10-20 23:19:22 +08:00
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 一键删除不想要的值
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function DeleteBadPrompt() {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
}
|
2024-10-20 23:19:22 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
code: 0,
|
|
|
|
|
|
message: error.toString()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 打开购买 GPT 的网址
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function openGptBuyUrl(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
OpenUrl(value)
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 打开传入的网址
|
2024-10-20 23:19:22 +08:00
|
|
|
|
* @param {} value
|
2024-05-15 12:57:15 +08:00
|
|
|
|
*/
|
|
|
|
|
|
async function OpenUrl(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
shell.openExternal(value)
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取ADetailer配置列表
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function GetADetailerList() {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
}
|
2024-10-20 23:19:22 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
code: 0,
|
|
|
|
|
|
message: error.toString()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 保存ADetailer数据信息
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function SaveADetailerConfig(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
}
|
2024-10-20 23:19:22 +08:00
|
|
|
|
} catch (error) {
|
|
|
|
|
|
return {
|
|
|
|
|
|
code: 0,
|
|
|
|
|
|
message: error.toString()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 开始分镜
|
|
|
|
|
|
*/
|
|
|
|
|
|
async function StartStoryboarding(value) {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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-10-20 23:19:22 +08:00
|
|
|
|
}
|
2024-05-15 12:57:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export const func = {
|
2024-10-20 23:19:22 +08:00
|
|
|
|
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
|
|
|
|
|
|
}
|