diff --git a/backend/build_binary.py b/backend/build_binary.py index cf587dc2..db413b99 100644 --- a/backend/build_binary.py +++ b/backend/build_binary.py @@ -111,6 +111,12 @@ def build_server(cuda=False): # inflect uses typeguard @typechecked which calls inspect.getsource() # at import time — needs .py source files, not just .pyc bytecode '--collect-all', 'inflect', + # perth ships pretrained watermark model files (hparams.yaml, .pth.tar) + # in perth/perth_net/pretrained/ — needed by chatterbox at runtime + '--collect-all', 'perth', + # piper_phonemize ships espeak-ng-data/ (phoneme tables, language dicts) + # needed by LuxTTS for text-to-phoneme conversion + '--collect-all', 'piper_phonemize', ]) # Add CUDA-specific hidden imports diff --git a/backend/server.py b/backend/server.py index 8dd970b3..bc6a81b2 100644 --- a/backend/server.py +++ b/backend/server.py @@ -26,6 +26,20 @@ if not _is_writable(sys.stdout): if not _is_writable(sys.stderr): sys.stderr = open(os.devnull, 'w') +# PyInstaller + multiprocessing: child processes re-execute the frozen binary +# with internal arguments. freeze_support() handles this and exits early. +import multiprocessing +multiprocessing.freeze_support() + +# In frozen builds, piper_phonemize's espeak-ng C library falls back to +# /usr/share/espeak-ng-data/ which doesn't exist. Point it at the bundled +# data directory instead. +if getattr(sys, 'frozen', False): + _meipass = getattr(sys, '_MEIPASS', os.path.dirname(sys.executable)) + _espeak_data = os.path.join(_meipass, 'piper_phonemize', 'espeak-ng-data') + if os.path.isdir(_espeak_data): + os.environ.setdefault('ESPEAK_DATA_PATH', _espeak_data) + # Fast path: handle --version before any heavy imports so the Rust # version check doesn't block for 30+ seconds loading torch etc. if "--version" in sys.argv: