diff --git a/.gitignore b/.gitignore index e69685b..fd3441c 100644 --- a/.gitignore +++ b/.gitignore @@ -373,5 +373,5 @@ test*_no_sub*.mp4 /backend/models/big-lama/big-lama.pt /test/debug/ /backend/tools/train/release_model/ -model.onnx +inference.onnx /config/config.json diff --git a/README.md b/README.md index 5fff328..ac23b86 100755 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ cd <源码所在目录> #### 4. 安装合适的运行环境 -本项目支持 CUDA(NVIDIA显卡加速)、CPU(无 GPU)和 DirectML(AMD、Intel等GPU/APU加速)三种运行模式。 +本项目支持 CUDA (NVIDIA显卡加速)、CPU (无 GPU)、 DirectML (AMD、Intel等GPU/APU加速) 和 macOS (Apple Silicon) 四种运行模式。 ##### (1) CUDA(NVIDIA 显卡用户) @@ -198,7 +198,16 @@ cd <源码所在目录> pip install torch==2.7.0 torchvision==0.22.0 pip install -r requirements.txt ``` - +##### (4) macOS 运行 (Apple Silicon) +- 适用于 macOS (Apple Silicon) 设备 +- macOS (Intel) 请使用CPU, 强行使用GPU只会更慢 +- macOS (Apple Silicon)上字幕检测精准模式的模型(ch_det_fast/model.onnx)精度似乎不太理想, 推荐使用快速模式 + ```shell + pip install paddlepaddle==3.0.0 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/ + pip install torch==2.7.0 torchvision==0.22.0 + pip install -r requirements.txt + ``` + > 基于Python3.13版本测试 #### 4. 运行程序 - 运行图形化界面 diff --git a/README_en.md b/README_en.md index f8caf40..d8023e2 100755 --- a/README_en.md +++ b/README_en.md @@ -133,7 +133,7 @@ cd #### 4. Install the Appropriate Runtime Environment -This project supports three runtime modes: CUDA (NVIDIA GPU acceleration), CPU (no GPU) and DirectML (AMD, Intel, and other GPUs/APUs). +This project supports four running modes: CUDA (NVIDIA GPU acceleration), CPU (no GPU), DirectML (AMD, Intel and other GPU/APU acceleration), and macOS (Apple Silicon). ##### (1) CUDA (For NVIDIA GPU users) @@ -199,6 +199,17 @@ This project supports three runtime modes: CUDA (NVIDIA GPU acceleration), CPU ( pip install -r requirements.txt ``` +##### (4) Running on macOS (Apple Silicon) +- Suitable for macOS (Apple Silicon) devices +- For macOS (Intel), please use the CPU mode. Forcing GPU usage will only be slower. +- On macOS (Apple Silicon), the accuracy of the subtitle detection precision mode model (ch_det_fast/model.onnx) does not seem to be ideal. It is recommended to use the fast mode instead. + ```shell + pip install paddlepaddle==3.0.0 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/ + pip install torch==2.7.0 torchvision==0.22.0 + pip install -r requirements.txt + ``` + > Tested with Python 3.13 + #### 4. Run the program - Run the graphical interface diff --git a/backend/main.py b/backend/main.py index 930c0dd..26340a4 100644 --- a/backend/main.py +++ b/backend/main.py @@ -395,7 +395,7 @@ class SubtitleRemover: accelerator_name = self.hardware_accelerator.accelerator_name if accelerator_name == 'DirectML' and config.inpaintMode.value in [InpaintMode.STTN_AUTO, InpaintMode.STTN_DET]: model_device = 'DirectML' - if self.hardware_accelerator.has_cuda(): + if self.hardware_accelerator.has_cuda() or self.hardware_accelerator.has_mps(): model_device = accelerator_name self.append_output(tr['Main']['UseModel'].format(f"{model_friendly_name} ({model_device})")) @@ -446,7 +446,7 @@ class SubtitleRemover: @cached_property def lama_inpaint(self): model_path = os.path.join(self.model_config.LAMA_MODEL_DIR, 'big-lama.pt') - device = self.hardware_accelerator.device if self.hardware_accelerator.has_cuda() else torch.device("cpu") + device = self.hardware_accelerator.device if self.hardware_accelerator.has_cuda() or self.hardware_accelerator.has_mps() else torch.device("cpu") return LamaInpaint(device, model_path) @cached_property diff --git a/backend/models/V4/ch_det/fs_manifest.csv b/backend/models/V4/ch_det/fs_manifest.csv deleted file mode 100644 index 9cc6786..0000000 --- a/backend/models/V4/ch_det/fs_manifest.csv +++ /dev/null @@ -1,4 +0,0 @@ -filename,filesize,encoding,header -inference_1.pdiparams,50000000,, -inference_2.pdiparams,50000000,, -inference_3.pdiparams,13295054,, diff --git a/backend/models/V4/ch_det/inference.pdiparams.info b/backend/models/V4/ch_det/inference.pdiparams.info deleted file mode 100644 index 272488f..0000000 Binary files a/backend/models/V4/ch_det/inference.pdiparams.info and /dev/null differ diff --git a/backend/models/V4/ch_det/inference.pdmodel b/backend/models/V4/ch_det/inference.pdmodel deleted file mode 100644 index 1579721..0000000 Binary files a/backend/models/V4/ch_det/inference.pdmodel and /dev/null differ diff --git a/backend/models/V4/ch_det/inference_3.pdiparams b/backend/models/V4/ch_det/inference_3.pdiparams deleted file mode 100644 index 030d488..0000000 Binary files a/backend/models/V4/ch_det/inference_3.pdiparams and /dev/null differ diff --git a/backend/models/V4/ch_det_fast/inference.pdiparams b/backend/models/V4/ch_det_fast/inference.pdiparams deleted file mode 100644 index 089594a..0000000 Binary files a/backend/models/V4/ch_det_fast/inference.pdiparams and /dev/null differ diff --git a/backend/models/V4/ch_det_fast/inference.pdiparams.info b/backend/models/V4/ch_det_fast/inference.pdiparams.info deleted file mode 100644 index 082c148..0000000 Binary files a/backend/models/V4/ch_det_fast/inference.pdiparams.info and /dev/null differ diff --git a/backend/models/V4/ch_det_fast/inference.pdmodel b/backend/models/V4/ch_det_fast/inference.pdmodel deleted file mode 100644 index 223b861..0000000 Binary files a/backend/models/V4/ch_det_fast/inference.pdmodel and /dev/null differ diff --git a/backend/models/V5/ch_det/fs_manifest.csv b/backend/models/V5/ch_det/fs_manifest.csv new file mode 100644 index 0000000..04bbc9b --- /dev/null +++ b/backend/models/V5/ch_det/fs_manifest.csv @@ -0,0 +1,3 @@ +filename,filesize,encoding,header +inference_1.onnx,50000000,, +inference_2.onnx,38118768,, diff --git a/backend/models/V4/ch_det/inference_2.pdiparams b/backend/models/V5/ch_det/inference_1.onnx similarity index 79% rename from backend/models/V4/ch_det/inference_2.pdiparams rename to backend/models/V5/ch_det/inference_1.onnx index a3aa060..4fce4e5 100644 Binary files a/backend/models/V4/ch_det/inference_2.pdiparams and b/backend/models/V5/ch_det/inference_1.onnx differ diff --git a/backend/models/V4/ch_det/inference_1.pdiparams b/backend/models/V5/ch_det/inference_2.onnx similarity index 66% rename from backend/models/V4/ch_det/inference_1.pdiparams rename to backend/models/V5/ch_det/inference_2.onnx index 322c93d..e0c26da 100644 Binary files a/backend/models/V4/ch_det/inference_1.pdiparams and b/backend/models/V5/ch_det/inference_2.onnx differ diff --git a/backend/models/V5/ch_det_fast/inference.onnx b/backend/models/V5/ch_det_fast/inference.onnx new file mode 100644 index 0000000..96c2b33 Binary files /dev/null and b/backend/models/V5/ch_det_fast/inference.onnx differ diff --git a/backend/tools/common_tools.py b/backend/tools/common_tools.py index 9e74240..1cd1a71 100644 --- a/backend/tools/common_tools.py +++ b/backend/tools/common_tools.py @@ -37,9 +37,11 @@ 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): +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) def get_readable_path(path): diff --git a/backend/tools/hardware_accelerator.py b/backend/tools/hardware_accelerator.py index 8cbd666..5cc0e67 100644 --- a/backend/tools/hardware_accelerator.py +++ b/backend/tools/hardware_accelerator.py @@ -21,6 +21,7 @@ class HardwareAccelerator: def __init__(self): self.__cuda = False self.__dml = False + self.__mps = False self.__onnx_providers = [] self.__enabled = True self.__device = None @@ -28,6 +29,7 @@ class HardwareAccelerator: def initialize(self): self.check_directml_available() self.check_cuda_available() + self.check_mps_available() self.load_onnx_providers() def check_directml_available(self): @@ -36,6 +38,9 @@ class HardwareAccelerator: def check_cuda_available(self): self.__cuda = torch.cuda.is_available() + def check_mps_available(self): + self.__mps = torch.backends.mps.is_available() and torch.backends.mps.is_built() + def load_onnx_providers(self): try: import onnxruntime as ort @@ -65,7 +70,7 @@ class HardwareAccelerator: def has_accelerator(self): if not self.__enabled: return False - return self.__cuda or self.__dml or len(self.__onnx_providers) > 0 + return self.__cuda or self.__dml or self.__mps or len(self.__onnx_providers) > 0 @property def accelerator_name(self): @@ -75,6 +80,8 @@ class HardwareAccelerator: return "DirectML" if self.__cuda: return "GPU" + if self.__mps: + return "MPS" elif len(self.__onnx_providers) > 0: return ", ".join(self.__onnx_providers) else: @@ -83,7 +90,7 @@ class HardwareAccelerator: @property def onnx_providers(self): if not self.__enabled: - return [] + return ["CPUExecutionProvider"] return self.__onnx_providers def has_cuda(self): @@ -91,6 +98,11 @@ class HardwareAccelerator: return False return self.__cuda + def has_mps(self): + if not self.__enabled: + return False + return self.__mps + def set_enabled(self, enable): self.__enabled = enable @@ -117,4 +129,6 @@ class HardwareAccelerator: self.__dml = False if self.__cuda: return torch.device("cuda:0") + if self.__mps: + return torch.device("mps") return torch.device("cpu") \ No newline at end of file diff --git a/backend/tools/model_config.py b/backend/tools/model_config.py index 641cf1f..5ee43c9 100644 --- a/backend/tools/model_config.py +++ b/backend/tools/model_config.py @@ -10,54 +10,13 @@ class ModelConfig: self.STTN_DET_MODEL_PATH = os.path.join(BASE_DIR, 'models', 'sttn-det', 'sttn.pth') self.PROPAINTER_MODEL_DIR = os.path.join(BASE_DIR,'models', 'propainter') if config.subtitleDetectMode.value == SubtitleDetectMode.Fast: - self.DET_MODEL_DIR = os.path.join(BASE_DIR,'models', 'V4', 'ch_det_fast') + self.DET_MODEL_DIR = os.path.join(BASE_DIR,'models', 'V5', 'ch_det_fast') elif config.subtitleDetectMode.value == SubtitleDetectMode.Accurate: - self.DET_MODEL_DIR = os.path.join(BASE_DIR, 'models', 'V4', 'ch_det') + self.DET_MODEL_DIR = os.path.join(BASE_DIR, 'models', 'V5', 'ch_det') else: raise ValueError(f"Invalid subtitle detect mode: {config.subtitleDetectMode.value}") merge_big_file_if_not_exists(self.LAMA_MODEL_DIR, 'bit-lama.pt') merge_big_file_if_not_exists(self.PROPAINTER_MODEL_DIR, 'ProPainter.pth') - merge_big_file_if_not_exists(self.DET_MODEL_DIR, 'inference.pdiparams') - - def convertToOnnxModelIfNeeded(self, model_dir, model_filename="inference.pdmodel", params_filename="inference.pdiparams", opset_version=14): - """Converts a Paddle model to ONNX if ONNX providers are available and the model does not already exist.""" - - onnx_model_path = os.path.join(model_dir, "model.onnx") - - if os.path.exists(onnx_model_path): - print(f"ONNX model already exists: {onnx_model_path}. Skipping conversion.") - return onnx_model_path - - print(f"Converting Paddle model {model_dir} to ONNX...") - model_file = os.path.join(model_dir, model_filename) - params_file = os.path.join(model_dir, params_filename) if params_filename else "" - - try: - import paddle2onnx - # Ensure the target directory exists - os.makedirs(os.path.dirname(onnx_model_path), exist_ok=True) - - # Convert and save the model - onnx_model = paddle2onnx.export( - model_filename=model_file, - params_filename=params_file, - save_file=onnx_model_path, - opset_version=opset_version, - auto_upgrade_opset=True, - verbose=True, - enable_onnx_checker=True, - enable_experimental_op=True, - enable_optimize=True, - custom_op_info={}, - deploy_backend="onnxruntime", - calibration_file="calibration.cache", - external_file=os.path.join(model_dir, "external_data"), - export_fp16_model=False, - ) - - print(f"Conversion successful. ONNX model saved to: {onnx_model_path}") - return onnx_model_path - except Exception as e: - print(f"Error during conversion: {e}") - return model_dir + merge_big_file_if_not_exists(self.DET_MODEL_DIR, 'inference.onnx') + \ No newline at end of file diff --git a/backend/tools/subtitle_detect.py b/backend/tools/subtitle_detect.py index 46b28ee..4e91a3b 100644 --- a/backend/tools/subtitle_detect.py +++ b/backend/tools/subtitle_detect.py @@ -1,3 +1,4 @@ +import os import sys from functools import cached_property @@ -33,8 +34,8 @@ class SubtitleDetect: parser = utility.init_args() args = parser.parse_args([]) args.det_algorithm = 'DB' - args.det_model_dir = model_config.convertToOnnxModelIfNeeded(model_config.DET_MODEL_DIR) if len(onnx_providers) > 0 else model_config.DET_MODEL_DIR - args.use_gpu=hardware_accelerator.has_cuda() + args.det_model_dir = os.path.join(model_config.DET_MODEL_DIR, 'inference.onnx') if len(onnx_providers) > 0 else model_config.DET_MODEL_DIR + args.use_gpu=False args.use_onnx=len(onnx_providers) > 0 args.onnx_providers=onnx_providers return TextDetector(args) diff --git a/requirements.txt b/requirements.txt index 5baeba9..590fdbe 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,9 +18,8 @@ protobuf==6.30.2 av==14.3.0 einops==0.8.1 paddleocr==2.10.0 -paddle2onnx==1.3.1 onnxruntime-gpu==1.20.1; sys_platform == 'linux' # do not upgrade, windows 10/11 compatable issues, check hardware_acclerator.py:100 onnxruntime-directml==1.20.1; sys_platform == 'win32' -onnxruntime-coreml==1.13.1; sys_platform == 'darwin' +onnxruntime==1.22.0; sys_platform == 'darwin' je-showinfilemanager==1.1.6a4 \ No newline at end of file