97 lines
3.0 KiB
Python
97 lines
3.0 KiB
Python
# -*- mode: python ; coding: utf-8 -*-
|
|
# WhisperVoice - Single-file portable bootstrapper
|
|
#
|
|
# This builds a TINY exe that contains only:
|
|
# - The bootstrapper (downloads Python + deps on first run)
|
|
# - The app source code (bundled as data, extracted to runtime/app/)
|
|
#
|
|
# NO heavy dependencies (torch, PySide6, etc.) are bundled.
|
|
|
|
import os
|
|
import sys
|
|
import glob
|
|
|
|
block_cipher = None
|
|
|
|
# ── Collect app source as data (goes into app_source/ inside the bundle) ──
|
|
|
|
app_datas = []
|
|
|
|
# main.py
|
|
app_datas.append(('main.py', 'app_source'))
|
|
|
|
# requirements.txt
|
|
app_datas.append(('requirements.txt', 'app_source'))
|
|
|
|
# src/**/*.py (core, ui, utils - preserving directory structure)
|
|
for py in glob.glob('src/**/*.py', recursive=True):
|
|
dest = os.path.join('app_source', os.path.dirname(py))
|
|
app_datas.append((py, dest))
|
|
|
|
# src/ui/qml/** (QML files, shaders, SVGs, fonts, qmldir)
|
|
qml_dir = os.path.join('src', 'ui', 'qml')
|
|
for pattern in ('*.qml', '*.qsb', '*.frag', '*.svg', '*.ico', '*.png',
|
|
'qmldir', 'AUTHORS.txt', 'OFL.txt'):
|
|
for f in glob.glob(os.path.join(qml_dir, pattern)):
|
|
app_datas.append((f, os.path.join('app_source', qml_dir)))
|
|
|
|
# Fonts
|
|
for f in glob.glob(os.path.join(qml_dir, 'fonts', 'ttf', '*.ttf')):
|
|
app_datas.append((f, os.path.join('app_source', qml_dir, 'fonts', 'ttf')))
|
|
|
|
# assets/
|
|
if os.path.exists(os.path.join('assets', 'icon.ico')):
|
|
app_datas.append((os.path.join('assets', 'icon.ico'), os.path.join('app_source', 'assets')))
|
|
|
|
# ── Analysis - only the bootstrapper, NO heavy imports ────────────────────
|
|
|
|
a = Analysis(
|
|
['bootstrapper.py'],
|
|
pathex=[],
|
|
binaries=[],
|
|
datas=app_datas,
|
|
hiddenimports=[],
|
|
hookspath=[],
|
|
hooksconfig={},
|
|
runtime_hooks=[],
|
|
excludes=[
|
|
# Exclude everything heavy - the bootstrapper only uses stdlib
|
|
'torch', 'numpy', 'scipy', 'PySide6', 'shiboken6',
|
|
'faster_whisper', 'ctranslate2', 'llama_cpp',
|
|
'sounddevice', 'soundfile', 'keyboard', 'pyperclip',
|
|
'psutil', 'pynvml', 'pystray', 'PIL', 'Pillow',
|
|
'darkdetect', 'huggingface_hub', 'requests',
|
|
'tqdm', 'onnxruntime', 'av',
|
|
'matplotlib', 'notebook', 'IPython',
|
|
],
|
|
win_no_prefer_redirects=False,
|
|
win_private_assemblies=False,
|
|
cipher=block_cipher,
|
|
noarchive=False,
|
|
)
|
|
|
|
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
|
|
|
# ── Single-file EXE (--onefile) ──────────────────────────────────────────
|
|
|
|
exe = EXE(
|
|
pyz,
|
|
a.scripts,
|
|
a.binaries,
|
|
a.zipfiles,
|
|
a.datas,
|
|
[],
|
|
name='WhisperVoice',
|
|
debug=False,
|
|
bootloader_ignore_signals=False,
|
|
strip=False,
|
|
upx=True,
|
|
console=False, # No console - bootstrapper allocates one when needed
|
|
disable_windowed_traceback=False,
|
|
argv_emulation=False,
|
|
target_arch=None,
|
|
codesign_identity=None,
|
|
entitlements_file=None,
|
|
icon='assets/icon.ico' if sys.platform == 'win32' else None,
|
|
)
|