Unverified Commit 6c1f9ae8 authored by dmMaze's avatar dmMaze Committed by GitHub
Browse files

Merge pull request #217 from hyrulelinks/dev

Create launch.spec for building macOS standalone app via pyinstaller
parents 62f1d3e1 5c67d722
Loading
Loading
Loading
Loading
+77 −18
Original line number Diff line number Diff line
@@ -55,29 +55,88 @@ python ballontranslator

如果要使用Sugoi翻译器(仅日译英), 下载[离线模型](https://drive.google.com/drive/folders/1KnDlfUM9zbnYFTo6iCbnBaBKabXfnVJm), 将 "sugoi_translator" 移入BallonsTranslator/ballontranslator/data/models.  

### Apple Silicon Mac 本地构建.app应用
### 构建macOS应用(本方法兼容intel和apple silicon芯片)
![录屏2023-09-11 14 26 49](https://github.com/hyrulelinks/BallonsTranslator/assets/134026642/647c0fa0-ed37-49d6-bbf4-8a8697bc873e)

#### 1、准备工作
-[MEGA](https://mega.nz/folder/gmhmACoD#dkVlZ2nphOkU5-2ACb5dKw "MEGA")下载`libs``models`

> 📌截止2023年9月11日Google Drive资源尚未更新到最新,因此不要从Google Drive下载`libs`和`models`。
<img width="1268" alt="截屏2023-09-08 13 44 55_7g32SMgxIf" src="https://github.com/dmMaze/BallonsTranslator/assets/134026642/40fbb9b8-a788-4a6e-8e69-0248abaee21a">

-  下载`libopencv_world.4.4.0.dylib``libpatchmatch_inpaint.dylib`

> 📌下面的压缩包中的`dylib`均为`fat`文件,同时兼容intel芯片和apple芯片的Mac设备

[libopencv_world.4.4.0.dylib.zip](https://github.com/dmMaze/BallonsTranslator/files/12571658/libopencv_world.4.4.0.dylib.zip)

[libpatchmatch_inpaint.dylib.zip](https://github.com/dmMaze/BallonsTranslator/files/12571660/libpatchmatch_inpaint.dylib.zip)

-  将下载的资源全部放入名为`data`文件夹,最后的目录树结构应该如下所示:

```
data
├── libopencv_world.4.4.0.dylib
├── libpatchmatch_inpaint.dylib
├── libs
│   └── patchmatch_inpaint.dll
└── models
    ├── aot_inpainter.ckpt
    ├── comictextdetector.pt
    ├── comictextdetector.pt.onnx
    ├── lama_mpe.ckpt
    ├── manga-ocr-base
    │   ├── README.md
    │   ├── config.json
    │   ├── preprocessor_config.json
    │   ├── pytorch_model.bin
    │   ├── special_tokens_map.json
    │   ├── tokenizer_config.json
    │   └── vocab.txt
    ├── mit32px_ocr.ckpt
    ├── mit48pxctc_ocr.ckpt
    └── pkuseg
        ├── postag
        │   ├── features.pkl
        │   └── weights.npz
        ├── postag.zip
        └── spacy_ontonotes
            ├── features.msgpack
            └── weights.npz

7 directories, 23 files
```
# 安装Python 3.9.13虚拟环境
brew install pyenv mecab
env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install 3.9.13
pyenv global 3.9.13
python3 -m venv ballonstranslator
source ballonstranslator/bin/activate

# 克隆仓库
git clone https://github.com/dmMaze/BallonsTranslator.git
cd BallonsTranslator
-  安装pyenv命令行工具,这是用于管理Python版本的工具
```
# 通过Homebrew途径安装
brew install pyenv

# 通过官方自动脚本途径安装
curl https://pyenv.run | bash

# 安装完后需要设置shell环境
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
```

# 安装依赖
pip3 install -r requirements_macOS.txt

# 打包应用
cd ballontranslator
sudo pyinstaller __main__.spec
#### 2、构建应用
```
# 进入`data`工作目录
cd data

# 克隆仓库`dev`分支
git clone -b dev https://github.com/dmMaze/BallonsTranslator.git

# 进入`BallonsTranslator`工作目录
cd BallonsTranslator

# 打包好的`BallonsTranslator.app`在`dist`文件夹下
# 需要注意的是,现在的应用还无法使用,需要到 [MEGA](https://mega.nz/folder/gmhmACoD#dkVlZ2nphOkU5-2ACb5dKw) 或者 [Google Drive](https://drive.google.com/drive/folders/1uElIYRLNakJj-YS0Kd3r3HE-wzeEvrWd?usp=sharing) 下载`data`并覆盖到`BallonsTranslator.app/Contents/Resources/data`, 覆盖的时候选择“合并”,覆盖完成后应用最终打包完整,开箱即用,将应用拖到macOS的应用程序文件夹即可,不需要再配置Python环境。
# 运行构建脚本,运行到pyinstaller环节会要求输入开机密码,输入密码后按下回车即可
sh build-macos-app.sh
```
> 📌打包好的应用在`./data/BallonsTranslator/dist/BallonsTranslator.app`,将应用拖到macOS的应用程序文件夹即完成安装,开箱即用,不需要另外配置Python环境。

## 一键翻译
**建议在命令行终端下运行程序**, 首次运行请先配置好源语言/目标语言, 打开一个带图片的文件夹, 点击Run等待翻译完成  
+76 −30
Original line number Diff line number Diff line
@@ -61,47 +61,93 @@ python ballontranslator
```
For Linux or MacOS users, see [this script](ballontranslator/scripts/download_models.sh) and run to download ALL models

## Apple Silicon native build .app application

<details closed>
<summary>Instructions</summary>
<br>

Install python 3.9.13 virtual environment
```python
brew install pyenv mecab
env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install 3.9.13
pyenv global 3.9.13
python3 -m venv ballonstranslator
source ballonstranslator/bin/activate
### Build macOS application (compatible with both intel and apple silicon chips)
![录屏2023-09-11 14 26 49](https://github.com/hyrulelinks/BallonsTranslator/assets/134026642/647c0fa0-ed37-49d6-bbf4-8a8697bc873e)

#### 1. Preparation
-   Download libs and models from [MEGA](https://mega.nz/folder/gmhmACoD#dkVlZ2nphOkU5-2ACb5dKw "MEGA")

> 📌As of September 11, 2023, Google Drive resources have not been updated to the latest version, so do not download libs and models from Google Drive.
> 
<img width="1268" alt="截屏2023-09-08 13 44 55_7g32SMgxIf" src="https://github.com/dmMaze/BallonsTranslator/assets/134026642/40fbb9b8-a788-4a6e-8e69-0248abaee21a">

-  Download libopencv_world.4.4.0.dylib and libpatchmatch_inpaint.dylib.

> 📌The dylib files in the compressed package below are fat files, compatible with both intel and apple silicon chips for Mac devices.

[libopencv_world.4.4.0.dylib.zip](https://github.com/dmMaze/BallonsTranslator/files/12571658/libopencv_world.4.4.0.dylib.zip)

[libpatchmatch_inpaint.dylib.zip](https://github.com/dmMaze/BallonsTranslator/files/12571660/libpatchmatch_inpaint.dylib.zip)

-  Put all the downloaded resources into a folder called data, the final directory tree structure should look like:

```
data
├── libopencv_world.4.4.0.dylib
├── libpatchmatch_inpaint.dylib
├── libs
│   └── patchmatch_inpaint.dll
└── models
    ├── aot_inpainter.ckpt
    ├── comictextdetector.pt
    ├── comictextdetector.pt.onnx
    ├── lama_mpe.ckpt
    ├── manga-ocr-base
    │   ├── README.md
    │   ├── config.json
    │   ├── preprocessor_config.json
    │   ├── pytorch_model.bin
    │   ├── special_tokens_map.json
    │   ├── tokenizer_config.json
    │   └── vocab.txt
    ├── mit32px_ocr.ckpt
    ├── mit48pxctc_ocr.ckpt
    └── pkuseg
        ├── postag
        │   ├── features.pkl
        │   └── weights.npz
        ├── postag.zip
        └── spacy_ontonotes
            ├── features.msgpack
            └── weights.npz

7 directories, 23 files
```

Clone the repository
```bash
git clone https://github.com/dmMaze/BallonsTranslator.git
cd BallonsTranslator
-  Install pyenv command line tool for managing Python versions. Recommend installing via Homebrew.
```
# Install via Homebrew
brew install pyenv

Install the dependencies
```bash
pip3 install -r requirements_macOS.txt
# Install via official script
curl https://pyenv.run | bash

# Set shell environment after install
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.zshrc
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(pyenv init -)"' >> ~/.zshrc
```

Package the application
```bash
cd ballontranslator
sudo pyinstaller __main__.spec

#### 2、Build the application
```
# Enter the `data` working directory
cd data

The packaged `BallonsTranslator.app` is in the `dist` folder
Note that the app is not functional yet, you need to go to [MEGA](https://mega.nz/folder/gmhmACoD#dkVlZ2nphOkU5-2ACb5dKw) or [Google Drive](https://drive.google.com/drive/folders/1uElIYRLNakJj-YS0Kd3r3HE-wzeEvrWd?usp=sharing), download `data` and overwrite it to `BallonsTranslator.app/Contents/Resources/data`.
When overwriting select "``Merge``, after the overwrite is done, the application is finally packaged and complete, out of the box, just drag the application to the macOS application folder, no need to configure the Python environment again.
Or see [this script](ballontranslator/scripts/download_models.sh)
# Clone the `dev` branch of the repo
git clone -b dev https://github.com/dmMaze/BallonsTranslator.git

</details>
# Enter the `BallonsTranslator` working directory
cd BallonsTranslator

# Run the build script, will ask for password at pyinstaller step, enter password and press enter
sh build-macos-app.sh
```
> 📌The packaged app is at ./data/BallonsTranslator/dist/BallonsTranslator.app, drag the app to macOS application folder to install. Ready to use out of box without extra Python config.


</details>

To use Sugoi translator(Japanese-English only), download [offline model](https://drive.google.com/drive/folders/1KnDlfUM9zbnYFTo6iCbnBaBKabXfnVJm), move "sugoi_translator" into the BallonsTranslator/ballontranslator/data/models.  

# Usage

build-macos-app.sh

0 → 100644
+29 −0
Original line number Diff line number Diff line
# Install Python 3.11.5 via pyenv
if command -v pyenv >/dev/null 2>&1; then
  pyenv install '3.11.5'
else
  echo "pyenv is not installed"
fi

# Activate Python 3.11.5 in global environment
pyenv global '3.11.5'

# Create and activate Python 3.11.5 virtual environment
python -m venv 'venv'
source 'venv/bin/activate'

# Install dependencies
pip install -r requirements.txt
pip install pyinstaller

# Copy required directories to data
ditto ../libs data/libs -V
ditto ../models data/models -V

# Comment lines 213-229 of launch.py
cp launch.py launch.py.bak # backup launch.py
sed -i '' '213,229s|^| \#|' launch.py # comment specfied lines
sed -n '213,229p' launch.py # check if comment is successful

# Build macOS app via pyinstaller
sudo pyinstaller launch.spec

icons/icon.icns

0 → 100644
+483 KiB

File added.

No diff preview for this file type.

launch.spec

0 → 100644
+199 −0
Original line number Diff line number Diff line
# 导入模块
import os
import sys
from PyInstaller.utils.hooks import collect_data_files
import subprocess

# 获取提交哈希值
commit_hash = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']).decode('utf-8').strip()  

# 构造带提交哈希值的版本号
version = "1.3.35.dev." + commit_hash

block_cipher = None


a = Analysis([
    'launch.py',
    'modules/base.py',
    'modules/inpaint/aot.py',
    'modules/inpaint/ffc.py',
    'modules/inpaint/lama.py',
    'modules/inpaint/patch_match.py',
    'modules/ocr/macos_ocr.py',
    'modules/ocr/manga_ocr.py',
    'modules/ocr/mit48px_ctc.py',
    'modules/ocr/model_32px.py',
    'modules/ocr/windows_ocr.py',
    'modules/textdetector/db_utils.py',
    'modules/textdetector/textblock.py',
    'modules/textdetector/ctd/basemodel.py',
    'modules/textdetector/ctd/inference.py',
    'modules/textdetector/ctd/textmask.py',
    'modules/textdetector/yolov5/common.py',
    'modules/textdetector/yolov5/yolo.py',
    'modules/textdetector/yolov5/yolov5_utils.py',
    'modules/translators/base.py',
    'modules/translators/constants.py',
    'modules/translators/exceptions.py',
    'modules/translators/hooks.py',
    'modules/translators/trans_baidu.py',
    'modules/translators/trans_caiyun.py',
    'modules/translators/trans_chatgpt.py',
    'modules/translators/trans_deepl.py',
    'modules/translators/trans_deeplx.py',
    'modules/translators/trans_google.py',
    'modules/translators/trans_papago.py',
    'modules/translators/trans_sugoi.py',
    'modules/translators/trans_yandex.py',
    'scripts/svgscript.py',
    'scripts/update_translation.py',
    'ui/canvas.py',
    'ui/combobox.py',
    'ui/config.py',
    'ui/configpanel.py',
    'ui/constants.py',
    'ui/cursor.py',
    'ui/dlconfig_parse_widgets.py',
    'ui/drawing_commands.py',
    'ui/drawingpanel.py',
    'ui/fontformat_commands.py',
    'ui/fontformatpanel.py',
    'ui/funcmaps.py',
    'ui/global_search_widget.py',
    'ui/image_edit.py',
    'ui/imgtrans_proj.py',
    'ui/io_thread.py',
    'ui/keywordsubwidget.py',
    'ui/mainwindow.py',
    'ui/mainwindowbars.py',
    'ui/misc.py',
    'ui/module_manager.py',
    'ui/page_search_widget.py',
    'ui/preset_widget.py',
    'ui/scene_textlayout.py',
    'ui/scenetext_manager.py',
    'ui/shared_widget.py',
    'ui/stylewidgets.py',
    'ui/text_graphical_effect.py',
    'ui/textedit_area.py',
    'ui/textedit_commands.py',
    'ui/texteditshapecontrol.py',
    'ui/textitem.py',
    'ui/framelesswindow/fw_qt6/mac/window_effect.py',
    'ui/framelesswindow/fw_qt6/utils/linux_utils.py',
    'ui/framelesswindow/fw_qt6/utils/mac_utils.py',
    'ui/framelesswindow/fw_qt6/utils/win32_utils.py',
    'utils/appinfo.py',
    'utils/imgproc_utils.py',
    'utils/io_utils.py',
    'utils/logger.py',
    'utils/registry.py',
    'utils/stroke_width_calculator.py',
    'utils/structures.py',
    'utils/text_layout.py',
    'utils/text_processing.py',
    'utils/textblock_mask.py',],
    pathex=[],
    binaries=[],
    datas=[
        ('config', './config'),
        ('data', './data'),
        ('doc', './doc'),
        ('icons', './icons'),
        ('modules', './modules'),
        ('scripts', './scripts'),
        ('translate', './translate'),
        ('ui', './ui'),
        ('utils', './utils'),
        ('venv/lib/python3.11/site-packages/spacy_pkuseg', './spacy_pkuseg'),
        ('venv/lib/python3.11/site-packages/torchvision', './torchvision'),
        ],
    hiddenimports=[
        'PyQt6',
        'numpy',
        'urllib3',
        'jaconv',
        'torch',
        'torchvision',
        'transformers',
        'fugashi',
        'unidic_lite',
        'tqdm',
        'shapely',
        'pyclipper',
        'einops',
        'termcolor',
        'bs4',
        'deepl',
        'qtpy',
        'sentencepiece',
        'ctranslate2',
        'docx2txt',
        'piexif',
        'keyboard',
        'requests',
        'colorama',
        'openai',
        'httpx',
        'langdetect',
        'srsly',
        ],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    win_no_prefer_redirects=False,
    win_private_assemblies=False,
    cipher=block_cipher,
    noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
    pyz,
    a.scripts,
    [],
    exclude_binaries=True,
    name='launch',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)
coll = COLLECT(
    exe,
    a.binaries,
    a.zipfiles,
    a.datas,
    strip=False,
    upx=True,
    upx_exclude=[],
    name='launch',
)
app = BUNDLE(
    coll,
    name='BallonsTranslator.app',
    icon='icons/icon.icns',
    bundle_identifier=None,
    info_plist={
        'CFBundleDisplayName': 'BallonsTranslator',
        'CFBundleName': 'BallonsTranslator',
        'CFBundlePackageType': 'APPL',
        'CFBundleSignature': 'BATR',
        'CFBundleShortVersionString': version,
        'CFBundleVersion': version,
        'CFBundleExecutable': 'launch',
        'CFBundleIconFile': 'icon.icns',
        'CFBundleIdentifier': 'dev.dmmaze.batr',
        'CFBundleInfoDictionaryVersion': '6.0',
        'LSApplicationCategoryType': 'public.app-category.graphics-design',
        'LSEnvironment': {'LANG': 'zh_CN.UTF-8'},
      }
)