- build-client.bat: Use node_modules\.bin\electron-builder.cmd directly - build-all.ps1: Use direct path to electron-builder instead of npm run - setup-backend.bat: Add UTF-8 support and use python -m pip 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
322 lines
9.0 KiB
PowerShell
322 lines
9.0 KiB
PowerShell
#Requires -Version 5.1
|
||
<#
|
||
.SYNOPSIS
|
||
Meeting Assistant - Windows 一鍵打包腳本
|
||
.DESCRIPTION
|
||
在 Windows 環境下一鍵打包 Sidecar + Electron 成免安裝 exe
|
||
.EXAMPLE
|
||
.\scripts\build-all.ps1
|
||
.\scripts\build-all.ps1 -ApiUrl "http://192.168.1.100:8000/api"
|
||
.\scripts\build-all.ps1 -SkipSidecar
|
||
.\scripts\build-all.ps1 -Clean
|
||
#>
|
||
|
||
param(
|
||
[string]$ApiUrl,
|
||
[switch]$SkipSidecar,
|
||
[switch]$Clean,
|
||
[switch]$Help
|
||
)
|
||
|
||
$ErrorActionPreference = "Stop"
|
||
|
||
# 顏色輸出函數
|
||
function Write-Step { param($msg) Write-Host "[STEP] $msg" -ForegroundColor Cyan }
|
||
function Write-OK { param($msg) Write-Host "[OK] $msg" -ForegroundColor Green }
|
||
function Write-Warn { param($msg) Write-Host "[WARN] $msg" -ForegroundColor Yellow }
|
||
function Write-Err { param($msg) Write-Host "[ERROR] $msg" -ForegroundColor Red }
|
||
|
||
# 路徑設定
|
||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||
$ProjectDir = Split-Path -Parent $ScriptDir
|
||
$SidecarDir = Join-Path $ProjectDir "sidecar"
|
||
$ClientDir = Join-Path $ProjectDir "client"
|
||
$BuildDir = Join-Path $ProjectDir "build"
|
||
|
||
function Show-Banner {
|
||
Write-Host ""
|
||
Write-Host "==========================================" -ForegroundColor Cyan
|
||
Write-Host " Meeting Assistant - Windows Builder" -ForegroundColor Cyan
|
||
Write-Host " 一鍵打包 Electron + Sidecar" -ForegroundColor Cyan
|
||
Write-Host "==========================================" -ForegroundColor Cyan
|
||
Write-Host ""
|
||
}
|
||
|
||
function Show-Help {
|
||
Write-Host @"
|
||
|
||
Meeting Assistant - Windows 一鍵打包腳本
|
||
|
||
用法: .\build-all.ps1 [參數]
|
||
|
||
參數:
|
||
-ApiUrl URL 後端 API URL (預設: http://localhost:8000/api)
|
||
-SkipSidecar 跳過 Sidecar 打包(如果已經打包過)
|
||
-Clean 打包前清理所有建置目錄
|
||
-Help 顯示此幫助訊息
|
||
|
||
範例:
|
||
.\build-all.ps1 # 完整打包 (使用預設 localhost)
|
||
.\build-all.ps1 -ApiUrl "http://192.168.1.100:8000/api" # 指定後端 URL
|
||
.\build-all.ps1 -ApiUrl "https://api.example.com/api" # 使用公司伺服器
|
||
.\build-all.ps1 -Clean # 清理後打包
|
||
.\build-all.ps1 -SkipSidecar # 僅打包 Electron
|
||
|
||
"@
|
||
}
|
||
|
||
function Update-Config {
|
||
param([string]$NewApiUrl)
|
||
|
||
Write-Step "更新設定檔..."
|
||
|
||
$configPath = Join-Path $ClientDir "config.json"
|
||
|
||
if (Test-Path $configPath) {
|
||
$config = Get-Content $configPath -Raw | ConvertFrom-Json
|
||
|
||
if ($NewApiUrl) {
|
||
$config.apiBaseUrl = $NewApiUrl
|
||
Write-Host " API URL: $NewApiUrl" -ForegroundColor Gray
|
||
}
|
||
|
||
$config | ConvertTo-Json -Depth 10 | Set-Content $configPath -Encoding UTF8
|
||
Write-OK "設定檔已更新"
|
||
} else {
|
||
Write-Warn "找不到 config.json,使用預設設定"
|
||
}
|
||
}
|
||
|
||
function Test-Prerequisites {
|
||
Write-Step "檢查建置環境..."
|
||
|
||
# 檢查 Python
|
||
try {
|
||
$pyVersion = python --version 2>&1
|
||
Write-OK "Python: $pyVersion"
|
||
} catch {
|
||
Write-Err "Python 未安裝,請安裝 Python 3.10+"
|
||
exit 1
|
||
}
|
||
|
||
# 檢查 Node.js
|
||
try {
|
||
$nodeVersion = node --version 2>&1
|
||
Write-OK "Node.js: $nodeVersion"
|
||
} catch {
|
||
Write-Err "Node.js 未安裝,請安裝 Node.js 18+"
|
||
exit 1
|
||
}
|
||
|
||
# 檢查 npm
|
||
try {
|
||
$npmVersion = npm --version 2>&1
|
||
Write-OK "npm: $npmVersion"
|
||
} catch {
|
||
Write-Err "npm 未安裝"
|
||
exit 1
|
||
}
|
||
}
|
||
|
||
function Clear-BuildDirs {
|
||
Write-Step "清理建置目錄..."
|
||
|
||
$dirsToClean = @(
|
||
$BuildDir,
|
||
(Join-Path $ClientDir "dist"),
|
||
(Join-Path $SidecarDir "dist"),
|
||
(Join-Path $SidecarDir "build")
|
||
)
|
||
|
||
foreach ($dir in $dirsToClean) {
|
||
if (Test-Path $dir) {
|
||
Remove-Item -Recurse -Force $dir
|
||
Write-Host " 已刪除: $dir" -ForegroundColor Gray
|
||
}
|
||
}
|
||
|
||
# 刪除 spec 檔案
|
||
Get-ChildItem -Path $SidecarDir -Filter "*.spec" | Remove-Item -Force
|
||
|
||
Write-OK "清理完成"
|
||
}
|
||
|
||
function Build-Sidecar {
|
||
Write-Step "打包 Sidecar (Python → exe)..."
|
||
Write-Host " 這可能需要 5-10 分鐘..." -ForegroundColor Gray
|
||
|
||
Push-Location $SidecarDir
|
||
|
||
try {
|
||
# 建立/啟動虛擬環境
|
||
if (-not (Test-Path "venv")) {
|
||
Write-Host " 建立虛擬環境..." -ForegroundColor Gray
|
||
python -m venv venv
|
||
}
|
||
|
||
# 啟動虛擬環境並安裝依賴
|
||
& ".\venv\Scripts\Activate.ps1"
|
||
|
||
Write-Host " 安裝依賴..." -ForegroundColor Gray
|
||
pip install --upgrade pip -q
|
||
pip install -r requirements.txt -q
|
||
pip install pyinstaller -q
|
||
|
||
# 建立 dist 目錄
|
||
if (-not (Test-Path "dist")) {
|
||
New-Item -ItemType Directory -Path "dist" | Out-Null
|
||
}
|
||
|
||
Write-Host " 執行 PyInstaller..." -ForegroundColor Gray
|
||
|
||
# PyInstaller 打包
|
||
pyinstaller `
|
||
--onedir `
|
||
--name transcriber `
|
||
--distpath dist `
|
||
--workpath build `
|
||
--noconfirm `
|
||
--clean `
|
||
--console `
|
||
--hidden-import=faster_whisper `
|
||
--hidden-import=ctranslate2 `
|
||
--hidden-import=huggingface_hub `
|
||
--hidden-import=tokenizers `
|
||
--hidden-import=onnxruntime `
|
||
--hidden-import=opencc `
|
||
--hidden-import=pydub `
|
||
--hidden-import=numpy `
|
||
--hidden-import=av `
|
||
--collect-data=onnxruntime `
|
||
--collect-data=faster_whisper `
|
||
transcriber.py
|
||
|
||
if (Test-Path "dist\transcriber\transcriber.exe") {
|
||
Write-OK "Sidecar 打包完成"
|
||
} else {
|
||
Write-Err "Sidecar 打包失敗"
|
||
exit 1
|
||
}
|
||
}
|
||
finally {
|
||
Pop-Location
|
||
}
|
||
}
|
||
|
||
function Build-Electron {
|
||
Write-Step "打包 Electron 應用..."
|
||
|
||
Push-Location $ClientDir
|
||
|
||
try {
|
||
# 檢查 Sidecar 是否存在
|
||
$sidecarExe = Join-Path $SidecarDir "dist\transcriber\transcriber.exe"
|
||
if (-not (Test-Path $sidecarExe)) {
|
||
Write-Err "找不到 Sidecar: $sidecarExe"
|
||
Write-Warn "請先執行完整打包或移除 -SkipSidecar 參數"
|
||
exit 1
|
||
}
|
||
|
||
# 總是執行 npm install 確保依賴完整
|
||
Write-Host " 安裝 npm 依賴..." -ForegroundColor Gray
|
||
npm install
|
||
if ($LASTEXITCODE -ne 0) {
|
||
Write-Err "npm install 失敗"
|
||
exit 1
|
||
}
|
||
|
||
# 確認 electron-builder 已安裝
|
||
$electronBuilderPath = Join-Path $ClientDir "node_modules\.bin\electron-builder.cmd"
|
||
if (-not (Test-Path $electronBuilderPath)) {
|
||
Write-Err "electron-builder 未安裝"
|
||
Write-Warn "請確認 package.json 中的 devDependencies 包含 electron-builder"
|
||
exit 1
|
||
}
|
||
|
||
# 建立 .env 如果不存在
|
||
if (-not (Test-Path ".env") -and (Test-Path ".env.example")) {
|
||
Copy-Item ".env.example" ".env"
|
||
Write-Warn "已建立 .env,請確認設定"
|
||
}
|
||
|
||
Write-Host " 執行 electron-builder..." -ForegroundColor Gray
|
||
|
||
# 直接執行 node_modules 中的 electron-builder
|
||
& $electronBuilderPath --win
|
||
|
||
if ($LASTEXITCODE -ne 0) {
|
||
Write-Err "electron-builder 執行失敗"
|
||
exit 1
|
||
}
|
||
|
||
if (Test-Path "dist\*.exe") {
|
||
Write-OK "Electron 打包完成"
|
||
} else {
|
||
Write-Err "Electron 打包失敗 - dist 目錄中找不到 exe 檔案"
|
||
exit 1
|
||
}
|
||
}
|
||
finally {
|
||
Pop-Location
|
||
}
|
||
}
|
||
|
||
function Copy-Output {
|
||
Write-Step "整合輸出..."
|
||
|
||
if (-not (Test-Path $BuildDir)) {
|
||
New-Item -ItemType Directory -Path $BuildDir | Out-Null
|
||
}
|
||
|
||
# 複製 exe 檔案
|
||
$exeFiles = Get-ChildItem -Path (Join-Path $ClientDir "dist") -Filter "*.exe"
|
||
foreach ($file in $exeFiles) {
|
||
Copy-Item $file.FullName -Destination $BuildDir
|
||
Write-Host " 複製: $($file.Name)" -ForegroundColor Gray
|
||
}
|
||
|
||
Write-Host ""
|
||
Write-Host "==========================================" -ForegroundColor Cyan
|
||
Write-Host " 打包完成!" -ForegroundColor Green
|
||
Write-Host "==========================================" -ForegroundColor Cyan
|
||
Write-Host ""
|
||
Write-Host " 輸出目錄: $BuildDir" -ForegroundColor White
|
||
Write-Host ""
|
||
|
||
# 列出輸出檔案
|
||
Get-ChildItem -Path $BuildDir | ForEach-Object {
|
||
$size = [math]::Round($_.Length / 1MB, 2)
|
||
Write-Host " $($_.Name) ($size MB)" -ForegroundColor Gray
|
||
}
|
||
|
||
Write-Host ""
|
||
Write-Host " 使用說明:" -ForegroundColor Yellow
|
||
Write-Host " 直接執行 .exe 檔案即可,無需安裝" -ForegroundColor Gray
|
||
Write-Host ""
|
||
}
|
||
|
||
# 主程式
|
||
if ($Help) {
|
||
Show-Help
|
||
exit 0
|
||
}
|
||
|
||
Show-Banner
|
||
Test-Prerequisites
|
||
|
||
if ($Clean) {
|
||
Clear-BuildDirs
|
||
}
|
||
|
||
# Update config.json if API URL is specified
|
||
if ($ApiUrl) {
|
||
Update-Config -NewApiUrl $ApiUrl
|
||
}
|
||
|
||
if (-not $SkipSidecar) {
|
||
Build-Sidecar
|
||
}
|
||
|
||
Build-Electron
|
||
Copy-Output
|