mirror of
https://github.com/YaoFANGUK/video-subtitle-remover.git
synced 2026-05-02 06:27:31 +08:00
添加PyInstaller打包支持和运行时路径修复
- 创建PyInstaller规范文件和打包脚本 - 修复开发/打包环境路径兼容性问题 - 添加PaddleOCR运行时依赖(opencv-contrib-python, pypdfium2, pyclipper) - 支持打包后的多进程启动 - 修复图标路径和翻译文件路径 - 清理重复的模型和FFmpeg文件 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from qfluentwidgets import (qconfig, ConfigItem, QConfig, OptionsValidator, BoolValidator, OptionsConfigItem,
|
||||
EnumSerializer, RangeValidator, RangeConfigItem, ConfigValidator)
|
||||
@@ -115,10 +116,16 @@ elif isinstance(_detect_mode_value, str) and _detect_mode_value in ("精准", "P
|
||||
# 读取界面语言配置
|
||||
tr = configparser.ConfigParser()
|
||||
|
||||
TRANSLATION_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'interface', f"{config.interface.value}.ini")
|
||||
# 确定运行环境(开发环境或打包环境)
|
||||
if getattr(sys, 'frozen', False):
|
||||
# 打包后的环境
|
||||
BASE_DIR = sys._MEIPASS
|
||||
TRANSLATION_FILE = os.path.join(BASE_DIR, 'backend', 'interface', f"{config.interface.value}.ini")
|
||||
else:
|
||||
# 开发环境
|
||||
BASE_DIR = str(Path(os.path.abspath(__file__)).parent.parent)
|
||||
TRANSLATION_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'interface', f"{config.interface.value}.ini")
|
||||
|
||||
tr.read(TRANSLATION_FILE, encoding='utf-8')
|
||||
|
||||
# 项目的base目录
|
||||
BASE_DIR = str(Path(os.path.abspath(__file__)).parent)
|
||||
|
||||
os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,4 +0,0 @@
|
||||
filename,filesize,encoding,header
|
||||
ffmpeg_1.exe,50000000,,
|
||||
ffmpeg_2.exe,50000000,,
|
||||
ffmpeg_3.exe,13721856,,
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +0,0 @@
|
||||
filename,filesize,encoding,header
|
||||
big-lama_1.pt,50000000,,
|
||||
big-lama_2.pt,50000000,,
|
||||
big-lama_3.pt,50000000,,
|
||||
big-lama_4.pt,50000000,,
|
||||
big-lama_5.pt,5803670,,
|
||||
|
@@ -38,11 +38,15 @@ def is_video_or_image(filename):
|
||||
return file_extension in video_extensions or file_extension in image_extensions
|
||||
|
||||
def merge_big_file_if_not_exists(dir, file, man_filename = None):
|
||||
if file not in os.listdir(dir):
|
||||
fs = Filesplit()
|
||||
if man_filename is not None:
|
||||
fs.man_filename = man_filename
|
||||
fs.merge(input_dir=dir)
|
||||
try:
|
||||
if file not in os.listdir(dir):
|
||||
fs = Filesplit()
|
||||
if man_filename is not None:
|
||||
fs.man_filename = man_filename
|
||||
fs.merge(input_dir=dir)
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not merge big file {file} in {dir}: {e}")
|
||||
return False
|
||||
|
||||
def get_readable_path(path):
|
||||
if sys.platform != 'win32':
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
import sys
|
||||
import stat
|
||||
|
||||
import platform
|
||||
@@ -21,16 +22,29 @@ class FFmpegCLI:
|
||||
return cls._instance
|
||||
|
||||
def __init__(self):
|
||||
os.chmod(self.ffmpeg_path, stat.S_IRWXU + stat.S_IRWXG + stat.S_IRWXO)
|
||||
|
||||
# 设置 FFmpeg 可执行文件权限
|
||||
try:
|
||||
os.chmod(self.ffmpeg_path, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not set ffmpeg executable permissions: {e}")
|
||||
|
||||
@property
|
||||
def ffmpeg_path(self):
|
||||
system = platform.system()
|
||||
|
||||
# 确保路径正确(打包环境 vs 开发环境)
|
||||
if getattr(sys, 'frozen', False):
|
||||
# 打包环境:BASE_DIR 指向 sys._MEIPASS
|
||||
base_path = os.path.join(BASE_DIR, 'backend')
|
||||
else:
|
||||
# 开发环境:BASE_DIR 已经是项目根目录
|
||||
base_path = BASE_DIR
|
||||
|
||||
if system == "Windows":
|
||||
ffmpeg_dir = os.path.join(BASE_DIR, 'ffmpeg', 'win_x64')
|
||||
ffmpeg_dir = os.path.join(base_path, 'ffmpeg', 'win_x64')
|
||||
merge_big_file_if_not_exists(ffmpeg_dir, 'ffmpeg.exe')
|
||||
return os.path.join(ffmpeg_dir, 'ffmpeg.exe')
|
||||
elif system == "Linux":
|
||||
return os.path.join(BASE_DIR, 'ffmpeg', 'linux_x64', 'ffmpeg')
|
||||
return os.path.join(base_path, 'ffmpeg', 'linux_x64', 'ffmpeg')
|
||||
else:
|
||||
return os.path.join(BASE_DIR, 'ffmpeg', 'macos', 'ffmpeg')
|
||||
return os.path.join(base_path, 'ffmpeg', 'macos', 'ffmpeg')
|
||||
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
import sys
|
||||
from backend.config import config, BASE_DIR
|
||||
from backend.tools.common_tools import merge_big_file_if_not_exists
|
||||
from backend.tools.constant import SubtitleDetectMode
|
||||
@@ -10,15 +11,34 @@ _MODEL_NAME_MAP = {
|
||||
|
||||
class ModelConfig:
|
||||
def __init__(self):
|
||||
self.LAMA_MODEL_DIR = os.path.join(BASE_DIR, 'models', 'big-lama')
|
||||
self.STTN_AUTO_MODEL_PATH = os.path.join(BASE_DIR, 'models', 'sttn-auto', 'infer_model.pth')
|
||||
self.STTN_DET_MODEL_PATH = os.path.join(BASE_DIR, 'models', 'sttn-det', 'sttn.pth')
|
||||
# 确保模型路径正确(打包环境 vs 开发环境)
|
||||
if getattr(sys, 'frozen', False):
|
||||
# 打包环境:BASE_DIR 指向 sys._MEIPASS
|
||||
model_base = os.path.join(BASE_DIR, 'backend')
|
||||
else:
|
||||
# 开发环境:BASE_DIR 已经是项目根目录
|
||||
model_base = BASE_DIR
|
||||
|
||||
self.LAMA_MODEL_DIR = os.path.join(model_base, 'models', 'big-lama')
|
||||
self.STTN_AUTO_MODEL_PATH = os.path.join(model_base, 'models', 'sttn-auto', 'infer_model.pth')
|
||||
self.STTN_DET_MODEL_PATH = os.path.join(model_base, 'models', 'sttn-det', 'sttn.pth')
|
||||
if config.subtitleDetectMode.value == SubtitleDetectMode.PP_OCRv5_MOBILE:
|
||||
self.DET_MODEL_DIR = os.path.join(BASE_DIR,'models', 'V5', 'ch_det_fast')
|
||||
self.DET_MODEL_DIR = os.path.join(model_base,'models', 'V5', 'ch_det_fast')
|
||||
elif config.subtitleDetectMode.value == SubtitleDetectMode.PP_OCRv5_SERVER:
|
||||
self.DET_MODEL_DIR = os.path.join(BASE_DIR, 'models', 'V5', 'ch_det')
|
||||
self.DET_MODEL_DIR = os.path.join(model_base, 'models', 'V5', 'ch_det')
|
||||
else:
|
||||
raise ValueError(f"Invalid subtitle detect mode: {config.subtitleDetectMode.value}")
|
||||
self.DET_MODEL_NAME = _MODEL_NAME_MAP[config.subtitleDetectMode.value]
|
||||
|
||||
merge_big_file_if_not_exists(self.LAMA_MODEL_DIR, 'bit-lama.pt')
|
||||
# 尝试合并大文件(如果需要)
|
||||
lama_file = 'big-lama.pt' # 修正文件名:实际模型文件是 big-lama.pt
|
||||
lama_file_path = os.path.join(self.LAMA_MODEL_DIR, lama_file)
|
||||
if not os.path.exists(lama_file_path):
|
||||
merge_big_file_if_not_exists(self.LAMA_MODEL_DIR, lama_file)
|
||||
# 检查合并后文件是否存在
|
||||
if not os.path.exists(lama_file_path):
|
||||
raise FileNotFoundError(
|
||||
f"LAMA model file not found: {lama_file_path}. "
|
||||
f"Please ensure the model file exists in {self.LAMA_MODEL_DIR}"
|
||||
)
|
||||
|
||||
|
||||
222
build_pinstaller.py
Normal file
222
build_pinstaller.py
Normal file
@@ -0,0 +1,222 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
基于官方 PaddleX 打包脚本改编的视频字幕去除器打包脚本
|
||||
"""
|
||||
|
||||
import importlib.metadata
|
||||
import argparse
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
def get_installed_packages():
|
||||
"""获取当前环境中已安装的包"""
|
||||
return [dist.metadata["Name"] for dist in importlib.metadata.distributions()]
|
||||
|
||||
def build_package(main_file, include_cuda=False):
|
||||
"""构建打包命令"""
|
||||
# 基础命令
|
||||
cmd = [
|
||||
"pyinstaller", main_file,
|
||||
"--clean",
|
||||
"--noconfirm",
|
||||
"--name", "VideoSubtitleRemover",
|
||||
"--icon", "design/vsr.ico",
|
||||
"--console", # 先启用控制台以便调试
|
||||
]
|
||||
|
||||
# 收集数据文件
|
||||
cmd += [
|
||||
"--add-data", "backend/models/big-lama;backend/models/big-lama",
|
||||
"--add-data", "backend/models/sttn-auto;backend/models/sttn-auto",
|
||||
"--add-data", "backend/models/sttn-det;backend/models/sttn-det",
|
||||
"--add-data", "backend/models/V5;backend/models/V5",
|
||||
"--add-data", "backend/interface;backend/interface",
|
||||
"--add-data", "backend/ffmpeg/win_x64/ffmpeg.exe;backend/ffmpeg/win_x64",
|
||||
"--add-data", "config/config.json;config",
|
||||
"--add-data", "design/vsr.ico;design",
|
||||
]
|
||||
|
||||
# 收集重要包的数据和二进制文件
|
||||
cmd += [
|
||||
"--collect-data", "paddleocr",
|
||||
"--collect-data", "skimage",
|
||||
"--collect-binaries", "paddle",
|
||||
"--collect-data", "opencv-python",
|
||||
"--collect-data", "cv2",
|
||||
]
|
||||
|
||||
# 隐藏导入
|
||||
hidden_imports = [
|
||||
# GUI 相关
|
||||
"PySide6.QtCore",
|
||||
"PySide6.QtGui",
|
||||
"PySide6.QtWidgets",
|
||||
"PySide6.QtNetwork",
|
||||
"qfluentwidgets",
|
||||
"qframelesswindow",
|
||||
|
||||
# 深度学习相关
|
||||
"torch",
|
||||
"torchvision",
|
||||
"paddle",
|
||||
"paddleocr",
|
||||
"paddleocr.ppocr",
|
||||
"paddleocr.ppocr.api",
|
||||
"paddleocr.ppocr.utils",
|
||||
|
||||
# 图像处理
|
||||
"cv2",
|
||||
"cv2.data",
|
||||
"cv2.matplotlib",
|
||||
"cv2.typing",
|
||||
"numpy",
|
||||
"PIL",
|
||||
"scipy",
|
||||
"scipy.spatial",
|
||||
"scipy.spatial.transform",
|
||||
"scipy.ndimage",
|
||||
|
||||
# 视频处理
|
||||
"av",
|
||||
|
||||
# 工具库
|
||||
"tqdm",
|
||||
"requests",
|
||||
"configparser",
|
||||
"einops",
|
||||
"darkdetect",
|
||||
"je_showinfilemanager",
|
||||
"filesplit",
|
||||
|
||||
# 项目模块
|
||||
"backend",
|
||||
"backend.inpaint",
|
||||
"backend.inpaint.lama_inpaint",
|
||||
"backend.inpaint.sttn_auto_inpaint",
|
||||
"backend.inpaint.sttn_det_inpaint",
|
||||
"backend.inpaint.opencv_inpaint",
|
||||
"backend.tools",
|
||||
"backend.tools.ocr",
|
||||
"backend.tools.subtitle_detect",
|
||||
"backend.tools.subtitle_remover_remote_call",
|
||||
"backend.tools.video_io",
|
||||
"backend.tools.ffmpeg_cli",
|
||||
"backend.tools.process_manager",
|
||||
"backend.tools.hardware_accelerator",
|
||||
"backend.tools.inpaint_tools",
|
||||
"backend.tools.common_tools",
|
||||
"backend.config",
|
||||
"backend.scenedetect",
|
||||
"ui",
|
||||
"ui.home_interface",
|
||||
"ui.advanced_setting_interface",
|
||||
"ui.setting_interface",
|
||||
"ui.component",
|
||||
"ui.component.video_display_component",
|
||||
"ui.component.task_list_component",
|
||||
"ui.icon.my_fluent_icon",
|
||||
]
|
||||
|
||||
for imp in hidden_imports:
|
||||
cmd += ["--hidden-import", imp]
|
||||
|
||||
# 排除不需要的模块
|
||||
excludes = [
|
||||
"pytest", "unittest", "test", "tests",
|
||||
"IPython", "jupyter", "notebook", "ipykernel",
|
||||
"paddle.fluid.contrib", "paddle.fluid.dygraph", "paddle.fluid.optimizer",
|
||||
"torch.utils.tensorboard", "torch.utils.bottleneck",
|
||||
"sphinx", "docutils", "pandas", "matplotlib", "seaborn",
|
||||
"scrapy", "beautifulsoup4", "lxml", "sklearn", "xgboost", "lightgbm",
|
||||
]
|
||||
|
||||
for exc in excludes:
|
||||
cmd += ["--exclude-module", exc]
|
||||
|
||||
# CUDA 支持
|
||||
if include_cuda:
|
||||
cmd += ["--collect-binaries", "nvidia"]
|
||||
print("注意: 包含 NVIDIA CUDA 依赖")
|
||||
|
||||
# 复制重要包的元数据(只复制确实存在的包)
|
||||
important_packages = ["PySide6", "paddleocr", "torch", "torchvision", "numpy", "opencv-python", "scipy", "Pillow", "opencv-contrib-python"]
|
||||
installed = get_installed_packages()
|
||||
|
||||
for pkg in important_packages:
|
||||
if pkg in installed:
|
||||
try:
|
||||
cmd += ["--copy-metadata", pkg]
|
||||
except:
|
||||
print(f"Warning: Could not copy metadata for {pkg}")
|
||||
continue
|
||||
|
||||
# UPX 压缩
|
||||
cmd += ["--upx-dir", "C:/upx"] if os.path.exists("C:/upx") else ["--noupx"]
|
||||
|
||||
return cmd
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="视频字幕去除器打包脚本")
|
||||
parser.add_argument('--file', default='gui.py', help='主文件名,默认为 gui.py')
|
||||
parser.add_argument('--nvidia', action='store_true', help='包含 NVIDIA CUDA 和 cuDNN 依赖')
|
||||
parser.add_argument('--console', action='store_true', help='显示控制台窗口(用于调试)')
|
||||
|
||||
args = parser.parse_args()
|
||||
main_file = args.file
|
||||
|
||||
if not os.path.exists(main_file):
|
||||
print(f"错误: 找不到文件 {main_file}")
|
||||
sys.exit(1)
|
||||
|
||||
print("========================================")
|
||||
print(" 视频字幕去除器 - PyInstaller 打包")
|
||||
print("========================================")
|
||||
print(f"主文件: {main_file}")
|
||||
print(f"CUDA 支持: {'是' if args.nvidia else '否'}")
|
||||
print(f"控制台: {'显示' if args.console else '隐藏'}")
|
||||
print()
|
||||
|
||||
# 构建命令
|
||||
cmd = build_package(main_file, include_cuda=args.nvidia)
|
||||
|
||||
# 如果不显示控制台,添加 --noconsole
|
||||
if not args.console:
|
||||
cmd.append("--noconsole")
|
||||
|
||||
print("PyInstaller 命令:")
|
||||
print(" ".join(cmd))
|
||||
print()
|
||||
print("开始打包,这可能需要几分钟...")
|
||||
print()
|
||||
|
||||
try:
|
||||
# 执行打包,使用当前Python环境(vsr环境)
|
||||
result = subprocess.run(cmd, check=True, env=os.environ.copy())
|
||||
print()
|
||||
print("========================================")
|
||||
print(" ✓ 打包成功完成!")
|
||||
print("========================================")
|
||||
print(f"输出目录: dist/VideoSubtitleRemover/")
|
||||
print()
|
||||
print("下一步:")
|
||||
print("1. 测试运行: dist/VideoSubtitleRemover/VideoSubtitleRemover.exe")
|
||||
print("2. 如果测试通过,可以删除 build/ 目录以节省空间")
|
||||
return 0
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
print()
|
||||
print("========================================")
|
||||
print(" ✗ 打包失败!")
|
||||
print("========================================")
|
||||
print(f"错误代码: {e.returncode}")
|
||||
print()
|
||||
print("故障排除:")
|
||||
print("1. 检查是否所有依赖都已安装: pip list")
|
||||
print("2. 查看详细错误日志: build/VideoSubtitleRemover/warn-VideoSubtitleRemover.txt")
|
||||
print("3. 尝试使用 --console 参数查看详细错误信息")
|
||||
return 1
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
115
build_windows.bat
Normal file
115
build_windows.bat
Normal file
@@ -0,0 +1,115 @@
|
||||
@echo off
|
||||
chcp 65001 >nul
|
||||
echo ========================================
|
||||
echo 视频字幕去除器 - PyInstaller 打包脚本
|
||||
echo ========================================
|
||||
echo.
|
||||
|
||||
REM 读取版本号
|
||||
for /f "tokens=2 delims='" %%a in ('findstr /C:"VERSION = " backend\config.py') do set VERSION=%%a
|
||||
echo 版本号: %VERSION%
|
||||
echo.
|
||||
|
||||
REM 检查是否安装了 PyInstaller
|
||||
python -c "import PyInstaller" 2>nul
|
||||
if errorlevel 1 (
|
||||
echo 错误: 未安装 PyInstaller
|
||||
echo 正在安装 PyInstaller...
|
||||
pip install pyinstaller
|
||||
if errorlevel 1 (
|
||||
echo 安装失败,请手动运行: pip install pyinstaller
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
)
|
||||
|
||||
REM 清理旧的构建文件
|
||||
echo [1/5] 清理旧的构建文件...
|
||||
if exist build rmdir /s /q build
|
||||
if exist dist rmdir /s /q dist
|
||||
echo ✓ 清理完成
|
||||
echo.
|
||||
|
||||
REM 执行 PyInstaller 打包
|
||||
echo [2/5] 开始 PyInstaller 打包...
|
||||
echo 这可能需要几分钟时间,请耐心等待...
|
||||
echo.
|
||||
pyinstaller --clean --noconfirm VideoSubtitleRemover.spec
|
||||
if errorlevel 1 (
|
||||
echo ✗ 打包失败!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
echo ✓ 打包完成
|
||||
echo.
|
||||
|
||||
REM 重命名输出目录
|
||||
echo [3/5] 重命名输出目录...
|
||||
set OUTPUT_NAME=VideoSubtitleRemover-Windows-v%VERSION%
|
||||
if exist dist\%OUTPUT_NAME% rmdir /s /q dist\%OUTPUT_NAME%
|
||||
move dist\VideoSubtitleRemover dist\%OUTPUT_NAME%
|
||||
if errorlevel 1 (
|
||||
echo ✗ 重命名失败!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
echo ✓ 重命名完成: %OUTPUT_NAME%
|
||||
echo.
|
||||
|
||||
REM 检查是否安装了 7z
|
||||
echo [4/5] 检查 7z 压缩工具...
|
||||
where 7z >nul 2>&1
|
||||
if errorlevel 1 (
|
||||
echo 警告: 未找到 7z,跳过压缩步骤
|
||||
echo 请手动安装 7-Zip: https://www.7-zip.org/
|
||||
goto :skip_compression
|
||||
)
|
||||
|
||||
REM 创建 7z 压缩包
|
||||
echo 开始压缩(可能需要几分钟)...
|
||||
cd dist\%OUTPUT_NAME%
|
||||
7z a -t7z -mx=9 -m0=LZMA2 -ms=on -mfb=64 -md=32m -mmt=on -v2000m "..\vsr-v%VERSION%-windows-cpu.7z" *
|
||||
cd ..\..
|
||||
|
||||
REM 检查是否只有一个分卷
|
||||
if exist "vsr-v%VERSION%-windows-cpu.7z.001" (
|
||||
if not exist "vsr-v%VERSION%-windows-cpu.7z.002" (
|
||||
rename "vsr-v%VERSION%-windows-cpu.7z.001" "vsr-v%VERSION%-windows-cpu.7z"
|
||||
echo ✓ 压缩完成(单文件)
|
||||
) else (
|
||||
echo ✓ 压缩完成(分卷)
|
||||
)
|
||||
) else if exist "vsr-v%VERSION%-windows-cpu.7z" (
|
||||
echo ✓ 压缩完成(单文件)
|
||||
) else (
|
||||
echo ✗ 压缩失败!
|
||||
goto :skip_compression
|
||||
)
|
||||
|
||||
:skip_compression
|
||||
echo.
|
||||
|
||||
REM 显示构建结果
|
||||
echo [5/5] 构建结果摘要
|
||||
echo ========================================
|
||||
echo 输出目录: dist\%OUTPUT_NAME%
|
||||
echo.
|
||||
|
||||
if exist "vsr-v%VERSION%-windows-cpu.7z" (
|
||||
echo 压缩包: vsr-v%VERSION%-windows-cpu.7z
|
||||
for %%F in ("vsr-v%VERSION%-windows-cpu.7z") do echo 文件大小: %%~zF 字节
|
||||
) else if exist "vsr-v%VERSION%-windows-cpu.7z.001" (
|
||||
echo 压缩包: vsr-v%VERSION%-windows-cpu.7z.* (分卷)
|
||||
)
|
||||
|
||||
echo.
|
||||
echo ========================================
|
||||
echo ✓ 构建成功完成!
|
||||
echo ========================================
|
||||
echo.
|
||||
echo 下一步操作:
|
||||
echo 1. 测试运行: dist\%OUTPUT_NAME%\VideoSubtitleRemover.exe
|
||||
echo 2. 分发压缩包(如果生成了)
|
||||
echo.
|
||||
|
||||
pause
|
||||
12
gui.py
12
gui.py
@@ -41,8 +41,14 @@ class SubtitleExtractorGUI(FluentWindow):
|
||||
# self.themeListener = SystemThemeListener(self)
|
||||
# self.themeListener.start()
|
||||
|
||||
# 设置窗口图标
|
||||
self.setWindowIcon(QtGui.QIcon("design/vsr.ico"))
|
||||
# 设置窗口图标(支持打包环境)
|
||||
if getattr(sys, 'frozen', False):
|
||||
# 打包后的环境
|
||||
icon_path = os.path.join(sys._MEIPASS, 'design', 'vsr.ico')
|
||||
else:
|
||||
# 开发环境
|
||||
icon_path = "design/vsr.ico"
|
||||
self.setWindowIcon(QtGui.QIcon(icon_path))
|
||||
self.setWindowTitle(tr['SubtitleExtractorGUI']['Title'] + " v" + VERSION)
|
||||
# 创建界面布局
|
||||
self._create_layout()
|
||||
@@ -162,6 +168,8 @@ class SubtitleExtractorGUI(FluentWindow):
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# 支持打包后的多进程
|
||||
multiprocessing.freeze_support()
|
||||
multiprocessing.set_start_method("spawn")
|
||||
QApplication.setHighDpiScaleFactorRoundingPolicy(
|
||||
Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import os
|
||||
import sys
|
||||
from enum import Enum
|
||||
|
||||
from qfluentwidgets import getIconColor, Theme, FluentIconBase
|
||||
@@ -8,4 +10,12 @@ class MyFluentIcon(FluentIconBase, Enum):
|
||||
|
||||
def path(self, theme=Theme.AUTO):
|
||||
# getIconColor() return "white" or "black" according to current theme
|
||||
return f'./ui/icon/{self.value}_{getIconColor(theme)}.svg'
|
||||
# 支持打包环境和开发环境
|
||||
if getattr(sys, 'frozen', False):
|
||||
# 打包环境:使用 sys._MEIPASS 作为基础路径
|
||||
base_path = sys._MEIPASS
|
||||
else:
|
||||
# 开发环境:使用相对路径
|
||||
base_path = os.path.join(os.path.dirname(__file__), '..')
|
||||
|
||||
return os.path.join(base_path, 'ui', 'icon', f'{self.value}_{getIconColor(theme)}.svg')
|
||||
|
||||
Reference in New Issue
Block a user