213 lines
6.6 KiB
PowerShell
213 lines
6.6 KiB
PowerShell
[CmdletBinding()]
|
|
param(
|
|
[switch]$SkipInstall,
|
|
[switch]$FullTts,
|
|
[switch]$Lite,
|
|
[switch]$NoAdmin
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
$OutputEncoding = [System.Text.UTF8Encoding]::new($false)
|
|
|
|
$Root = Resolve-Path (Join-Path $PSScriptRoot "..")
|
|
$AdminRoot = Join-Path $Root "frontend\admin"
|
|
$DistRoot = Join-Path $Root "dist"
|
|
$AppDist = Join-Path $DistRoot "LiveStreaming"
|
|
$BuildRoot = Join-Path $Root "build"
|
|
$PyBuild = Join-Path $BuildRoot "pyinstaller"
|
|
|
|
function Write-Step([string]$Message) {
|
|
Write-Host ""
|
|
Write-Host "==> $Message" -ForegroundColor Cyan
|
|
}
|
|
|
|
function Invoke-Checked([string]$File, [string[]]$Arguments) {
|
|
& $File @Arguments
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "$File $($Arguments -join ' ') failed with exit code $LASTEXITCODE."
|
|
}
|
|
}
|
|
|
|
function Get-ProjectPython {
|
|
$candidates = @(
|
|
$env:LIVE_STREAMING_PYTHON,
|
|
(Join-Path $Root ".venv-tts\Scripts\python.exe"),
|
|
(Join-Path $Root ".venv\Scripts\python.exe"),
|
|
"E:\Programs\Anaconda3\envs\Live-streaming\python.exe",
|
|
"python"
|
|
) | Where-Object { $_ }
|
|
foreach ($candidate in $candidates) {
|
|
try {
|
|
$version = & $candidate -c "import sys; print(sys.version.split()[0])" 2>$null
|
|
if ($LASTEXITCODE -eq 0 -and $version) {
|
|
Write-Host "Python: $candidate ($version)"
|
|
return $candidate
|
|
}
|
|
} catch {
|
|
}
|
|
}
|
|
throw "No usable Python found. Create .venv, install Python 3.10+, or set LIVE_STREAMING_PYTHON."
|
|
}
|
|
|
|
$Python = Get-ProjectPython
|
|
$PythonPrefix = (& $Python -c "import sys; print(sys.prefix)").Trim()
|
|
if ($LASTEXITCODE -ne 0 -or -not $PythonPrefix) {
|
|
throw "Unable to resolve Python prefix from $Python."
|
|
}
|
|
$CondaBin = Join-Path $PythonPrefix "Library\bin"
|
|
if (Test-Path $CondaBin) {
|
|
$env:PATH = "$CondaBin;$env:PATH"
|
|
}
|
|
|
|
if (-not $SkipInstall) {
|
|
Write-Step "Install Python runtime/build dependencies"
|
|
Invoke-Checked $Python @("-m", "pip", "install", "-r", (Join-Path $Root "requirements.txt"))
|
|
}
|
|
|
|
Write-Step "Build Vue admin dist"
|
|
if (-not (Test-Path (Join-Path $AdminRoot "node_modules"))) {
|
|
Invoke-Checked "npm" @("--prefix", $AdminRoot, "install")
|
|
}
|
|
Invoke-Checked "npm" @("--prefix", $AdminRoot, "run", "build")
|
|
|
|
Write-Step "Prepare PyInstaller output"
|
|
|
|
# 确保没有残留进程占用 dist 目录
|
|
$killed = Get-Process -Name "LiveStreaming" -ErrorAction SilentlyContinue
|
|
if ($killed) {
|
|
$killed | Stop-Process -Force -ErrorAction SilentlyContinue
|
|
$killed | Wait-Process -Timeout 5 -ErrorAction SilentlyContinue
|
|
Start-Sleep -Seconds 2
|
|
Write-Host " Stopped LiveStreaming.exe before build"
|
|
}
|
|
|
|
function Remove-WithRetry([string]$Path) {
|
|
if (-not (Test-Path $Path)) { return }
|
|
$retries = 3
|
|
while ($retries -gt 0) {
|
|
try {
|
|
Remove-Item -LiteralPath $Path -Recurse -Force -ErrorAction Stop
|
|
return
|
|
} catch {
|
|
$retries--
|
|
if ($retries -eq 0) {
|
|
Write-Host " WARNING: Cannot remove $Path, skipping" -ForegroundColor Yellow
|
|
} else {
|
|
Write-Host " Retry remove $Path ($retries left)..." -ForegroundColor Yellow
|
|
Start-Sleep -Seconds 2
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Remove-WithRetry $AppDist
|
|
Remove-WithRetry $PyBuild
|
|
New-Item -ItemType Directory -Force -Path $DistRoot | Out-Null
|
|
New-Item -ItemType Directory -Force -Path $PyBuild | Out-Null
|
|
|
|
$excludeModules = @(
|
|
"tkinter",
|
|
"pytest",
|
|
"IPython",
|
|
"jupyter",
|
|
"notebook",
|
|
"matplotlib.tests",
|
|
"numpy.tests",
|
|
"pandas.tests",
|
|
"scipy.tests",
|
|
"torch.testing"
|
|
)
|
|
|
|
if ($Lite) {
|
|
$excludeModules += @(
|
|
"torch",
|
|
"torchaudio",
|
|
"torchvision",
|
|
"transformers",
|
|
"faster_qwen3_tts",
|
|
"dots_tts"
|
|
)
|
|
} else {
|
|
$excludeModules += @(
|
|
"torch.distributed",
|
|
"torch.utils.tensorboard",
|
|
"torchvision",
|
|
"torchaudio._internal",
|
|
"torch.utils.benchmark",
|
|
"torch.testing",
|
|
"torch.onnx",
|
|
"tensorboard",
|
|
"tensorboardX"
|
|
)
|
|
}
|
|
|
|
$pyiArgs = @(
|
|
"--noconfirm",
|
|
"--onedir",
|
|
"--name", "LiveStreaming",
|
|
"--distpath", $DistRoot,
|
|
"--workpath", $PyBuild,
|
|
"--specpath", $BuildRoot,
|
|
"--paths", (Join-Path $Root "app"),
|
|
"--hidden-import", "danmu_queue",
|
|
"--hidden-import", "music_monitor",
|
|
"--hidden-import", "tts_monitor",
|
|
"--hidden-import", "core.runtime_paths"
|
|
)
|
|
|
|
foreach ($module in $excludeModules) {
|
|
$pyiArgs += @("--exclude-module", $module)
|
|
}
|
|
|
|
$condaDlls = @("ffi.dll", "liblzma.dll", "libbz2.dll", "libexpat.dll")
|
|
if (Test-Path $CondaBin) {
|
|
foreach ($dll in $condaDlls) {
|
|
$dllPath = Join-Path $CondaBin $dll
|
|
if (Test-Path $dllPath) {
|
|
$pyiArgs += @("--add-binary", "$dllPath;.")
|
|
}
|
|
}
|
|
}
|
|
|
|
if (-not $NoAdmin) {
|
|
$pyiArgs += "--uac-admin"
|
|
}
|
|
$pyiArgs += (Join-Path $Root "app\main.py")
|
|
|
|
Write-Step "Package LiveStreaming.exe"
|
|
|
|
# PyInstaller 隔离模式与 torch DLL 冲突,设置环境变量跳过 CUDA 加载
|
|
$env:CUDA_VISIBLE_DEVICES = ""
|
|
$env:PYTORCH_NVFUSER_DISABLE = "1"
|
|
|
|
$SpecFile = Join-Path $BuildRoot "LiveStreaming.spec"
|
|
if (Test-Path $SpecFile) {
|
|
Write-Host " Reusing spec (incremental) ..."
|
|
Invoke-Checked $Python @("-m", "PyInstaller", "--noconfirm", $SpecFile)
|
|
} else {
|
|
Invoke-Checked $Python (@("-m", "PyInstaller") + $pyiArgs)
|
|
}
|
|
|
|
Write-Step "Create runtime directories"
|
|
$ExePath = Join-Path $AppDist "LiveStreaming.exe"
|
|
if (-not (Test-Path $ExePath)) {
|
|
throw "PyInstaller finished without creating $ExePath."
|
|
}
|
|
New-Item -ItemType Directory -Force -Path (Join-Path $AppDist "data") | Out-Null
|
|
New-Item -ItemType Directory -Force -Path (Join-Path $AppDist "logs") | Out-Null
|
|
Copy-Item -LiteralPath (Join-Path $Root "web") -Destination (Join-Path $AppDist "web") -Recurse -Force
|
|
Copy-Item -LiteralPath (Join-Path $Root "config") -Destination (Join-Path $AppDist "config") -Recurse -Force
|
|
Copy-Item -LiteralPath (Join-Path $Root "integrations") -Destination (Join-Path $AppDist "integrations") -Recurse -Force
|
|
Copy-Item -LiteralPath (Join-Path $Root "docs") -Destination (Join-Path $AppDist "docs") -Recurse -Force
|
|
Copy-Item -LiteralPath (Join-Path $Root "vendor") -Destination (Join-Path $AppDist "vendor") -Recurse -Force
|
|
Copy-Item -LiteralPath (Join-Path $Root "README.md") -Destination (Join-Path $AppDist "README.md") -Force
|
|
|
|
Write-Host ""
|
|
Write-Host "Build complete: $AppDist\LiveStreaming.exe" -ForegroundColor Green
|
|
if ($Lite) {
|
|
Write-Host "Lite build: TTS/GPU dependencies excluded."
|
|
} else {
|
|
Write-Host "Full build with TTS support."
|
|
}
|