1. 移除软件包自带的本地 whisper(需单独安装) 2. 重构版本底层依赖,移除外部依赖 3. 修复 首页 暗黑模式不兼容的问题 4. 修复 SD 合并提示词报错
352 lines
10 KiB
Python
352 lines
10 KiB
Python
# 读取文件的方法
|
|
import json
|
|
import os
|
|
import win32api
|
|
import win32con
|
|
import pywintypes
|
|
import shutil
|
|
import re
|
|
|
|
|
|
class PublicTools:
|
|
"""
|
|
一些公用的基础方法
|
|
"""
|
|
|
|
def delete_path(self, path):
|
|
"""
|
|
删除指定路径的文件或者是文件夹
|
|
"""
|
|
# 检查路径是否存在
|
|
if not os.path.exists(path):
|
|
return
|
|
|
|
# 检查路径是文件还是文件夹
|
|
if os.path.isfile(path):
|
|
# 是文件,执行删除
|
|
try:
|
|
os.remove(path)
|
|
except Exception as e:
|
|
raise e
|
|
elif os.path.isdir(path):
|
|
# 是文件夹,执行删除
|
|
try:
|
|
shutil.rmtree(path)
|
|
except Exception as e:
|
|
raise e
|
|
else:
|
|
raise
|
|
|
|
def list_files_by_extension(self, folder_path, extension):
|
|
"""
|
|
读取指定文件夹下面的所有的指定拓展文件命的文件列表
|
|
"""
|
|
file_list = []
|
|
for root, dirs, files in os.walk(folder_path):
|
|
for file in files:
|
|
if file.endswith(extension):
|
|
file_list.append(os.path.join(root, file))
|
|
elif file.endswith(extension.upper()):
|
|
file_list.append(os.path.join(root, file))
|
|
return file_list
|
|
|
|
def get_fonts_from_registry(self, key_path):
|
|
"""
|
|
获取注册表中安装的字体文件
|
|
"""
|
|
font_names = []
|
|
try:
|
|
key = win32api.RegOpenKeyEx(
|
|
(
|
|
win32con.HKEY_LOCAL_MACHINE
|
|
if "HKEY_LOCAL_MACHINE" in key_path
|
|
else win32con.HKEY_CURRENT_USER
|
|
),
|
|
key_path.split("\\", 1)[1],
|
|
0,
|
|
win32con.KEY_READ,
|
|
)
|
|
i = 0
|
|
while True:
|
|
try:
|
|
value = win32api.RegEnumValue(key, i)
|
|
font_name = value[0]
|
|
# 使用正则表达式移除括号及其内容
|
|
font_name = re.sub(r"\s*\([^)]*\)$", "", font_name)
|
|
font_names.append(font_name)
|
|
i += 1
|
|
except pywintypes.error as e:
|
|
if e.winerror == 259: # 没有更多的数据
|
|
break
|
|
else:
|
|
raise
|
|
finally:
|
|
try:
|
|
win32api.RegCloseKey(key)
|
|
except:
|
|
pass
|
|
return font_names
|
|
|
|
def get_installed_fonts(self):
|
|
"""
|
|
获取字体文件名称并返回
|
|
"""
|
|
system_fonts = self.get_fonts_from_registry(
|
|
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"
|
|
)
|
|
user_fonts = self.get_fonts_from_registry(
|
|
"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"
|
|
)
|
|
all_fonts = list(set(system_fonts + user_fonts)) # 合并并去重
|
|
return all_fonts
|
|
|
|
# 将RRGGBB转换为BBGGRR
|
|
def convert_rrggbb_to_bbggrr(self, rrggbb):
|
|
"""
|
|
将RRGGBB转换为BBGGRR
|
|
"""
|
|
if len(rrggbb) == 7:
|
|
rr = rrggbb[1:3]
|
|
gg = rrggbb[3:5]
|
|
bb = rrggbb[5:7]
|
|
return bb + gg + rr
|
|
else:
|
|
return "Invalid input"
|
|
|
|
def write_to_file(self, arr, filename):
|
|
with open(filename, "w",encoding='utf-8') as f:
|
|
for item in arr:
|
|
f.write("%s\n" % item)
|
|
|
|
|
|
# 读取文件
|
|
def read_file(fileType):
|
|
txt_path = input(f"输入{fileType}文件路径:")
|
|
txt_path = remove_prefix_and_suffix(txt_path, '"', '"')
|
|
while txt_path.strip() == "":
|
|
txt_path = input(f"输入{fileType}文件路径:")
|
|
|
|
while os.path.exists(txt_path) == False:
|
|
print("文件路径不存在错误:")
|
|
txt_path = input(f"输入{fileType}文件路径:")
|
|
txt_path = remove_prefix_and_suffix(txt_path, '"', '"')
|
|
return txt_path
|
|
|
|
|
|
def format_time_ms(milliseconds):
|
|
"""
|
|
时间转换将ms->小时:分钟:秒.毫秒格式
|
|
"""
|
|
seconds = milliseconds / 1000
|
|
# 计算小时、分钟和秒
|
|
hours = int(seconds // 3600)
|
|
minutes = int((seconds % 3600) // 60)
|
|
seconds = seconds % 60
|
|
# 格式化字符串
|
|
# 使用`%02d`确保小时和分钟总是显示为两位数,`%.2f`确保秒数显示两位小数
|
|
formatted_time = f"{hours}:{minutes:02d}:{seconds:05.2f}"
|
|
return formatted_time
|
|
|
|
|
|
# 删除满足条件的开头和结尾
|
|
def remove_prefix_and_suffix(input_str, prefix_to_remove, suffix_to_remove):
|
|
if input_str.startswith(prefix_to_remove):
|
|
# 删除开头
|
|
input_str = input_str[len(prefix_to_remove) :]
|
|
|
|
if input_str.endswith(suffix_to_remove):
|
|
# 删除结尾
|
|
input_str = input_str[: -len(suffix_to_remove)]
|
|
|
|
return input_str
|
|
|
|
|
|
# 判断文件夹下面是不是有特定的文件夹
|
|
def check_if_folder_exists(parent_folder, target_folder_name):
|
|
# 获取文件夹列表
|
|
subfolders = [f.name for f in os.scandir(parent_folder) if f.is_dir()]
|
|
|
|
# 检查特定文件夹是否存在
|
|
if target_folder_name in subfolders:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
# 检查指定文件夹中是否存在特定文件。
|
|
def file_exists_in_folder(folder_path: str, file_name: str) -> bool:
|
|
# 构建完整的文件路径
|
|
file_path = os.path.join(folder_path, file_name)
|
|
|
|
# 返回文件是否存在
|
|
return os.path.isfile(file_path)
|
|
|
|
|
|
# 秒数转换,保留一位小数
|
|
def convert_to_seconds(number, count):
|
|
seconds = number / 1000000
|
|
rounded_number = round(seconds, count)
|
|
return rounded_number
|
|
|
|
|
|
def is_empty(obj):
|
|
if obj is None:
|
|
return True
|
|
elif isinstance(obj, str):
|
|
return len(obj) == 0
|
|
elif isinstance(obj, list):
|
|
return len(obj) == 0
|
|
elif isinstance(obj, dict):
|
|
return len(obj) == 0
|
|
return False
|
|
|
|
|
|
def opt_dict(obj, key, default=None):
|
|
if obj is None:
|
|
return default
|
|
if key in obj:
|
|
v = obj[key]
|
|
if not is_empty(v):
|
|
return v
|
|
return default
|
|
|
|
|
|
def read_config(path, webui=True):
|
|
with open(path, "r", encoding="utf-8") as f:
|
|
runtime_config = json.load(f)
|
|
|
|
if "config" not in runtime_config:
|
|
print("no filed 'config' in json")
|
|
return None
|
|
|
|
config = runtime_config["config"]
|
|
if "webui" not in config:
|
|
print("no filed 'webui' in 'config'")
|
|
return None
|
|
|
|
setting_config_path = config["setting"]
|
|
if not os.path.exists(setting_config_path):
|
|
setting_config_path = "config/" + setting_config_path
|
|
if not os.path.exists(setting_config_path):
|
|
setting_config_path = "../" + setting_config_path
|
|
|
|
# read config
|
|
with open(setting_config_path, "r", encoding="utf-8") as f:
|
|
setting_config = json.load(f)
|
|
|
|
# set workspace parent:根目录
|
|
if "workspace" in setting_config:
|
|
setting_config["workspace"]["parent"] = runtime_config["workspace"]
|
|
else:
|
|
setting_config["workspace"] = {"parent": runtime_config["workspace"]}
|
|
setting_config["video"] = opt_dict(runtime_config, "video")
|
|
|
|
# merge setting config
|
|
if "setting" in config:
|
|
setting_config.update(runtime_config["setting"])
|
|
|
|
# webui config
|
|
if webui:
|
|
webui_config_path = config["webui"]
|
|
if not os.path.exists(webui_config_path):
|
|
webui_config_path = "config/webui/" + webui_config_path
|
|
if not os.path.exists(webui_config_path):
|
|
webui_config_path = "../" + webui_config_path
|
|
|
|
with open(webui_config_path, "r", encoding="utf-8") as f:
|
|
webui_config = json.load(f)
|
|
|
|
# merge webui config
|
|
if "webui" in runtime_config:
|
|
webui_config.update(runtime_config["webui"])
|
|
|
|
return webui_config, setting_config
|
|
return setting_config
|
|
|
|
|
|
TAG_MODE_NONE = ""
|
|
|
|
|
|
# 工作路径
|
|
class Workspace:
|
|
|
|
def __init__(
|
|
self,
|
|
root: str,
|
|
input: str,
|
|
output: str,
|
|
input_crop: str,
|
|
output_crop: str,
|
|
input_tag: str,
|
|
input_mask: str,
|
|
input_crop_mask: str,
|
|
crop_info: str,
|
|
):
|
|
self.root = root
|
|
self.input = input
|
|
self.output = output
|
|
self.input_crop = input_crop
|
|
self.output_crop = output_crop
|
|
self.input_tag = input_tag
|
|
self.input_mask = input_mask
|
|
self.input_crop_mask = input_crop_mask
|
|
self.crop_info = crop_info
|
|
|
|
|
|
# 定义一个倍数函数
|
|
def round_up(num, mul):
|
|
return (num // mul + 1) * mul
|
|
|
|
|
|
class SettingConfig:
|
|
|
|
def __init__(self, config: dict, workParent):
|
|
self.config = config
|
|
self.webui_work_api = None
|
|
self.workParent = workParent
|
|
|
|
def to_dict(self):
|
|
return self.__dict__
|
|
|
|
def get_tag_mode(self):
|
|
tag_cfg = opt_dict(self.config, "tag")
|
|
return opt_dict(tag_cfg, "mode", TAG_MODE_NONE)
|
|
|
|
def get_tag_actions(self):
|
|
tag_cfg = opt_dict(self.config, "tag")
|
|
return opt_dict(tag_cfg, "actions", [])
|
|
|
|
def get_workspace_config(self) -> Workspace:
|
|
workspace_config = opt_dict(self.config, "workspace")
|
|
tmp_config = opt_dict(workspace_config, "tmp")
|
|
|
|
input = opt_dict(workspace_config, "input", "input")
|
|
output = opt_dict(workspace_config, "output", "output")
|
|
workspace_parent = self.workParent
|
|
|
|
tmp_parent = opt_dict(tmp_config, "parent", "tmp")
|
|
input_crop = opt_dict(tmp_config, "input_crop", "input_crop")
|
|
output_crop = opt_dict(tmp_config, "output_crop", "output_crop")
|
|
input_tag = opt_dict(tmp_config, "input_tag", "input_crop")
|
|
input_mask = opt_dict(tmp_config, "input_mask", "input_mask")
|
|
input_crop_mask = opt_dict(tmp_config, "input_crop_mask", "input_crop_mask")
|
|
crop_info = opt_dict(tmp_config, "crop_info", "crop_info.txt")
|
|
|
|
tmp_path = os.path.join(workspace_parent, tmp_parent)
|
|
|
|
return Workspace(
|
|
workspace_parent,
|
|
os.path.join(workspace_parent, input),
|
|
os.path.join(workspace_parent, output),
|
|
os.path.join(tmp_path, input_crop),
|
|
os.path.join(tmp_path, output_crop),
|
|
os.path.join(tmp_path, input_tag),
|
|
os.path.join(tmp_path, input_mask),
|
|
os.path.join(tmp_path, input_crop_mask),
|
|
os.path.join(tmp_path, crop_info),
|
|
)
|
|
|
|
def enable_tag(self):
|
|
tag_cfg = opt_dict(self.config, "tag")
|
|
return opt_dict(tag_cfg, "enable", True)
|