From 03a2ca50c02c93f08a757507dfacb653c006213a Mon Sep 17 00:00:00 2001 From: EJClaw Date: Fri, 25 Sep 2026 23:38:34 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20PyInstaller=20=EA=B0=80=20webrtcvad=20?= =?UTF-8?q?=ED=9B=85=EC=97=90=EC=84=9C=20=EC=A3=BD=EC=96=B4=20=ED=8F=AC?= =?UTF-8?q?=ED=84=B0=EB=B8=94=20exe=20=EA=B0=80=20=EC=95=88=20=EB=82=98?= =?UTF-8?q?=EC=98=A4=EB=8D=98=20=EB=AC=B8=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Windows 포터블 빌드가 dist\LiveSub.exe 를 만들지 못했다. 원인은 pyinstaller-hooks-contrib 의 hook-webrtcvad.py 가 copy_metadata('webrtcvad') 를 부르는 것이다. 우리가 설치하는 배포 이름은 webrtcvad-wheels 라 (원본 webrtcvad 는 Windows 휠이 없어 MSVC 컴파일이 필요하다) PackageNotFoundError 가 나고, PyInstaller 는 훅 import 실패를 ImportErrorWhenRunningHook 으로 올려 빌드를 통째로 중단한다. packaging/pyinstaller-hooks/hook-webrtcvad.py 로 같은 이름의 훅을 덮어써 실제 배포 이름으로 메타데이터를 수집한다. spec 의 hookspath 에 등록했으므로 build-portable.ps1, .gitea 워크플로, VM 자체 검증이 모두 같은 경로를 탄다. 리눅스에서 최소 재현으로 확인: 훅 없이는 같은 ImportErrorWhenRunningHook, 훅을 넣으면 "Processing standard module hook ... from packaging/pyinstaller-hooks" 로 우리 훅이 선택되고 빌드 성공, 만들어진 바이너리에서 webrtcvad.Vad(2) 생성까지 통과. --- packaging/livesub.spec | 3 ++- packaging/pyinstaller-hooks/hook-webrtcvad.py | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 packaging/pyinstaller-hooks/hook-webrtcvad.py diff --git a/packaging/livesub.spec b/packaging/livesub.spec index 5d26e2f..6aa9609 100644 --- a/packaging/livesub.spec +++ b/packaging/livesub.spec @@ -72,7 +72,8 @@ a = Analysis( # noqa: F821 binaries=binaries, datas=datas, hiddenimports=hiddenimports, - hookspath=[], + # contrib 훅이 빌드를 중단시키는 것을 덮어쓴다 (hook-webrtcvad.py 주석 참고). + hookspath=[str(ROOT / "packaging" / "pyinstaller-hooks")], runtime_hooks=[], excludes=excludes, noarchive=False, diff --git a/packaging/pyinstaller-hooks/hook-webrtcvad.py b/packaging/pyinstaller-hooks/hook-webrtcvad.py new file mode 100644 index 0000000..d4b63f8 --- /dev/null +++ b/packaging/pyinstaller-hooks/hook-webrtcvad.py @@ -0,0 +1,25 @@ +"""webrtcvad 훅 재정의 — contrib 훅이 배포 이름을 찾지 못해 빌드를 중단시킨다. + +우리가 설치하는 건 `webrtcvad-wheels` 다. 원본 `webrtcvad` 는 Windows 용 휠을 +올리지 않아서 MSVC 컴파일이 필요하기 때문이다. import 이름(`webrtcvad`)은 같지만 +**배포 이름이 다르다.** + +pyinstaller-hooks-contrib 의 `hook-webrtcvad.py` 는 `copy_metadata('webrtcvad')` 를 +부른다. 배포 이름이 없으니 `PackageNotFoundError` 가 나고, PyInstaller 는 훅 모듈 +import 실패를 `ImportErrorWhenRunningHook` 으로 올려 **빌드를 통째로 중단한다.** +Windows 포터블 빌드가 정확히 여기서 죽어 dist\\LiveSub.exe 가 안 나왔다. + +hookspath 의 훅이 contrib 훅보다 먼저 검색되므로 같은 파일명으로 덮어쓴다. +메타데이터를 실제 배포 이름으로 수집하고, 둘 다 없으면 그냥 넘어간다 — +webrtcvad 런타임은 importlib.metadata 를 읽지 않으므로 없어도 동작한다. +""" + +from PyInstaller.utils.hooks import copy_metadata + +datas = [] +for dist in ("webrtcvad-wheels", "webrtcvad"): + try: + datas = copy_metadata(dist) + break + except Exception: # noqa: BLE001 - 배포 이름이 없을 때만 다음 후보로 넘어간다 + continue