packaging/watchdog.spec
Rama main · réplica de lectura del repositorio original.
"""
PyInstaller spec for the STT thin bootstrapper.
This builds a tiny (~10-20 MB) launcher from stt/watchdog.py only. No ML libraries
are bundled: on first run the bootstrapper provisions a local venv (via uv),
clones the app source, and installs dependencies + ffmpeg on the user machine.
The STT server then runs as a real script from that venv.
Build (from the repo root):
pyinstaller packaging/watchdog.spec
Or via build.py:
python packaging/build.py
"""
import sys
import os
block_cipher = None
IS_WINDOWS = sys.platform == "win32"
IS_MACOS = sys.platform == "darwin"
# Anchor all inputs to the repo root (parent of this spec's dir) so the build
# works regardless of the invoking cwd. Icons are generated into the root by
# make_icon.py; dist/ and the build workdir land in the invoking cwd as before.
ROOT = os.path.abspath(os.path.join(SPECPATH, "..")) # noqa: F821 (SPECPATH is a PyInstaller global)
_icon_file = os.path.join(ROOT, "icon.icns" if IS_MACOS else "icon.ico")
_icon = _icon_file if os.path.exists(_icon_file) else None
# Bundle version for the .app's Info.plist so macOS ("About STT", Finder Get Info)
# shows the real version instead of PyInstaller's default 0.0.0. Read from the
# git-managed VERSION file that's also bundled as runtime data.
try:
with open(os.path.join(ROOT, "VERSION")) as _vf:
_bundle_version = _vf.read().strip() or "0.0.0"
except OSError:
_bundle_version = "0.0.0"
a = Analysis(
[os.path.join(ROOT, "stt", "watchdog.py")],
pathex=[ROOT],
binaries=[],
datas=[
(os.path.join(ROOT, "VERSION"), "."),
] + ([(_icon_file, ".")] if os.path.exists(_icon_file) else []),
# Bootstrapper needs stdlib + tkinter (setup GUI) + certifi (TLS) +
# sentry_sdk (so first-run provisioning failures are reported — the venv
# that normally provides the SDK doesn't exist yet during setup).
# Everything else arrives via `git clone` + `uv pip install` on first run.
hiddenimports=[
"tkinter", "_tkinter", "tkinter.ttk", "tkinter.scrolledtext",
"certifi",
# sentry_sdk loads its default integrations dynamically; list them so
# PyInstaller's static analysis picks them up.
"sentry_sdk",
"sentry_sdk.integrations.stdlib",
"sentry_sdk.integrations.excepthook",
"sentry_sdk.integrations.dedupe",
"sentry_sdk.integrations.atexit",
"sentry_sdk.integrations.modules",
"sentry_sdk.integrations.logging",
"sentry_sdk.integrations.threading",
"sentry_sdk.integrations.argv",
# Imported by the bootstrapper through their package path: the Sentry
# before_send scrubber, the wheels-only install policy, the Windows job
# object that binds the server's process tree, and the open-file limit
# raise that launchd's 256 default needs. All stdlib-only, which
# is what lets a frozen bootstrapper use them. Listed rather than left to
# static analysis because the bundled watchdog imports them before it
# hands off to the git checkout — a miss here is a binary that dies at
# startup, on every install, before it can reach the source that works.
"stt.crash_reports",
"stt.wheel_policy",
"stt.win_job",
"stt.fd_limit",
"stt.server_port",
"stt.owner_exec",
"stt.server_restart",
"stt.coercion",
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[
"matplotlib",
"pytest",
"IPython",
"jupyter",
"notebook",
# Guard against accidentally sweeping a dev venv's ML libs into the exe.
"torch",
"torchaudio",
"transformers",
"faster_whisper",
"whisper",
"huggingface_hub",
"numpy",
"scipy",
"librosa",
"pandas",
],
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name="STT",
debug=False,
strip=False,
upx=True,
console=not IS_WINDOWS,
disable_windowed_traceback=False,
argv_emulation=IS_MACOS,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=_icon,
)
coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name="STT",
)
if IS_MACOS:
app = BUNDLE(
coll,
name="STT.app",
icon=_icon,
bundle_identifier="com.stt.watchdog",
info_plist={
"CFBundleName": "STT",
"CFBundleDisplayName": "STT",
"CFBundleExecutable": "STT",
"CFBundleShortVersionString": _bundle_version,
"CFBundleVersion": _bundle_version,
"NSHighResolutionCapable": True,
"NSMicrophoneUsageDescription":
"STT needs microphone access for speech recognition.",
"LSUIElement": False,
},
)